16-Vue核心-Vue数据监视
我们先探讨一个数据更新时的问题,假设在以下人员列表中,改变"马冬梅"的信息,可以通过什么方法

1)第一种方法(奏效)
数据更新时,方法奏效
this.persons[0].name = "马老师" this.persons[0].age = 50 this.persons[0].sex = "男"
2)第二种方法(不奏效)
数据更新时,Vue不监听,模板不改变,但通过控制台命令,vm.persons[0].name 发现内部数据已经发生改变
this.persons[0] = {id:"001",name:"马老师",age:50,sex:"男"}
3)第三种方法(奏效)
// splice() 方法用于添加或删除数组中的元素 // 第一个参数代表要添加的索引位置,第二参数代表要添加或删除的个数,第三个参数代表内容 this.persons.splice(0,1,{id:"001",name:"马老师",age:50,sex:"男"})
完整代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>数据更新时的一个问题</title>
<!-- 引入Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="root">
<!-- 遍历数组 -->
<h2>人员列表</h2>
<button @click="updateData">更新马冬梅的信息</button>
<ul>
<li v-for="(p,index) in persons" :key="index">
姓名:{{p.name}}    年龄:{{p.age}}    性别:{{p.sex}}
</li>
</ul>
</div>
<script type="text/javascript">
// 阻止 vue 在启动时生成生产提示
Vue.config.productionTip = false
new Vue({
el:"#root",
data(){
return{
persons:[
{id:"001",name:"马冬梅",age:30,sex:"女"},
{id:"002",name:"周冬雨",age:28,sex:"女"},
{id:"003",name:"周杰伦",age:24,sex:"男"},
{id:"004",name:"温兆伦",age:32,sex:"男"}
],
}
},
methods:{
updateData(){
// this.persons[0].name = "马老师"
// this.persons[0].age = 50
// this.persons[0].sex = "男"
// this.persons[0] = {id:"001",name:"马老师",age:50,sex:"男"}
// splice() 方法用于添加或删除数组中的元素
// 第一个参数代表要添加的索引位置,第二参数代表要添加或删除的个数,第三个参数代表内容
this.persons.splice(0,1,{id:"001",name:"马老师",age:50,sex:"男"})
}
}
})
</script>
</body>
</html>
模拟一个数据监测
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>数据更新时的一个问题</title>
<!-- 引入Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<script type="text/javascript">
// 阻止 vue 在启动时生成生产提示
Vue.config.productionTip = false
// 声明一个变量
let data = {
name:"马铃薯",
address:"河北"
}
// // 声明一个中间变量
// let tmp = ""
// // 定时器方法,每隔一定时间就调用函数,方法或对象
// setInterval(()=>{
// if(data.name !== tmp){
// tmp = data.name
// console.log("name正在被修改")
// }
// },100)
// 创建要给监视的实例对象,用于监视 data 中属性的变化
const obs = new Observer(data)
console.log(obs)
// Observer 构造函数
function Observer(obj){
// 汇总对象中所有属性,形成一个数组
const keys = Object.keys(obj)
// 遍历,forEach() 方法对数组的每个元素执行一次提供的函数
keys.forEach((k)=>{
// Object.defineproperty方法的作用就是直接在一个对象上定义一个新属性,或者修改一个已经存在的属性
Object.defineProperty(this,k,{
get(){
return obj[k]
},
set(val){
obj[k] = val
console.log(`${k}正在被修改,进行解析模板,生成虚拟DOM...`)
}
})
})
}
//准备一个 vm 实例对象
let vm = {}
vm._data = data = obs
</script>
</body>
</html>


Vue中set的使用
在student中,使用vue.set()方法添加一个sex属性,看看前后效果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue set的使用</title>
<!-- 引入Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="root">
<!-- 遍历数组 -->
<h2>学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
<hr/>
<h2>学生姓名:{{student.name}}</h2>
<button @click="addSex">添加一个性别属性,默认值是男的</button>
<!-- 控制台 Vue.set(vm._data.student,"sex","男") -->
<!-- 判断是否有学生的性别属性,有则进行展示,否则不展示 -->
<h2 v-if="student.sex">学生性别:{{student.sex}}</h2>
<h2>学生年龄:对内{{student.age.rAge}},对外:{{student.age.sAge}}</h2>
<h2>爱好</h2>
<ul>
<li v-for="(f,index) in student.hobby" :key="index">{{f}}</li>
</ul>
<h2>朋友列表</h2>
<ul>
<li v-for="(f,index) in student.friends" :key="index">
姓名:{{f.name}}    年龄:{{f.age}}
</li>
</ul>
</div>
<script type="text/javascript">
// 阻止 vue 在启动时生成生产提示
Vue.config.productionTip = false
const vm = new Vue({
el:"#root",
data(){
return{
name:"尚硅谷",
address:"北京",
student:{
name:"马铃薯",
age:{
rAge:26,
sAge:30
},
hobby:["抽烟","喝酒","烫头"],
friends:[
{name:"大宇",age:26},
{name:"帆帆",age:26}
]
}
}
},
methods:{
updateData(){
// this.persons[0].name = "马老师"
// this.persons[0].age = 50
// this.persons[0].sex = "男"
// this.persons[0] = {id:"001",name:"马老师",age:50,sex:"男"}
// splice() 方法用于添加或删除数组中的元素
// 第一个参数代表要添加的索引位置,第二参数代表要添加或删除的个数,第三个参数代表内容
this.persons.splice(0,1,{id:"001",name:"马老师",age:50,sex:"男"})
},
addSex(){
// Vue.set(vm._data.student,"sex","男")
Vue.set(this.student,"sex","男")
}
}
})
</script>
</body>
</html>
1)初始效果

