Asp.net

為什麼混合 Razor Pages 和 VueJs 是一件壞事?

  • February 9, 2018

我正在嘗試使用 Razor Pages 設置一個 .NET 核心項目,並將 vueJs 包含在 Razor 頁面中以用於我的所有邏輯。

像這樣的東西:

@{
   ViewData["Title"] = "VueJs With Razor";
}
<h2>@ViewData["Title"].</h2>

<div id="app">
  <span>{{ message }}</span>
</div>

<script>
    new Vue({
       el: '#app',
       data: {
         message : 'Hello vue.js'
       }
   })
</script>

我讀過混合使用 Vue 和 Razor 頁面是一種不好的做法,應該使用 Razor OR Vue。

為什麼是這樣?

你可以這樣做。有時您必須這樣做,如果像我們一樣,您正在遷移現有的程式碼庫並且您不能一次轉換所有內容。正如 Ron C 所說,它運作良好。

如果您正在開始一個新項目,您可以選擇。偏愛 SPA 而沒有 Razor 的原因是……

  • 反應性。SPA 應用程序通常感覺(很多)更具反應性。初始渲染通常在數據到達之前從記憶體中提供。在第一次載入時,所有資源都以一個請求-響應的形式打包到達。沒有,或者更少,請求鏈。
  • 工作流程。Webpack、捆綁和熱重載都很棒。您將獲得生產版本,具有縮小、編譯 Vue 渲染函式、消除 404 樣式錯誤、擷取 js 語法錯誤。對於許多錯誤,從引入錯誤到發現錯誤的周期大大縮短。
  • SPA 世界。路由,Vuex,這確實是未來的方式。
  • 純度。Razor 和 Vue 在一天結束時會做類似的事情。如果你混合它們,你可能很難保持頭腦清醒。

混合使用 VueJs 和 Razor Pages 不一定是壞事,它可能很棒!

我將 Vue 與 razor 一起用於非 SPA 頁面,並且兩者可以很好地協同工作。我選擇通過 CDN 中的腳本標籤載入 Vue 來使用它,並且我不利用 WebPack 進行轉譯,我只是在(gasp)ES5 中編寫我的程式碼。我選擇這種方法的原因如下。

  • 使用 Razor 頁面而不是 SPA 有助於 SEO 和麵向公眾的頁面的搜尋引擎排名。
  • 直接從 CDN 載入 Vue 從學習曲線中消除了一整套以 Webpack 為中心的技術,這使得新開發人員更容易掌握系統的速度。
  • 該方法仍然為 UI 開發提供了 Vue 固有的優勢。
  • 通過與“頁面模型”保持一致,提供站點功能的程式碼在邏輯上圍繞提供該功能的後端頁面進行分組。

由於 Vue 和 Razor 可以做許多相同的事情,我對面向公眾的頁面的目標是使用 Razor 生成盡可能接近最終 html 的內容,並使用 Vue 為頁面添加響應性。這為通過解析返回的 HTML 來索引頁面的爬蟲提供了巨大的 SEO 優勢。

我意識到我對 Vue 的使用與走 SPA 和 WebPack 的路線完全不同,而且這種方法通常意味著我不能在不修改程式碼的情況下使用 3rd 方 Vue 組件。但該方法簡化了軟體架構並提供了輕量級的反應式 UI。

通過使用這種方法,可以大量利用 Razor 來生成 HTML 的初始渲染,其中包含一些包含 vue 屬性的標籤。然後在瀏覽器中載入頁面後,Vue 接管並可以以任何需要的方式重新配置該頁面。

顯然,這種方法不能滿足所有開發人員或項目的需求,但對於某些案例來說,這是一個非常好的設置。

給有興趣的人提供更多細節

由於我在站點範圍內使用 vue,因此我的全域 _layout.aspx 文件負責實例化 vue。在 vue 中實現的任何站點範圍的功能都是在此級別實現的。許多頁面都有頁面特定的 vue 功能,這被實現為該頁面上的 mixin 或該頁面載入的 js 文件中的 mixin。當 _layout.aspx 頁面實例化 Vue 時,它會使用我註冊到全域 mixin 數組的所有 mixin。(頁面將它的 mixin 推送到該全域 mixin 數組上)

