列表遍历
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="text/javascript" src="../js/vue.js"></script> <!-- 引入Vue.js -->
</head>
<body>
<div id="root">
<!-- 遍历数组 -->
<h2>人员列表</h2>
<ul>
<li v-for="(p,index) in persons" :key="index">
{{p.name}}-{{p.age}}</li>
</ul>
<!-- 遍历对象 -->
<h2>汽车列表</h2>
<ul>
<li v-for="(value,k) of car" :key="k">
{{k}}---{{value}}
</li>
</ul>
<!-- 遍历字符串 -->
<h2>字符串列表</h2>
<ul>
<li v-for="(char,index) in str" :key="index">
{{char}}--{{index}}
</li>
</ul>
<!-- 遍历指定次数 -->
<h2>遍历指定次数</h2>
<ul>
<li v-for="(a,b) in 5" >
{{a}}--{{b}}
</li>
</ul>
</div>
<script type="text/javascript">
const vm=new Vue({
el:'#root',
data:{
persons:[
{id:'001',name:'张三',age:'18'},
{id:'002',name:'李四',age:'19'},
{id:'003',name:'王五',age:'20'}
],
car:{
name:'奥迪a8',
price:'70万',
color:'黑色'
},
str:'hello'
}
})
</script>
</body>
</html>
Key原理
使用index作为Key
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="text/javascript" src="../js/vue.js"></script> <!-- 引入Vue.js -->
</head>
<body>
<div id="root">
<!-- 遍历数组 -->
<h2>人员列表</h2>
<button @click.once="add">添加一个老刘</button>
<ul>
<li v-for="(p,index) in persons" :key="index">
{{p.name}}-{{p.age}}
<input type="text">
</li>
</ul>
</div>
<script type="text/javascript">
const vm=new Vue({
el:'#root',
data:{
persons:[
{id:'001',name:'张三',age:'18'},
{id:'002',name:'李四',age:'19'},
{id:'003',name:'王五',age:'20'}
]
},
methods: {
add(){
const p={id:'004',name:'老刘',age:40}
this.persons.unshift(p)
}
}
})
</script>
</body>
</html>
对比过程
如果我们选择使用index来作为key,由于数据会先从虚拟Dom,再转为真实Dom这个阶段,当我们对其进行数据更新时,新的虚拟Dom就会与旧的Dom进行对比,此时就会有一个虚拟Dom对比算法,
会对标签中的元素进行对比,新旧Dom的元素相同时,就会复用,不相同时新元素就会覆盖就元素,对比完成之后,才会产生新的真实Dom
也就是说,如果我们使用index来作为key时,如果存在打乱源列表顺序的情况,此时的内部元素就会错乱
使用id作为Key
如果我们选择使用id作为key的时候,再虚拟Dom对比过程中,如果新虚拟Dom中的新标签再旧Dom中不存在,就是直接进行新增而不是替换
如果我们不使用key,Vue默认会将index作为索引
最好是使用唯一标识作为key
列表过滤实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="text/javascript" src="../js/vue.js"></script> <!-- 引入Vue.js -->
</head>
<body>
<div id="root">
<h2>人员列表</h2>
<input type="text" placeholder="请输入名字" v-model="keyword">
<ul>
<li v-for="(p,index) in filPersion" :key="index">
{{p.name}}-{{p.age}}-{{p.sex}}</li>
</ul>
</div>
<script type="text/javascript">
// 使用watch实现
//#region
// const vm=new Vue({
// el:'#root',
// data:{
// keyword:'',
// persons:[
// {id:'001',name:'马冬梅',age:'18',sex:'女'},
// {id:'002',name:'周冬雨',age:'19',sex:'女'},
// {id:'003',name:'周杰伦',age:'20',sex:'男'},
// {id:'004',name:'问兆伦',age:'22',sex:'男'}
// ],
// filPersion:[]
// },
// watch: {
// keyword:{
// immediate:true,
// handler(val){ //一开始为空串,空串包含所有的name
// this.filPersion= this.persons.filter((p)=>{
// return p.name.indexOf(val)!==-1
// })
// }
// }
// }
// })
//#endregion
//使用computed实现
const vm=new Vue({
el:'#root',
data:{
keyword:'',
persons:[
{id:'001',name:'马冬梅',age:'18',sex:'女'},
{id:'002',name:'周冬雨',age:'19',sex:'女'},
{id:'003',name:'周杰伦',age:'20',sex:'男'},
{id:'004',name:'问兆伦',age:'22',sex:'男'}
],
},
computed: { //computed会自动帮我们在创建的时候调用一次
filPersion(){
return this.persons.filter((p)=>{
return p.name.indexOf(this.keyword)!==-1
})
}
}
})
</script>
</body>
</html>
给后续添加属性,在不改变源代码结构的情况下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="text/javascript" src="../js/vue.js"></script> <!-- 引入Vue.js -->
</head>
<body>
<div id="root">
<h1>学校信息</h1>
<h2>学校名称:{{ name }}</h2>
<h2>学校地址:{{ addr }}</h2>
<hr>
<h1>学生信息</h1>
<button @click="addSex">添加一个性别属性,默认是男</button>
<h2>学生姓名:{{ student.name }}</h2>
<h2 v-if="student.sex">学生性别:{{ student.sex }}</h2>
<h2>学生年龄:真实{{ student.age.rAge }},对外{{ student.age.sAge }}</h2>
<ul>
<li v-for="(f, index) in student.friends" :key="index">
{{ f.name }}--{{ f.age }}
</li>
</ul>
</div>
<script type="text/javascript">
const vm = new Vue({
el: '#root',
data: {
name: '尚硅谷',
addr: '北京',
student: {
name: 'tom',
age: {
rAge: 40,
sAge: 29
},
friends: [
{name: 'jerry', age: 35},
{name: 'tom', age: 36},
]
}
},
methods: {
addSex() {
// Vue.set(this.student, 'sex', '男'); 也可以使用$set
this.$set(this.student, 'sex', '男');
}
}
});
</script>
</body>
</html>
如这里,我们需要给vm.data.student拉斯添加新的属性,在不改变源student结构的情况下
可以使用Vue.set或是this.$set来进行新增
但是Vue只允许在data中的对象结构中新增新的属性,也就是只能在student这样的对象的层级下添加,不允许在data的结构下直接添加
数组元素的修改
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="text/javascript" src="../js/vue.js"></script> <!-- 引入Vue.js -->
</head>
<body>
<div id="root">
<h1>学生信息</h1>
<button @click="addSex">添加一个性别属性,默认是男</button>
<h2>学生姓名:{{ student.name }}</h2>
<h2 v-if="student.sex">学生性别:{{ student.sex }}</h2>
<h2>学生年龄:真实{{ student.age.rAge }},对外{{ student.age.sAge }}</h2>
<h2>爱好</h2>
<button @click="update">修改第一个爱好</button>
<button @click="remove">过滤掉爱好中的抽烟</button>
<ul>
<li v-for="(h, index) in student.hobby" :key="index">
{{h}}
</li>
</ul>
</div>
<script type="text/javascript">
const vm = new Vue({
el: '#root',
data: {
student: {
name: 'tom',
age: {
rAge: 40,
sAge: 29
},
hobby:['抽烟','喝酒','烫头'],
}
},
methods: {
addSex() {
// Vue.set(this.student, 'sex', '男'); 也可以使用$set
this.$set(this.student, 'sex', '男');
},
update(){
this.student.hobby.splice(0,1,'开车')
// Vue.set(this.student.hobby,0,'开车')
// this.$set(this.student.hobby,0,'开车')
},
remove(){
this.student.hobby= this.student.hobby.filter((h)=>{
return h!=='抽烟'
})
}
}
});
</script>
</body>
</html>
对于数组元素的修改,最好使用Vue提供的包装方法来进行
push(),shift(),pop(),unshift(),splice,sort(),reverse()
或是使用vue.set和this.$set(),但是不能给vm中直接添加根数据