知食记
搜索文档…
知食记
思维导图
归档
博客
🎃CSS
CSS基础
CSS3
SCSS
🎉JavaScript
JS 概念
JS陷阱
JS开发知识点
实现JS常见函数
实现JS 常见操作函数
JS Worker
ES6
ES6 函数
Typescript
V8
🕹️框架
Vue
基础知识
长列表性能优化
mixin
渲染函数
组件间通信
vue中的柯里化闭包
vue 渲染过程
Vue采用虚拟DOM的目的是什么
keep-alive
nextTick
vue 数组变异
vue-computed原理
vue-router原理
vue-router权限控制
路由懒加载
Vue diff原理
computed如何与视图绑定
scope css
Runtime Only vs Runtime + Compiler
集中变量管理
Vue3
React
React-Redux
React Hooks
Nuxt
Koa2
🎯算法
算法与数据结构
🎁HTML
DOM
SVG
🏈计算机网络
浏览器
计算机网络
🥊前端生态
Webpack
Babel
Fetch
Axios
Npm
Yarn
业务开发
微前端
Hexo
🏀后端
Node
Java
Python
🕹️面试
面试真经
To-do
🤖开源
开源项目
🧸其他
Linux
Git
正则
设计模式
计算机理论
Group 1
由
GitBook
提供支持
vue 数组变异
什么是变异数组方法?
变异数组方法即保持数组方法原有功能不变的前提下对其进行功能拓展,在
Vue
中这个所谓的功能拓展就是添加响应式功能。
将普通的数组变为变异数组的方法分为两步:
1.
数组劫持
2.
功能拓展
数组劫持
src/core/observer/index.js
1
if
(
Array
.
isArray
(
value
))
{
2
// 能力检测
3
const
augment
=
hasProto
4
?
protoAugment
5
:
copyAugment
6
// 通过能力检测的结果选择不同方式进行数组劫持
7
augment
(
value
,
arrayMethods
,
arrayKeys
)
8
// 对数组的响应式处理
9
this
.
observeArray
(
value
)
10
}
Copied!
其中
hasProto
1
export const hasProto = '__proto__' in {}
Copied!
1
function
protoAugment
(
target
,
src
:
Object
,
keys
:
any
)
{
2
/* eslint-disable no-proto */
3
target
.
__proto__
=
src
4
/* eslint-enable no-proto */
5
}
6
7
function
copyAugment
(
target
:
Object
,
src
:
Object
,
keys
:
Array
<
string
>
)
{
8
for
(
let
i
=
0
,
l
=
keys
.
length
;
i
<
l
;
i
++
)
{
9
const
key
=
keys
[
i
]
10
// Object.defineProperty的封装
11
def
(
target
,
key
,
src
[
key
])
12
}
13
}
Copied!
根据根据能力检测结果选择不同的数组劫持方法,如果浏览器支持隐式原型,则调用
protoAugment
函数作为数组劫持的方法( 原型链继承),反之则使用
copyAugment
.
copyAugment
函数就很清晰了,将所有变异数组中的方法,直接定义在数组实例本身,相当于变相的实现了数组的劫持。
功能拓展
1
import
{
def
}
from
'../util/index'
2
3
// 缓存数组原型
4
const
arrayProto
=
Array
.
prototype
5
// 实现 arrayMethods.__proto__ === Array.prototype
6
export
const
arrayMethods
=
Object
.
create
(
arrayProto
)
7
8
// 需要进行功能拓展的方法
9
const
methodsToPatch
=
[
10
'push'
,
11
'pop'
,
12
'shift'
,
13
'unshift'
,
14
'splice'
,
15
'sort'
,
16
'reverse'
17
]
18
19
/**
20
* Intercept mutating methods and emit events
21
*/
22
methodsToPatch
.
forEach
(
function
(
method
)
{
23
// cache original method
24
// 缓存原生数组方法
25
const
original
=
arrayProto
[
method
]
26
// 在变异数组中定义功能拓展方法
27
def
(
arrayMethods
,
method
,
function
mutator
(
...
args
)
{
28
// 执行并缓存原生数组方法的执行结果
29
const
result
=
original
.
apply
(
this
,
args
)
30
// 响应式处理
31
const
ob
=
this
.
__ob__
32
let
inserted
33
switch
(
method
)
{
34
case
'push'
:
35
case
'unshift'
:
36
inserted
=
args
37
break
38
case
'splice'
:
39
inserted
=
args
.
slice
(
2
)
40
break
41
}
42
if
(
inserted
)
ob
.
observeArray
(
inserted
)
43
// notify change
44
ob
.
dep
.
notify
()
45
// 返回原生数组方法的执行结果
46
return
result
47
})
48
})
Copied!
可以发现,源码在实现的方式上,和我在数组变异思路中采用的方法一致,只不过在其中添加了响应式的处理。
总结
Vue
的变异数组从本质上是来说是一种
装饰器模式
,通过学习它的原理,我们在实际工作中可以轻松处理这类保持原有功能不变的前提下对其进行功能拓展的需求。
以前
nextTick
下一个
vue-computed原理
最近更新
2yr ago
复制链接
内容
数组劫持
功能拓展