Vue2的核心原理剖析
Posted 几何心凉
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue2的核心原理剖析相关的知识,希望对你有一定的参考价值。
✨ 用了这么久的Vue2了你真的 知其然,知其所以然么?
✨ 今 天 博 主 就 为 大 家 带 来 一 篇 对 V u e 核 心 功 能 的 部 分 剖 析 \\textcolorpink今天博主就为大家带来一篇对Vue核心功能的部分剖析 今天博主就为大家带来一篇对Vue核心功能的部分剖析
✨ 后 续 文 章 会 用 更 多 小 案 例 来 帮 助 大 家 理 解 V u e 的 原 理 \\textcolorgreen后续文章会用更多小案例来帮助大家理解Vue的原理 后续文章会用更多小案例来帮助大家理解Vue的原理
前言:
- 相信大家阅读过很多关于Vue2的文章,我也阅读过很多,但是大部分文章介绍的都是如何在项目中进行应用,技术点如果使用,功能如何实现;
- 今天小编为大家带来这篇Vue2的核心原理剖析就是为大家介绍我们常用的Vue2他是如何实现的核心内容,我们简单代码的背后究竟他做了哪些,让大家能够 知其然,知其所以然
学习目标:
- 了解Object.defineProperty原理
- 了解set、get关联使用
- 了解数据反应到识图的过程
- 了解视图更换如何影响数据
- 掌握MVVM
Object.defineProperty
<script>
// 1. 字面量定义
let data =
name: 'aa'
data.name = 'bb' // 这种情况下我们并不能知道name属性发生了变化
// 2. Object.defineProperty
let data1 =
Object.defineProperty(data1, 'name',
// 当我们访问data1的name属性的时候自动调用的方法
// 并且get函数的返回值就是你拿到的值
get()
console.log('你访问了data1的name属性')
return 'aa'
,
// 当我们设置修改name属性的时候自动调用的函数
// 并且属性最新的值会被当成实参传入进来
set(newValue)
console.log('你修改了data1的name属性最新的值为', newValue)
// 这个位置 只要你修改了name属性就会得到执行
// 所以如果你想要在name变化的时候 完成一些自己的事情
// 都可以放到这里来执行
// 1. ajax()
// 2. 操作一块dom区域
)
// 以上是js中对象定义的另外一种方案,可以在访问属性和设置属性的时候自动调用对应的函数
// 访问属性:data.name data['name']
// 设置属性:data.name = 'bb' data['name'] = 'bb'
</script>
响应式的核心API
get、set
<script>
// let data =
// name: 'aa'
//
let data =
let _name = 'aa'
Object.defineProperty(data, 'name',
get()
console.log('你访问了data1的name属性')
return _name
,
set(newValue)
console.log('你修改了data1的name属性最新的值为', newValue)
_name = newValue
)
// 问题产生的原因:get中直接返回了一个固定的值,并且set函数中新值拿到了但是没有做任何事情
// 解决方案:通过声明一个中间变量,让get函数中return出去这个变量
// 并且在set函数中把最新的值设置到这个中间变量身上,起到一个set和get操作的一个
// 数据的效果
</script>
数据反应到视图
数据的变化可以引起视图的变化(通过操作dom把数据放到对应的位置上去 如果数据变化之后就用数据最新的值再重新放一次)
方案一:命令式操作
- document.querySelector(’#app’).innerText = data.name
- set函数中重新执行一下document.querySelector(’#app’).innerText = data.name
方案二:声明式渲染
v-text指令的实现
<p v-text="name"></p>
核心逻辑:通过‘模板编译’找到标记了v-text的元素,然后把对应的数据通过操作domapi放上去
<div id="app">
<p v-text="name"></p>
<p></p>
</app>
1.通过app根元素找到所有的子节点 (元素节点,文本节点…) -> dom.nodeChilds
2.通过节点类型筛选出元素节点 (p) -> nodeType 1元素节点 3文本节点
3.通过v-text找到需要设置的具体的节点 <p v-text></p>
4.找到绑定了v-text标记的元素 拿到它身上所有的属性 id class v-text=“name”
5.通过v-text=“name” 拿到指令类型 ‘v-text’ 拿到需要绑定的数据的属性名 ‘name’
6.判断当前是v-text指令 然后通过操作domapi 把name属性对应的值放上去 node.innerText = data[name]
以上整个过程可以称作‘模板编译’
视图的变化反映到数据
input元素 v-model双向绑定
M -> V
V -> M
M -> V
1.通过app根元素找到所有的子节点 (元素节点,文本节点…) -> dom.nodeChilds
2.通过节点类型筛选出元素节点 (p) -> nodeType 1元素节点 3文本节点
3.通过v-text找到需要设置的具体的节点 <p v-text></p>
4.找到绑定了v-text标记的元素 拿到它身上所有的属性 id class v-text=“name”
5.通过v-model=“name” 拿到指令类型 ‘v-model’ 拿到需要绑定的数据的属性名 ‘name’
6.判断当前是v-model指令 然后通过操作domapi 把name属性对应的值放上去 node.value = data[name]
v-model和v-text除了指令类型不一致,使用的dom api不一致 其它的步骤是完全一致的
V -> M
本质:事件监听在回调函数中拿到input中输入的最新的值然后赋值给绑定的属性
node.addEventListener('input',(e)=>
data[name] = e.target.value
)
以上总结:
1.数据的响应式
2.数据变化影响视图
3.视图变化影响数据
4.指令是如何实现的(常规实现逻辑)
优化工作:
1.通用的数据响应式处理
data()
return
name:'cp',
age:28
基于现成的数据,然后都处理成响应式
Object.keys(data) // 由所有的对象的key组成的数组
Object.keys(data).forEach(key=>
// key 属性名
// data[key] 属性值
// data 原对象
// 将所有的key都转成get和set的形式
defineReactive(data,key,data[key])
)
function defineReactive(data,key,value)
Oject.defineProperty(data, key,
get()
return value
,
set(newValue)
value = newValue
)
2.发布订阅模式
问题:
<div>
<p v-text="name"></p>
<p v-text="name"></p>
<div v-text="age"></div>
</div>
name发生变化之后 我需要做的事情是更新俩个p标签,而现在不管你更新了哪个数据,所有的标签都会被重新
操作赋值,无法做到精准更新
解决问题的思路:
1.数据发生变化之后最关键的代码是什么?
node.innerText = data[name]
2.设计一个存储结构
每一个响应式数据可能被多个标签绑定 是一个‘一对多’的关系
name: [()=> node(p1).innerText = data[name],()=> node(p2).innerText = data[name]...]
发布订阅(自定义事件) 解决的问题就是 ‘1对多’的问题
实现简单的发布订阅模式:
浏览器的事件模型
dom.addEventLister(‘click’,()=>)
只要调用click事件,所有绑定的回调函数都会执行 显然是一个1对多的关系
const Dep =
map:,
collect(eventName,fn)
// 如果从来没有收集过当前事件就先初始化成数组
if(!this.map[eventName])
this.map[eventName] = []
// 已经初始化好了就直接往里面push添加
this.map[eventName].push(fn)
,
trigger(eventName)
this.map[eventName].forEach(fn=>fn())
使用发布订阅模式优化现存问题
先前的写法 不管是哪个数据发生变化我们都是粗暴的执行一下compile函数即可
现在的写法 我们在compile函数初次执行的时候 完成更新函数的收集 然后在数据变化的时候
通过数据的key找到相对应的更新函数 依次执行 达到精准更新的效果
写在最后
✨ 原 创 不 易 , 还 希 望 各 位 大 佬 支 持 一 下 \\textcolorblue原创不易,还希望各位大佬支持一下 原创不易,还希望各位大佬支持一下
👍 点 赞 , 你 的 认 可 是 我 创 作 的 动 力 ! \\textcolorgreen点赞,你的认可是我创作的动力! 点赞,你的认可是我创作的动力!
⭐️ 收 藏 , 你 的 青 睐 是 我 努 力 的 方 向 ! \\textcolorgreen收藏,你的青睐是我努力的方向! 收藏,你的青睐是我努力的方向!
✏️ 评 论 , 你 的 意 见 是 我 进 步 的 财 富 ! \\textcolorgreen评论,你的意见是我进步的财富! 评论,你的意见是我进步的财富!
看完文章啦 验证大家对这篇文章的掌握 大家参与下方的投票呦!
以上是关于Vue2的核心原理剖析的主要内容,如果未能解决你的问题,请参考以下文章
深入浅出Spring原理及实战「原理分析专题」不看源码就带你剖析MVC容器核心流程以及运作原理