Vue渲染方法

当获取到后端数据后,我们会把它按照一定的规则加载到写好的模板中,输出成在浏览器中显示的HTML,这个过程就称之为渲染。而Vue.js是在前端(即浏览器内)进行的模板渲染。

早期的Web项目一般是在服务器端进行渲染,服务器进程从数据库获取数据后,利用后端模板引擎,甚至于直接在HTML模板中嵌入后端语言(例如JSP),将数据加载进来生成HTML,然后通过网络传输到用户的浏览器中,然后被浏览器解析成可见的页面。而前端渲染则是在浏览器里利用JS把数据和HTML模板进行组合。两种方式各有自己的优缺点,需要更具自己的业务场景来选择技术方案。

前端渲染的优点在于:
① 业务分离,后端只需要提供数据接口,前端在开发时也不需要部署对应的后端环境,通过一些代理服务器工具就能远程获取后端数据进行开发,能够提升开发效率。
② 计算量转移,原本需要后端渲染的任务转移给了前端,减轻了服务器的压力

而后端渲染的优点在于:
对搜索引擎友好
② 首页加载时间短,后端渲染加载完成后就直接显示HTML,但前端渲染在加载完成后还需要有段js渲染的时间。

Vue.js 2.0开始支持服务端渲染,从而让开发者在使用上有了更多的选择。

条件渲染

为元素挂上v-if指令即可,与之配套的还有v-else-if和v-else。v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回除了 false0""nullundefinedNaN 外的值的时候被渲染。

v-show也可以用于实现条件渲染,不过它只是简单地切换元素的CSS属性:display。

v-if和v-show的区别

相对于v-if来说,v-show并不能算作真正的条件渲染,因为挂载它的多个元素之间并没有条件上下文关系。v-show判定为假的元素的display属性被赋值为none,不过仍保留在DOM中,而v-if判定为假的元素则根本没有在DOM中出现。v-if引起了dom操作级别的变化,而v-show仅发生了样式的变化,从切换的角度考虑,v-show消耗的性能要比v-if小。

除此之外,v-if切换时,Vue.js会有一个局部编译/卸载的过程,因为v-if中的模板也可能包括数据绑定或子组件。v-if会确保条件块在切换当中适当地销毁与中间内部的事件监听器和子组件。而且v-if是惰性的,如果在初始条件为假时,v-if本身什么都不会做,而v-show则仍会进行正常的操作,然后把css样式设置为display:none。

几个注意点
●v-if会在切换中将组件上的事件监听器和子组件销毁和重建。当组件被销毁时,它将无法被任何方式获取,因为它已不存在于DOM中。
●在创建父组件时,如果子组件的v-if被判定为假,Vue不会对子组件做任何事情,直到第一次判定为真时。这在使用Vue生命周期钩子函数时要尤为注意,如果生命周期已走过组件创建的阶段,却仍无法获取组件对象,想一想,是不是v-if在作怪。
一般来说,v-if 会牵涉到虚拟 DOM diff 算法,有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。
●v-show不支持template元素

列表渲染

v-for用于实现列表渲染,可以使用item in items或者item of items的语法

语法
v-for = ' (item, index) in items'
➢ item表示每次遍历得到的元素
➢ index表示item的索引,为可选参数
➢ items表示数组或者对象


如上所示是一个双层循环。第一层遍历数组,第二层遍历数组中对象的键值对。在遍历对象时,是按Object.keys()的结果进行遍历,但是不能保证它的结果在不同的JavaScript引擎下是一致的。

除了数组和对象,v-for还可以接受单个整数,用作循环次数

Vue会把数组当作被观察者加入响应式系统中,当调用一些方法修改数组时,对应的视图将会同步更新。

上面这些数组操作方法,会直接改变原始数组称为变异方法,会促使视图自动更新。

非变异方法,例如:filter()、slice()、concat(),他们都是返回一个新数组,那么,在 Vue 中使用到这些方法,怎么样才能促使视图更新呢?我们就必须使用数组替换法,将非变异方法返回的新数组直接赋值给的旧数组

如:this.nav = this.nav.slice(1,4)

采用set方法去更新值

