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

Joe*_*iro 27 asp.net asp.net-mvc razor vue.js asp.net-core

我正在尝试使用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>
Run Code Online (Sandbox Code Playgroud)

我已经读过混合Vue和Razor页面是一种不好的做法,应该使用Razor OR Vue.

为什么是这样?

Ron*_*n C 68

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

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

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

由于Vue公司和剃须刀可以做很多的同样的事情,我对面向公众的页面的目标是用剃刀产生尽可能接近最终的HTML越好,使用Vue公司的reactiveness添加到页面.这为通过解析返回的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>
Run Code Online (Sandbox Code Playgroud)

在上面,它是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>
Run Code Online (Sandbox Code Playgroud)

如果有足够的兴趣,我可以在博客文章中更详细地写出我的方法,但希望我在这里提供的内容描绘了这种非传统方法的非常清晰的图景及其好处.

  • @ ron-c是的!我从答案中得到了它的要点,但想知道某处是否有更多的内容.无压力.谢谢你的帖子! (6认同)
  • 这很有趣.我很想看到一个完整的示例项目来演示这个概念.如果有人有时间,也许是一个简单的"Todo"应用程序? (5认同)
  • 我独立得出与您相同的结论。一个团队成员找到了这篇文章并提到了它。我发现的好处之一是,您可以预先填充许多字段,然后使用vue对其进行维护。这非常有效,因为初始页面加载很快并且已经包含数据,然后vue稍后处理响应性。显然,这需要花点时间来保持c#和js模型之间的一致性,但是要添加Web api,这还不错,例如:&lt;div v-text“ cart.subTotal”&gt; @ Model.SubTotal &lt;/ span&gt; &lt;div v-文字“ cart.tax”&gt; @ Model.Tax &lt;/ span&gt; &lt;div v-text“ cart.total”&gt; @ Model.Total &lt;/ span&gt; (4认同)
  • @MikeCasas - 我在等着看是否有兴趣,这会有帮助吗? (4认同)
  • 完全是@amsprich。对于面向公众的网页,我也是如此。我发现对于身份验证后的页面,由于Vue渲染速度如此之快,因此无法从预填充中获得很多好处。因此,对于那些页面,我只是通过c#将一些Json与页面一起输出,以便我的Vue模型具有来自页面初始浏览器渲染的字段数据。对于我来说,效果很好,并且对我来说不需要维护代码,因为在这种情况下,我不需要代码从c#端预填充输入字段。 (3认同)
  • @Insight - 我在答案中添加了更多信息,希望它能提供您需要的额外见解。 (2认同)
  • @ ron-c你有没有写过这篇博文? (2认同)
  • @Maverik 谢谢,我听到社区的声音响亮而清晰。我的下一个项目就是这样做,并完成一个 github 示例项目。完成后,我将使用博客文章的链接更新我的答案。 (2认同)

bbs*_*nbb 26

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

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

  • 反应.SPA应用程序通常感觉(更多)更具反应性.初始渲染通常在数据到达之前从缓存提供.在第一次加载时,所有资源都在一个请求响应中以捆绑形式到达.没有,或者更少,请求链接.

  • 流程.Webpack,捆绑和热重载非常棒.您可以获得生产构建,缩小,编译Vue渲染函数,消除404样式错误,js语法错误被捕获.对于许多错误,从引入错误到发现错误的循环大大减少.

  • SPA宇宙.路由,Vuex,这真的是未来的方式.

  • 纯度.Razor和Vue在一天结束时做了类似的事情.如果你混合它们,你可能很难保持头部直立.

  • SPA 对于小型项目来说很好,但项目越复杂,整体开发的诱惑和风险就越大,当谈到 webpack 捆绑时,我希望能更诚实一些,我知道很多人喜欢这种捆绑,但忽略了告诉人们它的巨大学习曲线。添加的组件越多(webpack 编译问题的风险就越大,这会阻碍开发,因为我个人花了几天时间尝试解决仅因使用 webpack 才存在的非常简单的错误) (3认同)
  • 这两个答案坐在这里,并看到另一个答案获得了 3 倍的选票,这很有趣。Webpack 单体似乎是一个问题,目前我没有好的解决方案。仅就开发人员的舒适度而言,重新编译时间可能会迅速增长,以至于超过了热重载的便利性。F5从来没有花太长时间!任何更了解的人,请随时在评论中留下链接。[这里](https://levelup.gitconnected.com/micro-frontend-architecture-replacing-a-monolith-from-the-inside-out-61f60d2e14c1)一篇关于许多小型应用程序的有趣文章。 (2认同)