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

news2024/12/23 9:06:12

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 = false

    const 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 = false

  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', '男')
      },
      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 = false

    new 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 = false

    new 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 = false

    new 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.coloradmin.cn/o/600542.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Markdown笔记应用程序Note Mark

什么是 Note Mark Note Mark 是一种轻量、快速、简约&#xff0c;基于网络的 Markdown 笔记应用程序。具有时尚且响应迅速的网络用户界面。 安装 在群晖上以 Docker 方式安装。 ghcr.io 镜像下载 官方的镜像没有发布在 docker hub&#xff0c;而是在 ghcr.io&#xff0c;所以…

总结了几百个ChatGPT模型的调教经验,确定不来看看?

目录 前言 chatgpt调教指南 提示词 1.清晰的问题或请求&#xff1a; 2.上下文设置&#xff1a; 3.具体的主题或领域&#xff1a; 4.陈述性问题&#xff1a; 5.追问和澄清&#xff1a; 6.限定问题范围&#xff1a; 角色扮演 充当 Linux 终端 担任产品经理 充当 SQL…

技术帖——飞凌嵌入式RK3588开发板推理模型转换及测试

RKNN&#xff08;Rockchip Neural Network&#xff09;是一种用于嵌入式设备的深度学习推理框架&#xff0c;它提供了一个端到端的解决方案&#xff0c;用于将训练好的深度学习模型转换为在嵌入式设备上运行的可执行文件。使用RKNN框架可以在嵌入式设备上高效地运行深度学习模型…

易基因:DNA羟甲基化和TET酶在胎盘发育和妊娠结局中的作用 | 深度综述

大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。 胎盘是支持哺乳动物胚胎和胎儿发育所必需的临时器官。了解滋养层细胞分化和胎盘功能的分子机制可能有助于改善产科并发症的诊断和治疗。印迹基因是调控胎盘发育的基础&#xff0c;表观遗…

chatgpt赋能python:使用Python编写数据接口:如何让您的网站更具吸引力和效率

使用Python编写数据接口&#xff1a;如何让您的网站更具吸引力和效率 在当今数字时代&#xff0c;大多数公司都希望能够从用户生成的数据中收集和分析信息&#xff0c;以了解他们的客户群体并提高他们的营销策略。为此&#xff0c;开发数据接口成为了一项对于互联网公司不可或…

新文本检测算法TextFuseNet

TextFuseNet: Scene Text Detection with Richer Fused Features 自然场景中任意形状文本检测是一项极具挑战性的任务&#xff0c;与现有的仅基于有限特征表示感知文本的文本检测方法不同&#xff0c;本文提出了一种新的框架&#xff0c;即 TextFuseNet &#xff0c;以利用融合…

网络开发过程详细知识点

网络生命周期至少包括系统构思与计划、分析和设计、运行和维护的过程。 常见的迭代周期分为四阶段周期、五阶段周期、六阶段周期。 网络开发过程根据五阶段迭代周期模型可被分为五个阶段&#xff1a; 需求分析、现有网络分析、确定网络逻辑结构、确定网络物理结构、安装与维护。…

linux实践php8.2加laravel-cotane和swoole服务器

php8.2 composer -v 报错&#xff1a; Deprecation Notice: strlen(): Passing null to parameter #1 ($string) of type string is deprecated in phar:///usr/bin/composer/vendor/symfony/console/Descriptor/TextDescriptor.php:290 解决方法可以升级下composer&#xff1…

计算机中小数的存储

十进制小数怎么转成二进制小数&#xff1f;怎么在计算机中存储float&#xff1f; 计算机中存储的二进制小数&#xff08;float&#xff09;怎么转成十进制小数&#xff1f;

法规标准-ISO 20900标准解读

ISO 20900是做什么的&#xff1f; ISO 20900全名为智能交通系统-部分自动泊车系统(PAPS)-性能要求和试验程序&#xff0c;其中主要是对PAPS系统的功能要求、性能要求及测试步骤进行了介绍 PAPS类型 I类型PAPS系统反应 II类型PAPS系统反应 一般要求 运行期间的最大速度 系统…

