学习VUE第五天(VUE之内置指令(基本、条件、列表渲染)——下篇)
大纲
(1)JS迭代器
(2)遮罩指令v-cloak
(3)多条件渲染指令v-if、v-else-if、v-else
(4)列表渲染指令v-for
(5)列表渲染指令标识符key属性
(6)key属性由来与虚拟DOM
(7)diff微分算法
JS迭代器
迭代器模式是一种相对简单的模式,迭代器的使用可以极大地简化数据操作,目前的绝大部分语言都内置了迭代器
-
(1)forEach迭代器
forEach方法接收一个函数作为参数,对数组中每个元素使用这个函数,只调用这个函数,数组本身没有任何变化,即不改变原始数组 -
forEach
-
(2)map迭代器
map迭代器和forEach有些类似,区别:可以生成新数组 -
(3)every迭代器
every方法接受一个返回值为布尔类型的函数,对数组中每个元素使用这个函数,如果对于所有元素,该函数均返回true,则该方法返回true,否则返回false
应用场景:全选和全不选的业务逻辑 -
(4)some迭代器
some方法也是接受一个返回值为布尔类型的函数,只要有一个元素使得该函数返回true,该方法就返回true
应用场景:批量删除时有一个选中即可
(1)遍历对象for-in,条件遍历中的var可以省略
这里补充下JS遍历操作中常见的for-in
作用:用于对数组或者对象的属性进行循环操作
语法:
案例:
小结:
①for … in 循环中的代码每执行一次,就会对数组的元素或者对象的属性进行一次操作
②数组的键名是数字,但是for…in循环是以字符串作为键名“0”、“1”、“2”等等,而key为string类型,可能会意外导致如:‘2’ + 1 == ‘21’
③某些情况下,for…in循环会以任意顺序遍历键名
注意:总之,for…in循环主要是为遍历对象而设计的,不适用于遍历数组
(2)遍历对象键–Object.keys()
构造函数Object里面自带的方法Object.keys()(取键名)
(3)遍历对象值–Object.values
构造函数Object里面自带的方法Object.values()(取键值)
(4)for…of遍历,优点如下:
①有着同for…in一样的简洁语法,但是避开了 for-in 循环的所有缺陷
②for-of 循环不支持普通对象,但如果你想迭代一个对象的属性,可以用 for-in 循环(这也是它的本职工作)或内建的 Object.keys() 方法
(4)for…of遍历:(对比记忆v-for in/of)
指令(Directive)的概念
之前已经介绍过指令(Directive)的概念了,Vue.js的指令是带有特殊前缀“v-”的HTML特性,它绑定一个表达式,并将一些特性应用到DOM上。
目前用到过很多Vue内置指令,例如v-html、v-pre、v-bind等,本节继续讲解Vue常用的内置指令。
基本指令之v-cloak
v-cloak不需要表达式,它会在Vue实例编译结束时从绑定的HTML元素上移除,经常和CSS的display:none;配合使用。
v-cloak遮罩指令
对于屏幕闪动,只要在v-cloak基础上再加一句CSS即可
一般情况下,v-cloak是解决初始化慢导致页面闪动的最佳方案,对于简单项目很实用。但在工程化的项目里,项目的HTML结构只有一个空的div元素,剩余的内容都是由路由去挂载不同组件完成的,所以不再需要v-cloak。
v-if指令回顾
指令主要职责就是当表达式值改动时,相应的将某些行为应用到DOM上,以v-if为例
- v-if指条件性渲染,为true时渲染DOM,否则不进行渲染:
数据驱动DOM是Vue.js的核心理念,所以尽量避免直接操作DOM,只需要维护关注数据即可,DOM的事Vue会进行处理。
条件渲染指令v-else
- 与JS条件语句if、else-if、else类似,Vue条件指令也可以根据表达式的值在DOM中创建或销毁元素/组件。
例如v-if与v-else,使用 v-else 指令来表示 v-if 的“else 块”:
注意:v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别。
条件渲染指令v-else-if
- v-if、v-else-if、v-else语法
2.1.0版本新增,v-else-if,顾名思义,充当 v-if 的“else-if 块”,可以连续使用。类似于 v-else,v-else-if 也必须紧跟在带 v-if 或者 v-else-if 的元素之后。
条件渲染指令-key属性
-
Vue在渲染元素时,出于效率考虑,会尽可能复用已有的元素而非重新渲染,如下所示
-
如果不希望元素复用,可以使用Vue.js提供的key键属性,可以决定是否复用元素
注意:key的值必须是唯一的。如下所示:
给两个input元素添加key键属性后,便不会再复用了,切换类型时键入的内容也会被删除。
列表渲染指令v-for
-
简介:
v-for用于将一个数组对应为一组元素,至此只需操作数组,便可以自动将元素变化映射到真实的DOM节点上。
场景:
数据的迭代渲染:后台传过来一串关于热销书的数组
需要通过vue遍历到页面上,此时便需要用到列表渲染指令v-for。 -
当需要遍历数组或者枚举对象循环显示时,需要用到列表渲染指令v-for。表达式需要结合in使用,类似item in items的形式,如下。
-
列表渲染也支持用of来代替in作为分隔符,更接近JS迭代器语法。
-
可选参数:索引
除了上述语法外,v-for表达式还支持可选参数“索引”,例如:
分隔符in/of前的语句使用括号,第二个可选参数即为索引。
列表渲染指令v-for
对象遍历
除了数组外,对象的属性也是可以遍历的
对象遍历
第二个可选参数: property 名称 (即对象的键名):
第三个可选参数:index索引
整数遍历
此外v-for还可以迭代整数
v-for与v-if可以结合使用
当它们处于同一节点,v-for 的优先级比 v-if 更高,这时v-if 将分别重复运行于每个 v-for 循环中。当你想为仅有的一些项渲染节点时,这种优先级的机制十分有用,如下:
- 除了同级,二者也可以嵌套使用
v-for控制循环次数
在Vue中v-for控制循环次数的方法可以通过以下两种方法
1.截取循环的数据(截取循环的数据长度,从而控制循环的次数)
在Vue中v-for控制循环次数的方法可以通过以下两种方法
2.通过v-if来控制
v-for与v-if同级问题
注意事项:不推荐v-for与v-if同级使用。当它们处于同一节点,v-for 的优先级比 v-if 高,这时v-if 将分别重复运行于每个 v-for 循环中。
案例
- 由此推理出,哪怕只渲染出一小部分用户的元素,也得在每次重渲染的时候遍历整个列表,不论活跃用户是否发生了变化,这样的写法多少会影响性能。所以,可以把上面的改为计算属性:
-
即先在计算属性里筛选过滤,再进行循环输出。
列表渲染指令v-for之key
状态维护key属性,接下来介绍下Vue中v-for循环key属性注意事项。
当Vue用 v-for 正在更新已渲染过的元素列表是,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue将不是移动DOM元素来匹配数据项的改变,而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。
为了给Vue一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性。key属性的类型只能为 string或者number类型。
接下来看个简单的例子
key属性由来与虚拟DOM
key属性标识由来:
1、当数据发生变化时,vue是怎么更新节点的?
要知道渲染真实DOM的开销是很大的,比如有时候我们修改了某个数据,如果直接渲染到真实dom上会引起整个dom树的重绘和重排,有没有可能我们只更新我们修改的那一小块dom而不要更新整个dom呢?
方案:diff微分算法能够帮助我们。
key属性原理diff算法步骤:
1、先根据真实DOM生成一颗virtual DOM
2、当virtual DOM某个节点的数据改变后会生成一个新的Vnode
3、然后Vnode和oldVnode作对比,发现有不一样的地方就直接修改在真实的DOM上,然后使oldVnode的值为Vnode。
key之Diff算法
key属性标识原理:
vue和react的虚拟DOM的Diff算法大致相同,其核心是基于两个简单的假设
先看一下diff算法的处理方法,对操作前后的dom树同一层的节点进行对比,一层一层对比,如下图:
Diff算法有三大策略:
1、Tree Diff
2、Component Diff
3、Element Diff
三种策略的执行顺序也是顺序依次执行。
Diff算法有三大策略之Tree Diff
Tree Diff 是对树每一层进行遍历,找出不同,如下图所示
Diff算法有三大策略之Component Diff
Component Diff 是数据层面的差异比较
1、如果都是同一类型的组件(即:两节点是同一个组件类的两个不同实例,比如:
2、如果出现不是同一类型的组件,则将该组件判断为dirty component,从而替换整个组件下的所有子节点
Diff算法有三大策略之Element Diff
Element Diff真实DOM渲染,结构差异的比较
当节点处于同一层级时,Diff提供三种DOM操作:删除、移动、插入。
key属性标识原理:
当某一层有很多相同的节点时,也就是列表节点时,Diff算法的更新过程默认情况下也是遵循以上原则。比如一下这个情况:
希望可以在B和C之间加一个F,Diff算法默认执行起来是这样的
key属性标识原理:
- 即把C更新成F,D更新成C,E更新成D,最后再插入E,是不是很没有效率?
- 所以需要使用key来给每个节点做一个唯一标识,Diff算法就可以正确的识别此节点,找到正确的位置区插入新的节点。
key属性标识原理:
vue中列表循环需加:key=“唯一标识” 唯一标识可以是item里面id、name等,因为vue组件高度复用增加Key可以标识组件的唯一性,为了更好地区别各个组件 key的作用主要是为了高效的更新虚拟DOM
key属性标识原理diff算法作用小结
1、diff算法的作用是用来计算出 Virtual DOM 中被改变的部分,然后针对该部分进行原生DOM操作,而不用重新渲染整个页面。
2、在采取diff算法比较新旧节点的时候,比较只会在同层级进行, 不会跨层级比较
key属性标识小结:
①简单理解:给 了Vue元素 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素。
②建议尽可能在使用 v-for 时提供 key attribute,除非遍历输出的 DOM 内容非常简单。
③key是 Vue 识别节点的一个通用机制,建议理想的key值是每项中都有的且唯一的id,不推荐使用index索引作为key。
④重要性:如果每一个虚拟DOM节点没有一个key值,他就没有自己的一个名字。当我们在做新旧虚拟dom的比对时,旧状态的虚拟节点就与难以与新状态的虚拟节点之间确立关系。当每一个虚拟节点都有唯一key值时,新旧状态的虚拟节点很快就能知道谁是谁,这样就极大提升了diff算法的效率。