【Vue】数据监视输入绑定

hello,我是小索奇,精心制作的Vue系列持续发放,涵盖大量的经验和示例,如有需要,可以收藏哈
本章给大家讲解的是数据监视,前面的章节已经更新完毕,后面的章节持续输出,有任何问题都可以留言或私信哈,一起加油~

数据监视

Vue实现数据监测的核心是通过defineProperty()劫持属性的getter& setter,当我们获取data数据时,底层都是通过调用getter & setter来实现的,在属性读取或修改时可以进行额外操作这实际上将数据对象“代理”了一层,形成所谓的“响应式数据”

具体一点来说哈,在初始化组件时,Vue会遍历data对象的所有属性,使用Object.defineProperty将它们转换成getter/setter这种代理允许Vue追踪依赖,在属性被访问和修改时通知变化(VM中的data就数据代理自_data)

例如我们定义了一个名为message的data属性,Vue会将其转化为

Object.defineProperty(data, 'message', {get () {// ...进行依赖收集 },set (newValue) {// ...触发更新}
})

这样在读取或修改message时,就可以触发getter和setter,从而进行依赖收集和更新触发,把这些直接叫做数据劫持即可

数据劫持就是Vue实现响应式的基石,它可以检测数据变化并触发回调来完成视图更新,使开发者只需要关注数据本身而不需要手动操作DOM

这里为什么提到数据劫持呢?

一句话形容:数据劫持是手段,数据监视是目的(没有数据劫持,就无法精确监视数据变化)

具体往下看,这里划重点,结合下面,不懂再爬上来一下哈

模拟一个小响应系统的工作方式:

<div id="app"><!-- 视图渲染 -->
</div><script>
// 数据对象  
const data = {name: 'John',age: 20
};function reactive(obj) {
// 汇总所有obj形成一个数组并进行遍历// 核心响应式转换代码Object.keys(obj).forEach(key => {let value = obj[key];const dep = new Set();Object.defineProperty(obj, key, {get() {// 收集依赖dep.add(updateView); return value;},set(newVal) {// 更新值value = newVal;// 触发依赖更新dep.forEach(fn => fn());}});});return obj;
}// 数据响应式处理
const reactiveData = reactive(data);// 视图更新函数 
function updateView() {// ...渲染视图
}// 初始化
updateView(); // 数据改变时触发视图更新
reactiveData.name = "Bob";
</script>

这个响应式系统,可以自动更新视图

当获取属性值时,收集订阅者;当设置属性值时,通知订阅者更新视图

没有get和set就不会有响应式数据,也不会显示到页面上!(调试页面中的带括号的就证明有,直接定义的没有get、set也不会响应到页面上)

拓展

响应式转换可能不理解?

// 响应式转换
const reactiveData = reactive(data);

reactive函数是用来把普通对象转换成响应式对象的,它接受一个普通对象作为参数,对这个对象的所有属性进行响应式处理,然后返回这个响应式对象

所以这里

const data = {name: 'John',age: 20
};

是定义一个普通对象data

调用:

const reactiveData = reactive(data);

reactive函数会遍历data对象的所有属性,使用Object.defineProperty()把这些属性转换成getter/setter的形式

这样responsiveData就变成一个响应式对象了,它和data对象具有相同的属性,但多了响应式的功能之后我们使用responsiveData来代替data,就可以实现视图的自动更新

简单来说reactive(data)这一行的作用就是把一个普通对象data转换成响应式对象reactiveData,得到一个可以实现数据监听与视图更新的响应式数据对象

需要注意的是,由于是直接监测属性,所以对象上的层级结构过深时,内部属性的变化不会触发响应这需要完整替换对象或手动设置新值

data: {user: {name: 'John',friend: {name: 'Chris' }}
}

如果直接这样改friend.name,Vue监测不到(直接修改深层属性无法被监测到,是因为Vue的响应式通过劫持属性的getter和setter来实现的但它只能劫持对象的第一层属性~)

this.user.friend.name = '小索奇'

重要:必须整个替换user对象,或者用Vue.set | this.$set 改friend.name,才会是响应式的数据,才会生效!

// 非响应式
this.user.name = '小索奇'
// 响应式
// Vue.set(target, key, value) | this.$set(target, key, value)
this.$set(this.user.friend, 'name', '小索奇')

数组也一样,记住不能够通过数组的索引值更改(数组本身不具备get、set方法)

this.list[0] = 'A'
// 如果数组下有对象属性,可以更改
this.list[0].name = '小索奇'

要直接调用Vue的全局API来改变数组,如用Vue.set改索引,或者用数组自身push、pop、shift、unshift、splice、sort、reverse、之类的API

  • 这些方法都被Vue做了包装,所以可以进行视图更新

上面的就可以用splice替换

this.list.splice(start, deleteCount, item1)

异步函数里改数据,页面也不会立刻更新,只有等异步函数完了,页面才显示新数据

setTimeout(() => {this.message = 'hello'
}, 1000)

所以用定时器、ajax之类的改数据,页面会晚一点才刷新

这就是Vue数据监测需要注意的几个点概括来说就是:

  • 嵌套深的数据要用Vue.set或者整个替换
  • 数组索引要用Vue.set或数组方法改
  • 异步函数里改数据,页面更新会 delay 一下

拓展

Vue.set(target,key,val)

// vm.$set()
Vue.set(vm._data.obj,'country','China')
// 为什么等同于下面的
Vue.set(vm.obj,'country','China')

这是因为数据代理-review

Vue.set 方法可以向响应式对象中添加一个属性并确保这个新属性同样是响应式的

Vue 在初始化时,会将 data 对象代理到 Vue 实例上,所以 vm.obj 等同于访问 vm._data.obj

也就是说,在组件实例 VM 中,访问 vm.obj 等同于访问 vm._data.obj,因为它会被代理到 _data 中的原始数据对象上

这是通过 Vue 的 proxy 方法实现的,大致如下:

function proxy(vm) {Object.keys(vm._data).forEach(key => {Object.defineProperty(vm, key, {get() { return vm._data[key];}});});
}

所以 Vue.set 方法既可以接受原始的 _data 对象,也可以接受代理后的组件实例对象,效果是相同的

它们都指向同一个原始数据对象

注意

  • target不允许是VM实例,也不允许是直接根对象,比如data

image-20230823005727583

表单输入绑定

这里不废话,直接上重点了哈:

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

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

如果:<input type="checkbox"/>

  • 没有配置input的value属性,那么收集的就是checked(勾选 or 未勾选,是布尔值)

配置input的value属性:

  1. v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,是布尔值)

  2. v-model的初始值是数组,那么收集的的就是value组成的数组

