欢迎各位小伙伴们!
为大家推荐一款刷题神奇哦 点击链接访问牛客网
各大互联网大厂面试真题。从基础到入阶乃至原理刨析类面试题 应有尽有,赶快来装备自己吧!助你面试稳操胜券,solo全场面试官
文章目录
- 数据的变化反应到视图
- 命令式操作视图
- 声明式操作视图
- 小结
- 视图的变化反应到数据
- 现存的问题
- 写在最后
数据的变化反应到视图
前面我们了解到数据劫持之后,我们可以在数据发生修改之后做任何我们想要做的事情,操作视图当然也是OK的
命令式操作视图
目标:我们通过原始的操作dom的方式让每一次的name的最新值都能显示到p元素内部
<div id="app"><p></p>
</div>
<script>let data = {name: '小兰同学',age: 18,height:180}// 遍历每一个属性Object.keys(data).forEach((key)=>{// key 属性名// data[key] 属性值defineReactive(data,key,data[key])})function defineReactive(data,key,value){Object.defineProperty(data,key,{get(){return value},set(newVal){value = newVal // 数据发生变化,操作dom进行更新document.querySelector('#app p').innerHTML = data.name}})}// 首次渲染document.querySelector('#app p').innerHTML = data.name
</script>
声明式操作视图
目标:我们将data中name属性的值作为文本渲染到标记了v-text的p标签内部,在vue中,我们把这种标记式的声明式渲染叫做
指令
<div id="app"><p v-text="name"></p>
</div>
<script>let data = {name: '小兰同学',age: 18,height: 180}// 遍历每一个属性Object.keys(data).forEach((key) => {// key 属性名// data[key] 属性值// data 原对象defineReactive(data, key, data[key])})function defineReactive(data, key, value) {Object.defineProperty(data, key, {get() {return value},set(newVal) {value = newVal// 数据发生变化,操作dom进行更新compile()}})}// function compile() {let app = document.getElementById('app')// 1.拿到app下所有的子元素const nodes = app.childNodes // [text, input, text]//2.遍历所有的子元素nodes.forEach(node => {// nodeType为1为元素节点if (node.nodeType === 1) {const attrs = node.attributes// 遍历所有的attrubites找到 v-modelArray.from(attrs).forEach(attr => {const dirName = attr.nodeNameconst dataProp = attr.nodeValueif (dirName === 'v-text') {node.innerText = data[dataProp]}})}})}// 首次渲染compile()
</script>
小结
- 不管是指令也好,插值表达式也好,这些都是将数据反应到视图的标记而已,通过标记我们可以把数据的变化响应式的反应到对应的dom位置上去
- 找标记,把数据绑定到dom的过程,我们称之为
binding
视图的变化反应到数据
目标:将data中的message属性对应的值渲染到input上面,同时input值发生修改之后,可以反向修改message的值,在vue系统中,v-model指令就是干这个事情的,下面我们就实现一下v-model的功能
<div id="app"><input v-model="name" />
</div>
<script>let data = {name: '小兰同学',age: 18,height: 170}// 遍历每一个属性Object.keys(data).forEach((key) => {// key 属性名// data[key] 属性值// data 原对象defineReactive(data, key, data[key])})function defineReactive(data, key, value) {Object.defineProperty(data, key, {get() {return value},set(newVal) {// 数据发生变化,操作dom进行更新if (newVal === value) {return}value = newValcompile()}})}// 编译函数function compile() {let app = document.getElementById('app')// 1.拿到app下所有的子元素const nodes = app.childNodes // [text, input, text]//2.遍历所有的子元素nodes.forEach(node => {// nodeType为1为元素节点if (node.nodeType === 1) {const attrs = node.attributes// 遍历所有的attrubites找到 v-modelArray.from(attrs).forEach(attr => {const dirName = attr.nodeNameconst dataProp = attr.nodeValueif (dirName === 'v-model') {node.value = data[dataProp]// 视图变化反应到数据 无非是事件监听反向修改node.addEventListener('input', (e) => {data[dataProp] = e.target.value})}})}})}// 首次渲染compile()
</script>
现存的问题
无法做到精准更新
<div id="app"><p v-text="name"></p><p v-text="age"></p><p v-text="name"></p>
</div>
<script>let data = {name: '小兰同学',age: 18,height: 180}// 遍历每一个属性Object.keys(data).forEach((key) => {// key 属性名// data[key] 属性值// data 原对象defineReactive(data, key, data[key])})function defineReactive(data, key, value) {Object.defineProperty(data, key, {get() {return value},set(newVal) {// 数据发生变化,操作dom进行更新if (newVal === value) {return}value = newValcompile()}})}// 编译函数function compile() {let app = document.getElementById('app')// 1.拿到app下所有的子元素const nodes = app.childNodes // [text, input, text]//2.遍历所有的子元素nodes.forEach(node => {// nodeType为1为元素节点if (node.nodeType === 1) {const attrs = node.attributesArray.from(attrs).forEach(attr => {const dirName = attr.nodeNameconst dataProp = attr.nodeValueconsole.log( dirName,dataProp)if (dirName === 'v-text') {console.log(`更新了${dirName}指令,需要更新的属性为${dataProp}`)node.innerText = data[dataProp]}})}})}// 首次渲染compile()
</script>
下节中对本问题进行修复
写在最后
✨原创不易,还希望各位大佬支持一下\textcolor{blue}{原创不易,还希望各位大佬支持一下}原创不易,还希望各位大佬支持一下
👍 点赞,你的认可是我创作的动力!\textcolor{green}{点赞,你的认可是我创作的动力!}点赞,你的认可是我创作的动力!
⭐️ 收藏,你的青睐是我努力的方向!\textcolor{green}{收藏,你的青睐是我努力的方向!}收藏,你的青睐是我努力的方向!
✏️ 评论,你的意见是我进步的财富!\textcolor{green}{评论,你的意见是我进步的财富!}评论,你的意见是我进步的财富!