为什么混合Razor Pages和VueJs是件坏事?

问题描述 投票:20回答:3

我正在尝试使用Razor Pages设置一个.NET核心项目,并在剃刀页面中包含所有逻辑的vueJs。

像这样的东西:

@{
    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。

为什么是这样?

asp.net asp.net-mvc razor asp.net-core vue.js
3个回答
22
投票

你可以这样做。有时您有义务这样做,如果像我们一样,您正在迁移现有的代码库,而您无法一次转换所有内容。正如Ron C所说,它运作良好。

如果你正在开始一个新项目,你可以选择。赞成SPA而不是Razor的原因是......

  • 反应。 SPA应用程序通常感觉(更多)更具反应性。初始渲染通常在数据到达之前从缓存提供。在第一次加载时,所有资源都在一个请求响应中以捆绑形式到达。没有,或者更少,请求链接。
  • 流程。 Webpack,捆绑和热重新加载都很棒。您可以获得生产构建,缩小,编译Vue渲染函数,消除404样式错误,js语法错误被捕获。对于许多错误,从引入错误到发现错误的循环大大减少。
  • SPA宇宙。路由,Vuex,这真的是未来的方式。
  • 纯度。 Razor和Vue在一天结束时做了类似的事情。如果你混合它们,你可能很难保持头部直立。

63
投票

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

我在非SPA页面上使用Vue和剃刀,两者很好地协同工作。我选择通过来自CDN的脚本标签加载Vue并且我没有利用WebPack进行转换,我只是在(gasp)ES5中编写代码。我选择这种方法的原因如下。

  • 使用Razor页面而不是SPA有助于SEO和公共对象页面的搜索引擎排名。
  • 直接从CDN加载Vue从学习曲线中消除了整堆Webpack中心技术,这使新开发人员更容易加快系统速度。
  • 该方法仍然为Vue固有地带来的UI开发提供了反应性的优点。
  • 通过与“页面模型”保持一致,提供站点功能的代码在逻辑上分组在提供该功能的后端页面周围。

由于Vue和Razor可以做很多相同的事情,我面向公众的页面的目标是使用Razor生成尽可能接近最终的html,并使用Vue添加对页面的反应性。这为通过解析返回的HTML索引页面的爬虫提供了极好的SEO优势。

我意识到我使用Vue与使用SPA和WebPack的路径完全不同,这种方法通常意味着我不能在不重新编写代码的情况下使用第三方Vue组件。但该方法简化了软件架构并提供了轻量级的响应式UI。

通过使用这种方法,可以大量利用Razor来生成HTML的初始呈现,其中包含一些包含vue属性的标记。然后在浏览器中加载页面后,Vue接管并可以任何方式重新配置该页面。

显然,这种方法不适合所有开发人员或项目的需求,但对于某些用例,这是一个非常好的设置。

还有一些感兴趣的细节

由于我在全站点使用vue,我的全局_layout.aspx文件负责实例化vue。在vue中实现的任何站点范围功能都在此级别实现。许多页面具有页面特定的vue功能,这是作为该页面上的mixin或该页面加载的js文件中的mixin实现的。当_layout.aspx页面实例化Vue时,它会使用我已注册到全局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!


1
投票

您现在还可以在Razor视图中隐藏VueJS模板:

https://www.npmjs.com/package/razor-vue-lint

© www.soinside.com 2019 - 2024. All rights reserved.