因为Vue.js对data中数组的原生方法进行了封装,所以在改变数组时能触发视图更新,但以下两种情况是无法触发视图更新的:
① 通过索引直接修改数组元素,例如vm.items[0] = { title : ‘title-changed’}; —使用下标/键名为数组/对象设置成员时
② 无法直接修改“修改数组”的长度,例如:vm.items.length = 0

对于第一种情况,Vue.js提供了$set方法或者其他能引起原始数组改变的方法

1
2
3
4
// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)

同样对于对象而言,由于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除,直接进行修改操作是不会构成响应式,不会触发视图更新。必须使用 Vue.set(object, key, value) 方法向嵌套对象添加响应式属性

key属性

在列表渲染的时候,为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性。

Vue1.0可以通过trace-by给数组设定唯一标识绑定,这样,Vue.js在渲染过程中会尽量复用原有对象的作用域及DOM元素。

在Vue.js 2.2.0以上的版本里,当在组件中使用v-for时,key是必须的,然而,任何数据都不会被自动传递到组件里,因为组件有自己独立的作用域。为了把迭代数据传递到组件里,需要使用props:

1
<my-component v-for="(item, index) in items"    v-bind:item="item"     v-bind:index="index"     v-bind:key="item.id"    ></my-component>

不能自动将item注入到组件里的原因是,会使组件与v-for的运作紧密耦合。明确组件数据的来源能够使组件在其他场合重复使用。

具体来说,当使用v-for更新已渲染过的元素列表时,默认用“就地复用”策略。如果数据项的顺序被改变,Vue.js将不会移动DOM元素来匹配数据项的顺序,而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时DOM状态(如表单输入值)的列表渲染输出。所以为了给Vue.js一个提示,以便能跟踪每个节点的身份,从而重用和重新排序现有元素,开发者需要为每项提供一个唯一的key属性。

显示过滤

显示一个数组的过滤或排序副本,而不实际改变或重置原始数据。在这种情况下,可以创建返回过滤或排序数组的计算属性或者直接用方法。

可以视为一种缓存?有点像数据库里的view

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<div id="app">
<span v-for="number in oddNumber">{{number}}</span>
</div>
<script>
var app = new Vue({
el:'#app',
data:{
numberArray:[1,2,3,4,5,6,7,8]
},
computed: {
//计算 numberArray 中为奇数的 oddNumber 奇数数组
oddNumber:function(){
return this.numberArray.filter(function(number){
return number%2===1
})
}
},
})
</script>

同时使用

两种渲染方式可以配合起来使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 <div id="app">
<div v-if="numbers.length">
<div v-for="item in numbers">
{{item}}
</div>
</div>
<div style="color:red" v-else>请添加数组元素</div>
</div>
<script>
var app = new Vue({
el:'#app',
data:{
numbers:[1,2,3,4]
}
})
</script>

对于这两种渲染方式,如何要同时处理多个DOM元素,可以放在template标签内。但template标签本身不会显示在DOM渲染结果中。注意v-show不支持template元素

当它们处于同一节点,v-for的优先级比v-if更高,这意味着v-if将分别重复运行于每个v-for循环中。

Vue.js 2.0新特性

与渲染有关的主要是两个方面,Render函数和服务端渲染。Render函数给开发者提供了自由度更高的模板编程能力,而不仅仅局限于之前的v-if/v-else指令。服务端渲染则为SPA项目提供了有利于SEO和网络情况慢的解决方案,弥补了纯粹前端渲染的一些弊端。

Render函数

除了给定的两种渲染方式以外,还可以用render自定义渲染函数,通过参数动态地加载组件选项

Render函数中主要提供了createElement方法

函数化组件是一个没有状态(data)和没有实例(this上下文)的一种组件类型,只通过render函数进行渲染,以及render函数中新增的context参数来传递上下文。由于不存在状态和上下文,组件的渲染开销就比较低,常用于不含具体模板,但根据所传参数可以生成具体类型组件的情况(有点类似于abstract class)

服务端渲染

主要依赖于Vue-server-renderer,由它提供了方法将Vue.js实例转化成HTML字符串形式。

这部分以后再看吧