v-model默认是收集value值,必须要写value,才能够在vue中收集到设置的内容,否则收集默认值(比如checkbox默认为checked-布尔值)

Vue 中对表单元素绑定默认值的常见示例如下:

单选框绑定字符串值

// 不设置value默认读取null
<input type="radio" v-model="picked" value="A">
<script>
data() {return {picked: 'A'}
}  
</script>

复选框绑定布尔值:

// checkbox 必须设置value值,不设置的话默认为checked的状态(布尔值)
// 如果有多组值,需要把绑定的数据设置为数组,
睡觉<input type="checkbox" v-model="hobby" value="sleep">
玩<input type="checkbox" v-model="hobby" value="play">
吃<input type="checkbox" v-model="hobby" value="eat"><script>
data() {hobby:[]
}
</script>

选择框绑定字符串:

<select v-model="selected"><option>A</option><option>B</option><option>C</option>
</select><script>
data() {return {selected: 'A'}  
}  
</script>

文本输入绑定字符串:

<input v-model="message"><script>
data() {return {message: ''}
}
</script>

此外,还有更多实用的功能等着我们去汲取,例如:

  • 使用计算属性来处理表单输入的值,可以进行一些数据的预处理或者格式化。
  • 使用v-model的修饰符,如.number.trim,可以在需要时对输入进行自动转换或者修饰。