05 【绑定样式 条件渲染 列表渲染】

1.绑定样式 1.1 class样式 写法 :classxxx xxx可以是字符串、对象、数组。 所以分为三种写法:字符串写法、对象写法、数组写法。 1.1.1 字符串写法 字符串写法适用于: 类名不确定,要动态获取 <style>.normal{background-color: skyblue;} </style><!-- 准备…

DeSTSeg:用于异常检测的分割网络引导去噪学生教师模型(CVPR2023)

文章目录 DeSTSeg: Segmentation Guided Denoising Student-Teacher for Anomaly Detection摘要本文方法Synthetic Anomaly GenerationDenoising Student-Teacher Network分割网络推理 实验结果消融实验 DeSTSeg: Segmentation Guided Denoising Student-Teacher for Anomaly D…

倾斜摄影三维模型数据的几何坐标变换与点云重建并行计算技术探讨

倾斜摄影三维模型数据的几何坐标变换与点云重建并行计算技术探讨 倾斜摄影三维模型数据的几何坐标变换和点云重建是一项大规模计算密集型任务&#xff0c;需要消耗大量的计算资源。并行计算技术可以将这些任务分解为多个子任务&#xff0c;并在多个CPU或GPU上同时运行&#xff…

一起学SF框架系列4.6-模块context-AbstractApplicationContext

org.springframework.context.ApplicationContext接口表示Spring IoC容器&#xff0c;负责实例化、配置和组装bean。容器通过读取配置元数据来获取关于实例化、配置和组装哪些对象的指令。配置元数据以XML、Java注释或Java代码表示。它允许您表达组成应用程序的对象以及这些对象…

微信小程序的登录流程

一、背景 传统的web开发实现登陆功能&#xff0c;一般的做法是输入账号密码、或者输入手机号及短信验证码进行登录。 服务端校验用户信息通过之后&#xff0c;下发一个代表登录态的 token 给客户端&#xff0c;以便进行后续的交互,每当token过期&#xff0c;用户都需要重新登…

深度学习训练营N1周:Pytorch文本分类入门

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 NLP的功能&#xff1a; 本周使用AG News数据集进行文本分类。实现过程分为前期准备、代码实战、使用测试数据集评估模型和总结四个部分。…

chatgpt赋能python:Python冒泡排序详解

Python冒泡排序详解 介绍 Python是一门强大的编程语言&#xff0c;它在数据科学、机器学习、Web开发等领域都有广泛的应用。其中&#xff0c;排序算法是编程中一个重要的话题&#xff0c;冒泡排序也是最基本的排序算法之一。本文将详解Python冒泡排序的实现方法和优化技巧&am…

chatgpt赋能python:利用Python编写模拟器:一种循序渐进的方法

利用Python编写模拟器&#xff1a;一种循序渐进的方法 模拟器是一种用于模拟计算机硬件或软件的程序。它模拟了真实设备的功能&#xff0c;可以帮助开发人员进行测试和调试&#xff0c;以及提供一种环境来设计和验证新的算法和协议。Python是一种广泛使用的编程语言&#xff0…

计讯物联宝贝王手工大赛投票结果正式揭晓,速速围观!

在孩子的想象世界中&#xff0c; 生活中的可爱 可以是专属六一的蛋糕&#xff0c; 可以是创意手绘手摇扇&#xff0c; 可以是萌萌可爱的花束&#xff0c; 可以是未来超智能机器人&#xff0c; 可以是无人航天器模型…… 他们的想象&#xff0c; 是尚未被世俗沾染的赤忱之…

【i阿极送书——第三期】《Hadoop大数据技术基础与应用》

系列文章目录 作者&#xff1a;i阿极 作者简介&#xff1a;Python领域新星作者、多项比赛获奖者&#xff1a;博主个人首页 &#x1f60a;&#x1f60a;&#x1f60a;如果觉得文章不错或能帮助到你学习&#xff0c;可以点赞&#x1f44d;收藏&#x1f4c1;评论&#x1f4d2;关注…