新:哈哈,最近发了一篇vue文章,放个链接~教你从零开始写一个简单的VUE谢谢一些人们看到我在谈论技术。本文主要介绍了最近非常流行的vue2前端框架的特点以及vue2+vuex2+webpack2的前后端同构渲染架构的构建过程。最后附上代码。文章想到什么就写什么,如果有什么错误,或者大家有什么建议,欢迎指出Vue2和Vue1的对比。vue2出来之后,基本上在论坛和技术群里都能看到各种文章和讨论。大家都学了一段时间Vue2,我是今年年初开始接触vue的。一开始我对比了react、angular、vue,最后选择了vue,因为它对前端更友好(使用普通模板而不是JSX)、概念和学习成本。比较简单(对于团队开发,技术的引入要考虑其学习成本),下面介绍一下我理解的vue2和vue1的区别,如有不足欢迎补充:1.vue1中引入virtualDom,data和view的绑定过程是通过Object.defineProperty将数据转换成getter/setter,在getter/setter中添加watcher,当数据被操作时,触发setter的watch重新计算,然后更新这个数据元素关联的dom,这就是vue1的数据驱动视图原理。在vue2中,数据绑定和触发与vue1相同。基本原理是通过Object.defineProperty给数据加上一个‘钩子’,让它在数据变化时做出响应。响应后,不像vue1那样直接更新dom元素,而是放到虚拟Dom中,比较计算,然后对dom元素进行相应的处理。下面是vue1和vue2vue:vue2的响应过程对比:关于virtualDom:virtualdom最早是在react上知道的,其实就是在js内存中建立一个dom结构,然后做个区别在更新虚拟dom的时候比较差异,更新到页面中,尽量减少页面的渲染。当然,并不是说对于所有场景,virtualdom的性能都是最好的。毕竟和直接操作dom元素相比,他还是需要在内存中进行计算。因此,对于少量的元素更新,其性能可能比直接操作要好。dom元素更糟糕。当然引入virtualdom不仅仅是出于性能的考虑。虚拟dom可以带来编程上的变化。例如,您可以使用render方法直接创建新节点。虚拟dom也是vue2服务端渲染的关键。因为虚拟dom是内存的重点,所以vue2的ssr可以直接从虚拟dom生成html字符串,从而实现ssr。此外,vue2在从模板到虚拟DOM的编译阶段使用了一些高级优化:(1)。它将检测静态类名称和属性,以便在初始呈现后永远不会比较它们。(2).它会检测出最大的静态子树(即不需要动态的子树),并从渲染函数中提取出来。这样,每次重新渲染时,它只是重复使用完全相同的虚拟节点,同时跳过比较。这些高级优化通常只在使用JSX时通过Babel插件完成,但vue2即使在使用浏览器内编译器时也会这样做。2.组件事件传递机制的改变,取消组件数据双向绑定vue2组件取消了$dispath/$broadcast父子组件的事件传播方式,取消了过滤器的数据双向绑定和处理功能,props参数等,说明作者希望用户能建立一个全局的状态管理,事件管理机制,利用事件中心让组件自由通信。不管组件在组件树的哪一层,状态管理都可以一起处理。官方的vuex用于几个管理状态。3、服务器端渲染ssr:server-side-render由于虚拟dom的引入,使得vue的服务器端渲染成为可能。下面是vue-server-renderer官方提供的渲染流程图:可以看到vue-render的server端由三部分组成,一部分是页面的源代码(source),渲染部分节点层和浏览器的渲染部分。源码分为两个入口,一个是前端页面的client入口,主要是实例化Vue对象并挂载到页面;另一个是后端渲染服务入口的server入口,主要是控制服务端渲染模块Callback,返回一个Promise对象,最后返回一个Vue对象(经过测试,也可以返回直接Vue对象);前面源码部分是业务开发的代码,开发完成后通过webpack构建生成对应的bundle,这里不说了clientbundle,是一个打包后的文件,可以在浏览器端执行;这里先说下serverbundle,vue2提供了vue-server-renderer模块,可以提供两种render:rendererer/bundleRenderer,下面分别介绍render。渲染器接收一个Vue对象然后渲染它。对于简单的Vue对象可以这样做,但是对于复杂的项目,如果用这种方式直接require一个Vue对象,对于服务端代码的结构和逻辑来说是不合适的。太友好了,首先,模块的状态会在每次请求渲染请求中延续,我们需要管理避免这个渲染请求的状态影响后续的请求,所以vue-server-renderer提供了另一种渲染模式,通过AbundleRenderer进行渲染。bundleRenderer是官方推荐的更复杂项目的服务端渲染方法。通过webpack,将serverentry按照一定的要求打包生成server-bundle,相当于一个app的打包压缩文件,可供server使用。每次调用都会重新初始化Vue对象,确保每个请求都是独立的。对于开发者来说,只需要关注当前的业务,不需要去开发更多服务端渲染的逻辑代码。渲染器生成后,有两个接口,分别是renderToString和renderToStream,一个是将页面一次性渲染成一个字符串文件,一个是流式渲染,适用于支持流式的web服务器,可以请求服务的速度更快4.除了上面提到的差异,vue2在生命周期管理、动画机制等方面与vue有些不同,具体请浏览migrationVuex2和Vuex的差异,Webpack2和WebpackVuex有主要变化相比vue2和vue,Vue的状态管理工具vuex变化不大。由于时间限制,没有详细研究底层的变化,但是有更多的Helpers在使用。使用ES6的扩展功能可以更方便地使用state、getters、mutations、actions。下面简单介绍一下vuex各部分的概念。state是全局状态存储,数据会存储在里面。vue组件可以直接访问里面的值,但是只能读,不能写。getter,有时候我们需要get而不是直接获取state中的数据,可以通过getter定义函数,返回相应的数据。Mutations是vuex中唯一可以修改数据的地方。Mutations可以定义事件函数,可以在vue组件中传递commit发出一个事件并调用一个函数。需要注意的是,mutations中的操作必须是同步的,不能存在异步操作。动作类似于突变。不同的是,action不直接修改state,而是通过commit调用mutation修改数据,并且action中可以有异步处理逻辑。与webpack相比,webpack2有以下新特性:ES6模块:webpack2支持原生的ES6模块加载器,这意味着webpack2可以理解和处理导入和导出,而无需将它们转换为CommonJS进行处理。代码拆分与ES6:ES6模块加载器定义了System.import方法,可以在运行时动态加载ES6模块。MixingES6withAMDandCommonJS(MixingES6withAMDandCommonJS)更具体的新特性可以浏览到链接地址从头开始搭建项目,前面这么多,估计没人会看,言归正传,开始敲代码,哈哈,接下来我会用vue2+vuex2+webpack2搭建一个简单的ssr项目,可以直接出页面,保存为静态文件。官网虽然回应了vue-hackernews-2.0的例子,但是一开始下载代码不太容易看懂,所以参考了它的例子从头开始搭建项目。源码在文末。当然,使用npminit新建一个项目,将如下依赖写入package.json,然后运行npmi,然后去厕所喝杯茶。全部依赖安装完成后,介绍一些模块的功能。vue、vuex是vue项目使用express的基础框架,vue-server-renderer、serialize-javascript是服务端渲染使用的模块,babel-*是ES6转ES5的模块,其他webpack*、*-loader是webpack构建所需要的模块,如果项目需要学习webpack的使用,可以阅读官方文档。安装阶段完成,接下来就是进入愉快的编码阶段了。其实按照流程来看,应该是同时进行编码打包、开发环境配置等工作。对于文章的效果,我单独说一下。制作出来的页面是一个没有任何业务场景的页面(原谅我,想到什么代码就写什么),主要是演示组件的引用过程,vuex状态管理和引用,状态变化后视图更新,异步操作视图更新,所以当你下载源码,或者页面的时候,你会看到下面这个诡异的东西:好了,先不管这些细节,先看看这个诡异的东西是怎么出来的,先展示一下下面这个项目的最终目录结构:其中index.html是最终生成页面的模板页面,包含简单的头部信息和占位符,服务端渲染后可以替换。app.js是页面的逻辑入口文件,这里实例化了Vue对象,实例化时可以传入其中使用的store和route。你可以看到app.js引用了App.vue组件。.vue是vue官方推出的单文件开发方式,配合webpack的vue-loader可以轻松实现模块化开发。.vue文件在打包的时候会被编译成一个js对象,其中包含了渲染页面的render方法。以下是App.vue文件。可以看到页面包含了template、script、style三部分,其中template是组件使用的模板。现在vue2除了template还可以使用JSX和jstemplates,但是相对于其他两个,template对于前端开发者来说更??加直观,而script是component的逻辑部分,使用es6进行模块化,构建时,会使用Vue.extend生成一个组件。style是页面的样式部分。您可以指定lang来声明使用的样式语法类型。可以使用原生的css、stylus、sass等,只要配置不同的webpacksloader就可以编译。另外还可以指定scoped,这样组件中的样式只会对该组件生效,不会影响其他组件。不用担心重复命名的问题。原理是在生成label的时候给label生成一个随机数(没有我研究过生成数的算法),在selector中添加随机数对应的属性selector。可以看到该组件又导入了一个List.vue组件,在components和template中引用了它,实现了组件的嵌套和复用,下面是List.vue文件。这个文件使用了vuex管理的数据。之前版本的vuex,需要在组件使用数据中写上很多computed和methods,新版本才能使用。ES6的扩展功能和vuex的helper,缩写了很多功能,组件部分的内容就到这里了。可能有人会说什么是computed,什么是methods。自己阅读文档。一般来说,写一个组件需要了解以下几点:模板指令,比如v-for、v-bind、v-on等数据使用配置属性data、computed、props、watch等组件的生命周期属性created、mounted等全局方法Vue.set、Vue.nextTick高级开发:动画效果、自定义指令、自定义插件、混合组件开发下面说说使用vuex做状态管理,store/index.js文件.可以看到使用vuex需要在Vue.use中引入,然后实例化一个Vuex.Store对象即可,该对象需要定义state、actions、mutations、getters等,这样就可以建立一个全局的状态管理机制,并且可以从应用程序的顶部处理数据。数据操作也是通过事件直接传递给Vuex进行数据更新,然后响应其他使用相同数据的组件进行视图更新。项目的逻辑代码已经完成,但是对比上面ssr的概念,你会发现webpack的入口点还少了两个,一个是前端代码的入口点,可以是入口指向服务端渲染,下面是前端client-entry。js文件文件引入app.js,如果判断服务端渲染已经写入state,则替换vuex的state,这样服务端渲染的html和vuex管理的数据就是同步。然后将vue实例挂载到html指定的节点上。下面是server-entry.js文件,其中服务端会传递一个context对象,可以从中获取信息或者写入信息。可以看到服务端将已有的vuex状态赋值给context进行渲染,最后返回一个vue对象(文档上说需要返回一个Promise对象,在对象中应该返回一个vue对象。它也可以实验后直接返回,如果应用中有异步操作会影响view和vuex数据状态,那么应该返回一个Promise对象,这样服务端拿到的vue对象就是最终的数据和view同步统一)代码写完了,接下来让他运行,配置分为两部分,一是webpack打包的配置,二是服务器渲染服务器的搭建,这里用express搭建一个简单的服务器,不涉及任何负载均衡和性能优化问题。下面分别说说这两部分:webpack打包:webpack打包主要有三个文件webpack.base.config.js,webpack.client。config.js、webpack.server.cofnig.js,其中base主要是配置对应文件类型的loader,同时也指定了入口的切入点。业务代码和库,客户端指定client-entry.js为入口,库文件和业务文件也分开打包,还有一些图片处理和代码压缩。服务端指定server-entry.js为入口,指定封装类型标准为commonjs2,供服务端渲染模块使用。在开发过程中,可以使用webpack-hot-middleware/client、webpack-hot-middleware实现codewatch和rebuild双端代码流程,让开发更方便。具体配置在setup-dev-server。最后说下js中服务端渲染的服务端配置。server部分使用vue-server-renderer模块的createBundleRenderer通过传入刚才webpack生成的server-bundler生成一个bundleRenderer,然后就可以调用renderToStream或者renderToString来渲染页面了。具体配置在server.js中,如何运行项目可以在package.json的scripts属性中看到,其中dev是开发,start是正式环境动态生成页面,build可以直接生成client-bundler和server-bundler基本可以媲美完整的vue2前端同构渲染已经引入。先说说我对框架的看法。前端框架基本都是流行的。学新不忘本。我们必须有自己的技术栈和工作流程,就像《人月神话》中的一句话说的,没有解决任何问题的灵丹妙药。针对不同的项目,不同的业务场景,应该采用不同的框架,采用最适合的开发架构进行开发。.附上代码,点我,给个star~最后无话可说,不如祝大家新年快乐,祝大家代码无bug,哈哈