2)使用Vue.set(vm._data.student,"sex","男"),添加之后的效果

Vue监视数据的原理
1.Vue会监视data中所有层次的数据
2.如何监测对象中的数据
通过setter实现监视,且要在new Vue时就传入要监测的数据
1)对象中后追加的属性,Vue默认不做响应式处理
2)如需给后添加的属性做响应式,请使用如下API:
Vue.set(target, propertyName/index, value) 或 vm.$set(target, propertyName/index, value)
3.如何监测数组中的数据
通过包裹数组更新元素的方法实现,本质就是做了两件事
1)调用原生对应的方法对数组进行更新
2)重新解析模板,进而更新页面
4.在Vue修改数组中的某个元素一定要用如下方法:
1)使用数组的这七个API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
push( )方法:可以将一个或者更多的参数添加在数组的尾部;返回添加后的数组的长度,原数组发生改变
// 写法:array.push(item1, item2, …, itemX) var arr=[1,2,3,4]; var a=arr.push(9,8,7); console.log(a,arr);

unshift( )方法:可以将一个或者更多的参数添加在数组的头部;返回添加后的数组的长度,原数组发生改变。
// 写法:array.unshift(item1,item2, …, itemX) var arr=[1,2,3,4]; var a=arr.unshift(9,8,7); console.log(a,arr);

pop( )方法:从数组尾部删除一个元素,返回这个被删除的元素,原数组发生改变。
// 写法:array.pop() var arr=[1,2,3,4]; var a=arr.pop(); console.log(a,arr)

shift( ) 方法:从数组头部删除一个元素,返回这个被删除的元素,原数组发生改变。
// 写法:array.shift() var arr = [1,2,3,4]; var a = arr.shift(); console.log(a,arr)

splice( ) 方法:方法用于添加或删除数组中的元素
没有参数,返回空数组,原数组不变;
一个参数,从该参数表示的索引位开始截取,直至数组结束,返回截取的 数组,原数组改变;
两个参数,第一个参数表示开始截取的索引位,第二个参数表示截取的长度,返回截取的 数组,原数组改变;
三个或者更多参数,第三个及以后的参数表示要从截取位插入的值。
var hobby = ["抽烟","喝酒","烫头"]; // 将数组的第一个元素改为”开车“ hobby.splice(0,1,"开车") //删除第二个元素 hobby.splice(1,1) console.log(hobby)

2)Vue.set() 或 vm.$set()
// Vue.set()方法 Vue.set(vm._data.student,"sex","男") Vue.set(this.student,"sex","男") //vm.$set()方法 this.$set(this.student,"sex","男")
特别注意:Vue.set() 和 vm.$set() 不能给 vm 或 vm的根数据对象 添加属性 !!!
完整代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue set的使用</title>
<!-- 引入Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="root">
<h1>学生信息</h1>
<button @click="student.age++">年龄+1岁</button><br/>
<button @click="addSex">添加性别属性,默认值:男</button><br/>
<button @click="student.sex === '男' ? student.sex = '女' : student.sex = '男'">修改性别</button><br/>
<button @click="addFriend">在列表首位添加一个朋友</button><br/>
<button @click="updataFirstFriendName">修改第一个朋友的名字为:张三</button><br/>
<button @click="addHobby">添加一个爱好</button><br/>
<button @click="updateHobby">修改第一个爱好为:开车</button><br/>
<h3>姓名:{{student.name}}</h3>
<!-- 控制台 Vue.set(vm._data.student,"sex","男") -->
<!-- 判断是否有学生的性别属性,有则进行展示,否则不展示 -->
<h3 v-if="student.sex">学生性别:{{student.sex}}</h3>
<h3>年龄:{{student.age}}</h3>
<h3>爱好</h3>
<ul>
<li v-for="(h,index) in student.hobby" :key="index">{{h}}</li>
</ul>
<h3>朋友列表</h3>
<ul>
<li v-for="(f,index) in student.friends" :key="index">
姓名:{{f.name}}    年龄:{{f.age}}
</li>
</ul>
</div>
<script type="text/javascript">
// 阻止 vue 在启动时生成生产提示
Vue.config.productionTip = false
const vm = new Vue({
el:"#root",
data(){
return{
student:{
name:"马铃薯",
age:26,
hobby:["抽烟","喝酒","烫头"],
friends:[
{name:"大宇",age:26},
{name:"帆帆",age:26}
]
}
}
},
methods:{
addSex(){
// Vue.set(vm._data.student,"sex","男")
// Vue.set(this.student,"sex","男")
this.$set(this.student,"sex","男")
},
addFriend(){
// 在数组,第一个位置添加一个元素
this.student.friends.unshift({name:"钦权",age:24})
},
updataFirstFriendName(){
this.student.friends[0].name = "张三"
},
addHobby(){
// 在数组,最后一个位置添加一个元素
this.student.hobby.push("打豆豆")
},
updateHobby(){
// splice() 方法用于添加或删除数组中的元素
// 第一个参数代表要添加的索引位置,第二参数代表要添加或删除的个数,第三个参数代表内容
// this.student.hobby[0].splice(0,1,"开车")
// Vue.set(this.student.hobby,0,"开车")
this.$set(this.student.hobby,0,"开车")
}
}
})
</script>
</body>
</html>


浙公网安备 33010602011771号