下节继续加油~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/91140.shtml

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

相关文章

zemax埃尔弗目镜

可以认为是一种对称设计&#xff0c;在两个双胶合透镜之间增加一个双凹单透镜 将半视场增大到30&#xff0c;所有的轴外像差维持在可以接受的水平。 入瞳直径4mm波长0.51、0.56、0.61半视场30焦距27.9mm 镜头参数&#xff1a; 成像效果&#xff1a;

用ChatGPT编写一个词卡显示网页

一、问题缘起 之前&#xff0c;我就发觉很多老师喜欢通过播放单词音频&#xff0c;显示单词拼写&#xff0c;这种词卡的形式来帮助学生记忆单词。于是&#xff0c;我就用Python制作了一个记单词软件&#xff0c;可以实现对words.txt中的单词滚动显示&#xff0c;播放发音&…

正则表达式贪婪模式和非贪婪模式

一、贪婪模式 贪婪模式表示尽可能多的匹配字符串&#xff0c;正则表达式六个量词元字符?、、*、{n}、{n,m}、{n,}默认是贪婪模式 接下来引入一个场景来分析说明 获取html a标签href属性的值 <a href"https://www.baidu.com/" attr"abc"></a>…

【Linux】详解线程第三篇——线程同步和生产消费者模型

线程同步和生消模型 前言正式开始再次用黄牛抢票来讲解线程同步的思想通过条件变量来实现线程同步条件变量接口介绍初始化和销毁pthread_cond_waitsignal和broadcast 生产消费者模型三种关系用基本工程师思维再次理解基于生产消费者模型的阻塞队列版本一版本二多生多消 利用RAI…

java web+Mysql e-life智能生活小区物业管理系统

本项目为本人自己书写&#xff0c;主要服务小区业主和管理人员。 e-life智能生活小区涉及多个方面的智能化和便利化服务&#xff1a; 1. 用户模块&#xff1a;包含基本的登入登出操作&#xff0c;查看个人信息中用户可以查看 自己的个人资料但不可以修改个人信息。 a) 用户…

Celery结合flask完成异步任务与定时任务

Celery 常用于 web 异步任务、定时任务等。 使用 redis 作为 Celery的「消息代理 / 消息中间件」。 这里通过Flask-Mail使用qq邮箱延时发送邮件作为示例 pip install celery pip install redis pip install Flask-Mail1、使用flask发送邮件 使用 Flask-Mail 发送邮件需要进行…

数据分析三剑客之一:Numpy详解及实战

1 NumPy介绍 NumPy 软件包是Python生态系统中数据分析、机器学习和科学计算的主力军。它极大地简化了向量和矩阵的操作处理。Python的一些主要软件包&#xff08;如 scikit-learn、SciPy、pandas 和 tensorflow&#xff09;都以 NumPy 作为其架构的基础部分。除了能对数值数据…

Linux基本指令(一)

&#x1f493;博主个人主页:不是笨小孩&#x1f440; ⏩专栏分类:数据结构与算法&#x1f440; C&#x1f440; 刷题专栏&#x1f440; C语言&#x1f440; &#x1f69a;代码仓库:笨小孩的代码库&#x1f440; ⏩社区&#xff1a;不是笨小孩&#x1f440; &#x1f339;欢迎大…

对负采样(negative sampling)的一些理解

负采样&#xff08;negative sampling&#xff09;通常用于解决在训练神经网络模型时计算softmax的分母过大、难以计算的问题。但在LightGCN模型论文的BPR LOSS中&#xff0c;负采样的概念可能与传统的softmax分母问题不完全一样。 在LightGCN模型中&#xff0c;不同于传统的协…

AR智能眼镜:提升现场服务技能、效率与盈利能力的利器(一)

随着技术的不断进步&#xff0c;现场服务组织正朝着远程支持转变&#xff0c;用以解决技能差距和生产力问题&#xff0c;提高员工培训和操作效率&#xff0c;同时为企业提高利润率&#xff0c;创造竞争优势。 本文将探讨增强现实&#xff08;AR&#xff09;、辅助现实&#xf…

