06 【Vue数据监视 v-model双向绑定】

news/2025/1/15 22:40:32/

1.Vue数据监视

1.1 问题演示

先来个案例引入一下:

<!-- 准备好一个容器-->
<div id="root"><h2>人员列表</h2><button @click="updateMei">更新马冬梅的信息</button><ul><li v-for="(p,index) of persons" :key="p.id">{{p.name}}-{{p.age}}-{{p.sex}}</li></ul> 
</div><script type="text/javascript">Vue.config.productionTip = falseconst vm = new Vue({el:'#root',data:{persons:[{id:'001',name:'马冬梅',age:30,sex:'女'},{id:'002',name:'周冬雨',age:31,sex:'女'},{id:'003',name:'周杰伦',age:18,sex:'男'},{id:'004',name:'温兆伦',age:19,sex:'男'}]},methods: {updateMei(){// this.persons[0].name = '马老师' //奏效// this.persons[0].age = 50 //奏效// this.persons[0].sex = '男' //奏效this.persons[0] = {id:'001',name:'马老师',age:50,sex:'男'} //不奏效// this.persons.splice(0,1,{id:'001',name:'马老师',age:50,sex:'男'})}}}) </script>

点击更新马冬梅的信息,马冬梅的数据并没有发生改变。
在这里插入图片描述
我们来看看控制台:
在这里插入图片描述
控制台上的数据发生了改变,说明,这个更改的数据并没有被 vue 监测到。

1.2 模拟一个数据监测

let data = {name: 'lktest',address: '北京',
}function Observer(obj) {// 汇总对象中所有的属性形成一个数组const keys = Object.keys(obj)// 遍历keys.forEach((k) => {Object.defineProperty(this, k, {get() {return obj[k]},set(val) {console.log(`${k}被改了,我要去解析模板,生成虚拟DOM.....我要开始忙了`)obj[k] = val}})})
}// 创建一个监视的实例对象,用于监视data中属性的变化
const obs = new Observer(data)
console.log(obs)// 准备一个vm实例对象
let vm = {}
vm._data = data = obs

1.3 Vue.set 的使用

Vue.set(target,propertyName/index,value) vm.$set(target,propertyName/index,value)

用法
向响应式对象中添加一个 property,并确保这个新 property 同样是响应式的,且触发视图更新。它必须用于向响应式对象上添加新 property,因为 Vue 无法探测普通的新增 property (比如 vm.myObject.newProperty = 'hi')

<!-- 准备好一个容器-->
<div id="root"><h1>学生信息</h1><button @click="addSex">添加性别属性,默认值:男</button> <br/>
</div><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。const vm = new Vue({el:'#root',data:{student:{name:'tom',age:18,hobby:['抽烟','喝酒','烫头'],friends:[{name:'jerry',age:35},{name:'tony',age:36}]}},methods: {addSex(){// Vue.set(this.student,'sex','男')this.$set(this.student,'sex','男')}}})
</script>

Vue.set() vm.$set 有缺陷:
在这里插入图片描述

1.4 监测数组

看完了 vue 监测对象中的数据,再来看看 vue 如何监测 数组里的数据

<!-- 准备好一个容器-->
<div id="root"><h2>爱好</h2><ul><li v-for="(h,index) in student.hobby" :key="index">{{h}}</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.config.productionTip = false //阻止 vue 在启动时生成生产提示。const vm = new Vue({el:'#root',data:student:{name:'tom',age:{rAge:40,sAge:29,},hobby:['抽烟','喝酒','烫头'],friends:[{name:'jerry',age:35},{name:'tony',age:36}]}},methods: {}})
</script>

在这里插入图片描述

所以我们通过 vm._data.student.hobby[0] = ‘aaa’ // 不奏效
vue 监测在数组那没有 getter 和 setter,所以监测不到数据的更改,也不会引起页面的更新

在这里插入图片描述
既然 vue 在对数组无法通过 getter 和 setter 进行数据监视,那 vue 到底如何监视数组数据的变化呢?

vue对数组的监测是通过 包装数组上常用的用于修改数组的方法来实现的。

vue官网的解释:
在这里插入图片描述

1.5 练习

<style>button {margin-top: 10px;}</style><div id="root"><h1>学生信息</h1><button @click="student.age++">年龄+1岁</button> <br /><button @click="addSex">添加性别属性,默认值:男</button> <br /><button @click="student.sex = '未知' ">修改性别</button> <br /><button @click="addFriend">在列表首位添加一个朋友</button> <br /><button @click="updateFirstFriendName">修改第一个朋友的名字为:张三</button> <br /><button @click="addHobby">添加一个爱好</button> <br /><button @click="updateHobby">修改第一个爱好为:开车</button> <br /><button @click="removeSmoke">过滤掉爱好中的抽烟</button> <br /><h3>姓名:{{ student.name }}</h3><h3>年龄:{{ student.age }}</h3><h3 v-if="student.sex">性别:{{student.sex}}</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.config.productionTip = falseconst vm = new Vue({el: '#root',data: {student: {name: 'tom',age: 18,hobby: ['抽烟', '喝酒', '烫头'],friends: [{ name: 'jerry', age: 35 },{ name: 'tony', age: 36 }]}},methods: {addSex() {// Vue.set(this.student,'sex','男')this.$set(this.student, 'sex', '男')},addFriend() {this.student.friends.unshift({ name: 'jack', age: 70 })},updateFirstFriendName() {this.student.friends[0].name = '张三'},addHobby() {this.student.hobby.push('学习')},updateHobby() {// this.student.hobby.splice(0,1,'开车')// Vue.set(this.student.hobby,0,'开车')this.$set(this.student.hobby, 0, '开车')},removeSmoke() {this.student.hobby = this.student.hobby.filter((h) => {return h !== '抽烟'})}}})
</script>

1.6 总结

Vue监视数据的原理:

  • Vue会见识data中所有层次的数据
  • 如何检测对象中的数据?
    通过setter实现监视,且要在new Vue是传入要检测的数据.
    • 对象中后追加的属性,Vue默认不做响应式处理
    • 如需给后添加的属性做响应式,请使用如下API:
      Vue.set(target,propertyName/index,value) vm.$set(target,propertyName/index,value)
  • 如何监测数组中的数据?
    通过包裹数组更新元素的方法实现,本质就是做了两件事:
    • 调用原生对应的方法对数组进行更新
    • 重新解析模板,进而更新页面
  • 在Vue修改数组中的某个元素一定要用如下方法:
    • 使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
    • Vue.set()vm.$set()

特别注意:Vue.set()vm.$set() 不能给vm 或 vm的根数据对象 添加属性!!!
例:Vue.set(this,…,…)this.$set(this,…,…)

2.v-model双向绑定

2.1收集表单数据

若:<input type="text"/>,则v-model收集的是value值,用户输入的就是value值

<!-- 准备好一个容器-->
<div id="root"><form @submit.prevent="demo">账号:<input type="text" v-model.trim="userInfo.account"> <br/><br/>密码:<input type="password" v-model="userInfo.password"> <br/><br/>年龄:<input type="number" v-model.number="userInfo.age"> <br/><br/><button>提交</button></form>
</div><script type="text/javascript">Vue.config.productionTip = falsenew Vue({el:'#root',data:{userInfo:{account:'',password:'',age:18,}},methods: {demo(){console.log(JSON.stringify(this.userInfo))}}})
</script>

若:<input type="radio"/>,则v-model收集的是value值,且要给标签配置value值。

<!-- 准备好一个容器-->
<div id="root"><form @submit.prevent="demo">性别:男<input type="radio" name="sex" v-model="userInfo.sex" value="male"><input type="radio" name="sex" v-model="userInfo.sex" value="female"></form>
</div><script type="text/javascript">Vue.config.productionTip = falsenew Vue({el:'#root',data:{userInfo:{sex:'female'}},methods: {demo(){console.log(JSON.stringify(this.userInfo))}}})
</script>

若:<input type="checkbox"/>

  • 没有配置inputvalue属性,那么收集的就是checked(勾选 or 未勾选,是布尔值)
  • 配置inputvalue属性:
    • v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,是布尔值)
    • v-model的初始值是数组,那么收集的的就是value组成的数组
<!-- 准备好一个容器-->
<div id="root"><form @submit.prevent="demo">爱好:学习<input type="checkbox" v-model="userInfo.hobby" value="study">打游戏<input type="checkbox" v-model="userInfo.hobby" value="game">吃饭<input type="checkbox" v-model="userInfo.hobby" value="eat"><br/><br/>所属校区<select v-model="userInfo.city"><option value="">请选择校区</option><option value="beijing">北京</option><option value="shanghai">上海</option><option value="shenzhen">深圳</option><option value="wuhan">武汉</option></select><br/><br/>其他信息:<textarea v-model.lazy="userInfo.other"></textarea> <br/><br/><input type="checkbox" v-model="userInfo.agree">阅读并接受<a href="http://www.atguigu.com">《用户协议》</a><button>提交</button></form>
</div><script type="text/javascript">Vue.config.productionTip = falsenew Vue({el:'#root',data:{userInfo:{hobby:[],city:'beijing',other:'',agree:''}},methods: {demo(){console.log(JSON.stringify(this.userInfo))}}})
</script>

image-20220629115509712)

备注:v-model的三个修饰符:

lazy:失去焦点再收集数据

number:输入字符串转为有效的数字

trim:输入首尾空格过滤

例:v-model.number=“phone” 就算是number类型的input框,vue收集的还是字符串,可以使用这个修饰符

2.2模拟实现v-model

    <h2>v-model实现原理(vue2)</h2><!-- 原生DOM当中是有oninput事件,它经常结合表单元素一起使用,当表单元素文本内容发生变化的时候就会发出一次回调Vue2:可以通过value与input事件实现v-model功能原生DOM标签身上的 :value是v-bind单项数据绑定--><input type="text" :value="msg" @input="msg = $event.target.value"><span>{{msg}}</span>

http://www.ppmy.cn/news/161999.html

相关文章

9针RS232C串口故障检测

9针25针针脚定义电压值&#xff08;直流&#xff09; 1脚&#xff1a;载波检测DCD -0.07~-0.15V 2脚&#xff1a;接受数据RXD -0.07~-0.15V 3脚&#xff1a;发出数据TXD -10V~-12V…

东芝笔记本portege能装linux,东芝笔记本如何装双系统 东芝笔记本安装双系统步骤【教程】...

根据用户需要&#xff0c;有些用户需要使用双系统&#xff0c;但又不知道怎么安装&#xff0c;那该怎么办呢?u启动这边用装win10win8双系统为例&#xff0c;教大家使用东芝笔记本装双系统。 1、根据“ 电脑怎么进bios更改启动顺序 ”开机u盘启动(东芝笔记本开机启动快捷键是f1…

东芝是笔记本电脑的发明者,如今沦落至此?

世界上第一个笔记本电脑是东芝发明的。 dynabook玳能笔记本在座的各位基本上没听说过。 感觉有一天 苹果可能也会沦落至此&#xff0c; 被安卓超越。 苹果太封闭了 不想安卓那么开放 直到现在&#xff0c;苹果还不能滚动截屏&#xff0c;应用多开。 感觉苹果有一天也会沦落东芝…

东芝笔记本Satellite M40-A

1. 问题&#xff1a;开机F2/FnF2进入不了BIOS 原因&#xff1a;当安装了Windows10/Windows8并且开启了快速启动&#xff0c;开机F2会进入不了BIOS或者F12进入不了U盘启动选择 解决方法&#xff1a;进入 开始--设置--系统--电源和睡眠--其他电源设置--电源选项--更改电源按钮的功…

服务器c盘有个inetpub文件夹,? 东芝笔记本c40a如何删除c盘的inetpub文件夹?[多图]...

?最近有位东芝笔记本c40a用户在升级win10系统之后&#xff0c;发现C盘多了一个“inetpub”的文件夹&#xff0c;想知道这个文件的作用&#xff0c;是否可以删除。其实&#xff0c;inetpub是IIS服务端的一个文件夹&#xff0c;但是我们基本用不上IIS服务&#xff0c;可以先关闭…

8647服务器装系统,东芝Astrea笔记本怎么安装win10系统

东芝Astrea的屏幕可视面积为13.3英寸&#xff0c;但屏幕分辨率高达38402160像素&#xff0c;也就是达到了业界顶级的4K显示屏标准。像素密度达到了惊人的331ppi&#xff0c;超过了视网膜屏幕300ppi的基本标准&#xff0c;画质非常细腻&#xff0c;毫无颗粒感。那么这么一款笔记…

东芝z20t笔记本怎样u盘启动详细图解

东芝z20t笔记本的外观设计让人印象深刻&#xff0c;集平板电脑和笔记本电脑于一身的设计&#xff0c;满足了大家对其的随意支配&#xff0c;喜欢变形本的朋友肯定会对它爱不释手。那么东芝z20t笔记本要u盘装系统的话怎么设置u盘启动呢?下面快启动小编就为大家分享东芝z20t笔记…

东芝笔记本portege能装linux,东芝portege x20w-d笔记本安装win7系统操作方法

东芝portege x20w-d是一款微妙安全保障隐秘的办公利器&#xff0c;时尚商务超便携二合一&#xff0c;足够的小和轻&#xff0c;日常携带。电池寿命和性能办公来说足够坚实&#xff0c;不论是演示文稿还是照片编辑都完全足够。那东芝portege x20w-d要怎么安装win7系统呢?下面就…