JS迭代器
-
迭代器模式是一种相对简单的模式,迭代器的使用可以极大地简化数据操作,目前的绝大部分语言都内置了迭代器
-
(1)forEach迭代器
-
forEach方法接收一个函数作为参数,对数组中每个元素使用这个函数,只调用这个函数,数组本身没有任何变化,即不改变原始数组
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>forEach迭代器</title>
<script src="../js/vue-2.6.9.min.js" type="text/javascript"></script>
</head>
<body>
<div class="demo">
</div>
</body>
<script type="text/javascript">
/* forEach方法接收一个函数作为参数,对数组中每个元素使用这个函数,只调用这个函数,数组本身没有任何变化,即不改变原始数组*/
var array_list = [111,222,333,444,555,666]
array_list.forEach(function(itme,index,seif){
console.log(itme) /* 迭代源目标、迭代项 */
console.log(index) /* 迭代的索引、下表 */
console.log(seif) /* 迭代的数组本身 */
})
</script>
</html>
-
(2)map迭代器
-
map迭代器和forEach有些类似,区别:可以生成新数组
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>map迭代器</title>
<script src="../js/vue-2.6.9.min.js" type="text/javascript"></script>
</head>
<body>
<div class="demo">
</div>
</body>
<script type="text/javascript">
/*map迭代器和forEach有些类似,区别:可以生成新数组*/
var array_list = [111,222,333,444,555,666]
var new_array = array_list.map(add)
function add(x){
console.log(x*2)
}
</script>
</html>
-
(3)every迭代器
-
every方法接受一个返回值为布尔类型的函数,对数组中每个元素使用这个函数,如果对于所有元素,该函数均返回true,则该方法返回true,否则返回false
-
应用场景:全选和全不选的业务逻辑
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>every迭代器</title>
<script src="../js/vue-2.6.9.min.js" type="text/javascript"></script>
</head>
<body>
<div class="demo">
</div>
</body>
<script type="text/javascript">
// every方法接受一个返回值为布尔类型的函数,对数组中每个元素使用这个函数,
// 如果对于所有元素,该函数均返回true,则该方法返回true,否则返回false
/*有假即假,全真即真---全选,全部选中时,全选按钮才会激活*/
// (做购物车全选时使用)
var array_list = [2,4,6,8,10]
function evenFn(num){
return num%2 ==0
}
console.log(array_list.every(evenFn))
</script>
</html>
- (4)some迭代器
- some方法也是接受一个返回值为布尔类型的函数,只要有一个元素使得该函数返回true,该方法就返回true
- 应用场景:批量删除时有一个选中即可
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>some迭代器</title>
<script src="../js/vue-2.6.9.min.js" type="text/javascript"></script>
</head>
<body>
<div class="demo"></div>
</body>
<script type="text/javascript">
// some方法也是接受一个返回值为布尔类型的函数,只要有一个元素使得该函数返回true,该方法就返回true
/*有真即真,全假即假---删除,只要有一个选项被选中,即可删除*/
// (做购物车删除的时候使用)
var array_list = [3,4,5,7,9]
function evenFn(num){
return num%2 ==0
}
console.log(array_list.some(evenFn))
</script>
</html>
遍历对象for-in和for-of
- (1)遍历对象for-in,条件遍历中的var可以省略
- (2)遍历对象键–Object.keys()
- 构造函数Object里面自带的方法Object.keys()(取键名)
- (3)遍历对象值–Object.values
- 构造函数Object里面自带的方法Object.values()(取键值)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>遍历对象for-in和for-of</title>
<script src="../js/vue-2.6.9.min.js" type="text/javascript"></script>
</head>
<body>
<div class="demo"></div>
</body>
<script type="text/javascript">
var p = {
name:'狗',
sex:'男',
age:20
}
// for...in循环主要是为遍历对象而设计的,不适用于遍历数组
// 作用:用于对数组或者对象的属性进行循环操作
// for(x in p){
// console.log(x) /*键名*/
// console.log(x+p[x]) /*键值*/
// console.log(Object.keys(p)) /*遍历对象键--Object.keys()*/
// console.log(Object.values(p)) /*遍历对象值--Object.values*/
// }
var shu = [111,222,333,444,555,666]
for(x in shu){
console.log(x) /*x代表索引值*/
// console.log(shu[x]) /*x代表迭代项*/
}
for(x of shu){
console.log(x) /*x代表迭代项*/
}
</script>
</html>
- (4)for…of遍历 (对比记忆v-for in/of)
- 优点如下:
- ①有着同for…in一样的简洁语法,但是避开了 for-in 循环的所有缺陷
- ②for-of 循环不支持普通对象,但如果你想迭代一个对象的属性,可以用 for-in 循环(这也是它的本职工作)或内建的
- Object.keys() 方法
基本指令之v-cloak
- v-cloak不需要表达式,它会在Vue实例编译结束时从绑定的HTML元素上移除,经常和CSS的display:none;配合使用。
v-cloak遮罩指令
对于屏幕闪动,只要在v-cloak基础上再加一句CSS即可
- 一般情况下,v-cloak是解决初始化慢导致页面闪动的最佳方案,对于简单项目很实用。但在工程化的项目里,项目的HTML结构只有一个空的div元素,剩余的内容都是由路由去挂载不同组件完成的,所以不再需要v-cloak。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>基本指令之v-cloak</title>
<script src="../js/vue-2.6.9.min.js" type="text/javascript"></script>
<style type="text/css">
[v-cloak]{
display: none;
}
</style>
</head>
<body>
<div class="demo" v-cloak>{{name}}</div>
</body>
<script type="text/javascript">
var demo = new Vue({
el:'.demo',
data:{
name:'娇娇',
},
methods:{
},
computed:{
}
})
</script>
</html>
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-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 的元素之后。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>条件渲染指令v-else</title>
<script src="../js/vue-2.6.9.min.js" type="text/javascript"></script>
</head>
<body>
<div class="demo">
<p v-if="num == 1">上学</p>
<p v-else-if="num == 2">玩</p>
<p v-else-if="num == 3">玩电脑</p>
<p v-else-if="num == 4">玩手机</p>
<p v-else-if="num == 5">吃放</p>
<p v-else-if="num == 6">沙雕</p>
<p v-else>特殊情况</p>
</div>
</body>
<script type="text/javascript">
// 与JS条件语句if、else-if、else类似,Vue条件指令也可以根据表达式的值在DOM中创建或销毁元素/组件。
// 注意:v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别。
var demo = new Vue({
el:'.demo',
data:{
num:6
},
methods:{
},
computed:{
}
})
</script>
</html>
-
条件渲染指令-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前的语句使用括号,第二个可选参数即为索引。
对象遍历
- 除了数组外,对象的属性也是可以遍历的
- 第二个可选参数: 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类型。 - 接下来看个简单的例子
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../js/vue-2.6.9.min.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div class="demo" v-cloak>
<ul v-for="x in books" v-bind:key="x.name" >
<li @click="change">{{x.name}}</li>
</ul>
<button @click="add">添加</button>
</div>
</body>
<script type="text/javascript">
var demo = new Vue({
el:'.demo',
data:{
books:[
{name:'西游记'},
{name:'红楼梦'},
{name:'水浒传'},
{name:'三国演义'}
]
},
methods:{
add(){
var obj = {name:'新书本'};
this.books.unshift(obj)
},
change(event){
/*event.target 事件源*/
console.log(event.target.style.backgroundColor = 'red')
}
}
})
</script>
</html>
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、如果都是同一类型的组件(即:两节点是同一个组件类的两个不同实例,比如:
与<divid=“after”)按照原策略继续比较Virtual DOM树即可 -
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
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>key标识跟踪属性</title>
<script src="../js/vue-2.6.9.min.js" type="text/javascript"></script>
</head>
<body>
<div class="demo" v-cloak>
<!-- books时源数据数组、book是迭代的别名、迭代项 -->
<ul v-for="(book,index) in books">
<li>{{index+1}}------{{book.name}}</li>
<!-- 数组形式 -->
</ul>
<ul v-for="(value,key,index) in persons">
<!-- (value键值,key键,index索引值) -->
<!-- 对象形式 -->
<li>{{key}}------{{value}}-----{{index}}</li>
</ul>
<ul v-for="x in num" v-if="x>=12">
<li>{{x}}</li>
</ul>
</div>
</body>
<script type="text/javascript">
// v-for用于将一个数组对应为一组元素,至此只需操作数组,便可以自动将元素变化映射到真实的DOM节点上。
var demo = new Vue({
el:'.demo',
data:{
books:[
{name:'哪托传奇'},
{name:'东游记'},
{name:'水许传'},
{name:'黑楼梦'}
],
persons:{
name:'娇娇',
age:18
},
num:20
},
methods:{
},
computed:{
}
})
</script>
</html>
- 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算法的效率。
以上就是小编对VUE之内置指令(基本、条件、列表渲染)的编写以及理解,有疑问请随时联系小编!