【李沐深度学习笔记】损失函数

课程地址和说明 损失函数p2 本系列文章是我学习李沐老师深度学习系列课程的学习笔记&#xff0c;可能会对李沐老师上课没讲到的进行补充。 损失函数 损失函数是用来衡量预测值 y ^ \hat{y} y^​或 y ′ y y′与真实值 y y y的差别&#xff0c;下面给出常见的损失函数类型&am…

科技资讯|AirPods Pro基于定位控制的自适应音频功能

在接受 TechCrunch 媒体采访时&#xff0c;苹果高管 Ron Huang 和 Eric Treski 谈到了关于 AirPods Pro 自适应音频&#xff08;Adaptive Audio&#xff09;功能的轶事&#xff0c;曾考虑基于 GPS 信号来控制自适应音频级别。 Treski 表示在探索自适应音频功能初期&#xff0…

uniapp 实现下拉筛选框 二次开发定制

前言 最近又收到了一个需求&#xff0c;需要在uniapp 小程序上做一个下拉筛选框&#xff0c;然后找了一下插件市场&#xff0c;确实有找到&#xff0c;但不过他不支持搜索&#xff0c;于是乎&#xff0c;我就自动动手&#xff0c;进行了二开定制&#xff0c;站在巨人的肩膀上&…

什么是GraphQL?它与传统的REST API有什么不同?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 什么是GraphQL&#xff1f;⭐ 与传统的REST API 的不同⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣…

7.网络原理之TCP_IP(上)

文章目录 1.网络基础1.1认识IP地址1.2子网掩码1.3认识MAC地址1.4一跳一跳的网络数据传输1.5总结IP地址和MAC地址1.6网络设备及相关技术1.6.1集线器&#xff1a;转发所有端口1.6.2交换机&#xff1a;MAC地址转换表转发对应端口1.6.3主机&#xff1a;网络分层从上到下封装1.6.4主…

【新版】系统架构设计师 - 软件架构的演化与维护

个人总结&#xff0c;仅供参考&#xff0c;欢迎加好友一起讨论 文章目录 架构 - 软件架构的演化与维护考点摘要软件架构演化和定义面向对象软件架构演化对象演化消息演化复合片段演化约束演化 软件架构演化方式静态演化动态演化 软件架构演化原则软件架构演化评估方法大型网站架…

Ubuntu 20.04二进制部署Nightingale v6.1.0和Prometheus

sudo lsb_release -r可以看到操作系统版本是20.04&#xff0c;sudo uname -r可以看到内核版本是5.5.19。 sudo apt-get update进行更新镜像源。 完成之后&#xff0c;如下图&#xff1a; sudo apt-get upgrade -y更新软件。 选择NO&#xff0c;按下Enter。 完成如下&…

自定义注解实现Redis分布式锁、手动控制事务和根据异常名字或内容限流的三合一的功能

自定义注解实现Redis分布式锁、手动控制事务和根据异常名字或内容限流的三合一的功能 文章目录 [toc] 1.依赖2.Redisson配置2.1单机模式配置2.2主从模式2.3集群模式2.4哨兵模式 3.实现3.1 RedisConfig3.2 自定义注解IdempotentManualCtrlTransLimiterAnno3.3自定义切面Idempote…

问题记录 springboot 事务方法中使用this调用其它方法

原因: 因为代理对象中调用了原始对象的toString()方法,所以两个不同的对象打印出的引用是相同的

快速将iPhone大量照片快速传输到电脑的办法!

很多使用iPhone 的朋友要将照片传到电脑时&#xff0c;第一时间都只想到用iTunes 或iCloud&#xff0c;但这2个工具真的都非常难用&#xff0c;今天小编分享牛学长苹果数据管理工具的照片传输功能&#xff0c;他可以快速的将iPhone照片传输到电脑上&#xff0c;并且支持最新的i…