我不使用 .vue 文件。任何需要的組件都直接在頁面上實現,或者如果它們需要被多個頁面使用,那麼它們將在局部視圖中實現,如下所示:

dlogViewComponent.cshtml:

   @* dlog vue component template*@
   <script type="text/x-template" id="dlogTemplate">
       <div class="dlog" v-show="dlog.visible" v-on:click="dlog.closeBoxVisible ? close() : ''">
           <div class="dlogCell">
               <div class="dlogFrame" @@click.stop="" style="max-width:400px">
                   <i class="icon icon-close-thin-custom dlogCloseIcon" v-if="dlog.closeBoxVisible" @@click="close()"></i>
                   <div class="dlogCloseIconSpace" v-if="dlog.closeBoxVisible"></div>
                   <div class="dlogInner">
                       <div class="dlogTitle" style="float:left" v-text="title"></div>
                       <div class="clear"></div>
                       <div class="dlogContent">
                           <slot></slot>
                       </div>
                   </div>
               </div>
           </div>
       </div>
   </script>

   @* Vue dlog component *@
   <script type="text/javascript">
           Vue.component('dlog', {
               template: '#dlogTemplate',
               props: {    //don't mutate these!
                   closeBoxVisible: true,
                   title: 'One'
               },
               data: function () {
                   return {
                       dlog: { //nest the data props below dlog so I can use same names as cooresponding prop
                           closeBoxVisible: (typeof this.closeBoxVisible === 'undefined') ? true : (this.closeBoxVisible == 'true'),
                           title: (typeof this.title === 'undefined') ? '' : this.title,
                           visible: false
                       }
                   }
               },
               methods: {
                   //opens the dialog
                   open: function () {
                       app.hideBusy();        //just in case, no harm if not busy
                       this.dlog.visible = true;
                       var identifyingClass = this.getIdentifyingClass();
                       Vue.nextTick(function () {
                           $("." + identifyingClass).addClass("animateIn");
                           fx.manageDlogOnly();
                       });
                   },
                   //closes the dialog
                   close: function () {
                       fx.prepDlogClose();
                       var identifyingClass = this.getIdentifyingClass();
                       this.dlog.visible = false;
                       $("." + identifyingClass).removeClass("animateIn");
                   },
                   getIdentifyingClass: function () {
                       if (this.$el.classList.length > 1) {
                           //the last class is always our identifying css class.
                           return this.$el.classList[this.$el.classList.length - 1];
                       } else {
                           throw "A dialog must have an identifying class assigned to it.";
                       }
                   }

               }
           });
   </script>

在上面,是 Vue.component(‘dlog’, … js 的一部分安裝組件並使其可用於頁面。

_layout.cshtml 頁面上的 vue 程式碼類似於下面的程式碼。通過在整個站點使用的 _layout.cshtml 上實例化 Vue,Vue 僅在站點範圍內的一個地方實例化:

_layout.cshtml:

<script type="text/javascript">
   var app = new Vue({
       el: '#appTemplate',
       mixins: mixinArray,                     //The page adds it's mixin to mixinArray before this part of the layout executes. 
       data: {
           errorMsg: ''                        //used sitewide for error messages
           //other data used sitewide
       }, 
       methods: {
           //methods that need to be available in vue sitewide, examples below:
           showBusy: function (html) {
               //functionality to show the user that the site is busy with an ajax request.
           },
           hideBusy: function () {
               //functionality to hide the busy spinner and messaging
           }
       },
       created: function () {
            //this method is particularly useful for initializing data.
       }
   });

</script>

我在這裡提供的內容非常清楚地描繪了這種非傳統方法及其好處。不過,既然有幾個人問了,我也寫了一篇相關的博文:Using VueJs with ASP.NET Razor Can Be Great!

引用自:https://stackoverflow.com/questions/48706113