Vue源码分析的准备知识

Vue源码分析

准备知识

1. 将类数组对象转化为数组

<ul>
	<li>test1</li>
	<li>test2</li>
	<li>test3</li>
</ul>
const lis = document.getElementsByTagName('li')
console.log(lis instanceof Array, lis.forEach)
const lis2 = Array.from(lis) // es6
console.log(lis2 instanceof Array)
const lis3 = Array.prototype.slice.call(lis) // es5
console.log(lis3 instanceof Array)

控制台输出:

false undefined
prepare.html:23 true ƒ forEach() { [native code] }
prepare.html:25 true ƒ forEach() { [native code] }

2. 获取节点类型

DOM节点

根据 W3C 的 HTML DOM 标准,HTML 文档中的所有内容都是节点:

  • 整个文档是一个文档节点(Document)
  • 每个 HTML 元素是元素节点(Element)
  • HTML 元素内的文本是文本节点(Text)
  • 每个 HTML 属性是属性节点(Attr)
  • 注释是注释节点
HTML DOM 节点树

HTML DOM 将 HTML 文档视作树结构。这种结构被称为节点树

HTML DOM Tree 实例

HTML DOM Node Tree

通过 HTML DOM,树中的所有节点均可通过 JavaScript 进行访问。所有 HTML 元素(节点)均可被修改,也可以创建或删除节点。

<div id="test">IT</div>
const elementNode = document.getElementById('test')
const attrNode = elementNode.getAttributeNode('id')
const textNode = elementNode.firstChild
console.log(elementNode.nodeType, attrNode.nodeType, textNode.nodeType)

输出结果:

1 2 3

3. Object.defineProperty()方法

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

**备注:**应当直接在 Object 构造器对象上调用此方法,而不是在任意一个 Object 类型的实例上调用。

语法
Object.defineProperty(obj, prop, descriptor)
参数
  • obj

    要定义属性的对象。

  • prop

    要定义或修改的属性的名称或 Symbol

  • descriptor

    要定义或修改的属性描述符。

    数据描述符(4个):

    • configurable: 是否可以重新定义,默认为 false

    • enumerable: 是否可以枚举,默认为 false

    • value: 初始值,默认为 undefined

    • writable: 是否可以修改属性值,默认为 false

    访问描述符(2个):

    • get: 回调函数,根据其他相关的属性动态计算得到当前属性值,默认为 undefined

    • set: 回调函数,监视当前属性值的变化,更新其他相关的属性值,默认为 undefined

返回值

被传递给函数的对象。

在ES6中,由于 Symbol类型的特殊性,用Symbol类型的值来做对象的key与常规的定义或修改不同,而Object.defineProperty 是定义key为Symbol的属性的方法之一。

const obj = {
    firstName: 'A',
    lastName: 'B'
}
// 给obj添加fullName属性,并且能随firstName和lastName变化
Object.defineProperty(obj, 'fullName', {
    get() {
        return this.firstName + '-' + this.lastName
    },
    set(value) {
        const names = value.split('-')
        this.firstName = names[0]
        this.lastName = names[1]
    }
})

console.log(obj.fullName)
obj.firstName = 'C'
obj.lastName = 'D'
console.log(obj.fullName)
obj.fullName = 'E-F'
console.log(obj.firstName, obj.lastName)

输出结果:

A-B
C-D
E F
Object.defineProperty(obj, 'fullName2', {
    configurable: false,
    enumerable: true,
    value: 'G-H',
    writable: false
})
console.log(obj.fullName2)
obj.fullName2 = 'J-K'
console.log(obj.fullName2)

Object.defineProperty(obj, 'fullName2', {
    configurable: false,
    enumerable: false,
    value: 'G-H',
    writable: true
})

输出结果:

G-H
G-H

Object.defineProperty(obj, 'fullName2', {
       ^
       
TypeError: Cannot redefine property: fullName2

该语法仅支持IE9及以上,因此导致vue不支持IE8及以下。

4. Object.keys()方法

得到对象自身所有可枚举属性组成的数组。

const names = Object.keys(obj)
console.log(names)

输出结果:

[ 'firstName', 'lastName', 'fullName2' ]

5. Object.prototype.hasOwnProperty()方法

hasOwnProperty() 方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性(也就是,是否有指定的键)。

console.log(obj.hasOwnProperty('fullName'), obj.hasOwnProperty('toString'))

输出结果:

true false

6. DocumentFragment文档片段

Document:对应显示的页面,包含n个Element,一旦更新Document内部的某个元素,界面也会更新。

DocumentFragment:内存中保存n个Element的容器对象(不与界面关联),如果更新Fragment中的某个元素,界面不会改变。

实现:将li标签中的文本替换为atguigu
<ul id="fragment_test">
	<li>test1</li>
	<li>test2</li>
	<li>test3</li>
</ul>
const ul = document.getElementById('fragment_test')
// 1. 创建fragment
const fragment = document.createDocumentFragment()
// 2. 取出ul中所有的子节点保存到fragment中
// 换行是一个文本节点
let child
while (child = ul.firstChild) {
    // 因为每个节点只能有一个父节点,所以不会死循环
    // appendChild方法先将child从ul中移除,然后将child添加为fragment的子节点
    fragment.appendChild(child)
}
// 3. 更新fragment中所有li的文本
// childNodes获取所有的子节点,children获取所有的子标签
// 先将伪数组转换成真数组
Array.from(fragment.childNodes).forEach(node => {
    if (node.nodeType === 1) {
        // 说明当前节点为元素节点
        node.textContent = 'atguigu'
    }
})
// 4. 将fragment插入到ul中
ul.appendChild(fragment)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值