시리즈 기사 디렉토리
기사 디렉토리
1. 뷰 원칙
1. MVVM 모델 이해
컴포넌트화된
- 구성 요소화는 페이지를 작은 기능 모듈로 분할하는 것입니다.
- 각 기능 모듈은 독립 기능의 자체 부분에 속합니다.
- 전체 페이지의 관리 및 유지 보수를 매우 쉽게 만듭니다.
- asp jsp PHP는 이미 구성 요소화되어 있습니다.
- nodejs에도 유사한 구성 요소화가 있습니다.
데이터 기반 보기
- 기존 구성 요소는 정적으로만 렌더링되며 업데이트는 DOM 작동에 따라 달라집니다.
- 데이터 기반 보기 - Vue MVVM
- 데이터 기반 뷰 - React setState
MVVM 모델
2. 데이터 변경 모니터링을 위한 핵심 API
- 구성 요소 데이터의 데이터가 변경되면 뷰의 업데이트가 즉시 트리거됩니다.
- 데이터 기반 보기 구현의 첫 번째 단계
- 핵심 API - Object.defineProperty
- Object.defineProperty의 몇 가지 단점으로 인해 Vue3.0은 Proxy를 사용합니다.
- 그러나 프록시는 호환되지 않으며 폴리필할 수 없습니다.
Object.defineProperty() 기본 사용법
예: 기본 사용법
const data = {
}
const name = 'zhangsan'
Object.defineProperty(data, "name", {
get: function () {
console.log('get')
},
set: function (newVal) {
console.log('set')
name = newVal
}
})
console.log(data.name) // get zhangsan
data.name = 'lisi' // set
3. vue는 데이터 변경 사항을 어떻게 심층적으로 모니터링합니까?
Object.defineProperty 단점
- 딥 모니터링은 끝까지 재귀가 필요하고 한 번에 많은 양의 계산이 필요합니다.
- 신규/삭제된 속성 모니터링 불가(Vue.set, Vue.delete)
예: 보기가 세 번 업데이트되고 새 속성과 삭제된 속성을 모니터링할 수 없습니다.
// 触发更新视图
function updateView() {
console.log('视图更新');
}
// 重新定义属性,监听起来
function defineReactive(target, key, value) {
// 深度监听
observer(value)
// 核心 API
Object.defineProperty(target, key, {
get() {
return value
},
set(newValue) {
if(newValue !== value) {
// 深度监听
observer(value)
// 设置新值
// 注意,value 一直在闭包中,此处设置完之后,再 get 时也是会获取最新的值
value = newValue
// 触发更新视图
updateView()
}
}
})
}
// 监听对象属性
function observer(target) {
if (typeof target !== 'object' || target === null) {
// 不是对象或数组
return target
}
// 重新定义各个属性(for in 也可以遍历数组)
for (let key in target) {
defineReactive(target, key, target[key])
}
}
// 准备数据
const data = {
name: 'zhangsan',
age: 20,
info: {
address: '北京' // 需要深度监听
}
}
// 监听数据
observer(data)
// 测试
data.name = 'lisi'
data.age = 21
// console.log('age', data.age)
data.x = '100' // 新增属性,监听不到 —— 所以有 Vue.set
delete data.name // 删除属性,监听不到 —— 所以有 Vue.delete
data.info.address = '上海' // 深度监听
// data.nums.push(4) // 监听数组
4. vue는 어레이 변경을 어떻게 모니터합니까?
Object.defineProperty 단점
- 딥 모니터링은 끝까지 재귀가 필요하고 한 번에 많은 양의 계산이 필요합니다.
- 신규/삭제된 속성 모니터링 불가(Vue.set, Vue.delete)
- 어레이를 기본적으로 모니터링할 수 없으므로 특별한 처리가 필요합니다.
예시:
// 触发更新视图
function updateView() {
console.log('视图更新');
}
// 重新定义数组原型
const oldArrayProperty = Array.prototype
// 创建新对象,原型指向 oldArrayProperty,再扩展新的方法不会影响原型
const arrProto = Object.create(oldArrayProperty);
['push', 'pop', 'shift', 'unshift', 'splice'].forEach(methodName => {
arrProto[methodName] = function () {
updateView() // 触发视图更新
oldArrayProperty[methodName].call(this, ...arguments)
// 相当于 Array.prototype.push.call(this, ...arguments)
}
})
// 重新定义属性,监听起来
function defineReactive(target, key, value) {
// 深度监听
observer(value)
// 核心 API
Object.defineProperty(target, key, {
get() {
return value
},
set(newValue) {
if(newValue !== value) {
// 深度监听
observer(value)
// 设置新值
// 注意,value 一直在闭包中,此处设置完之后,再 get 时也是会获取最新的值
value = newValue
// 触发更新视图
updateView()
}
}
})
}
// 监听对象属性
function observer(target) {
if (typeof target !== 'object' || target === null) {
// 不是对象或数组
return target
}
// 如果是数组,就把 arrProto 赋值给数组的原型
if (Array.isArray(target)) {
target.__proto__ = arrProto
}
// 重新定义各个属性(for in 也可以遍历数组)
for (let key in target) {
defineReactive(target, key, target[key])
}
}
// 准备数据
const data = {
name: 'zhangsan',
age: 20,
info: {
address: '北京' // 需要深度监听
},
nums: [10, 20, 30]
}
// 监听数据
observer(data)
// 测试 - 监听数组
data.nums.push(4) // 监听数组
5. 가상 DOM
- vdom은 vue 및 react를 구현하기 위한 중요한 초석입니다.
- diff 알고리즘은 vdom의 핵심이자 가장 중요한 부분입니다.
- DOM 조작은 매우 성능 집약적입니다.
- jQuery를 사용하기 전에 DOM 작업의 타이밍을 직접 제어하고 수동으로 조정할 수 있습니다.
- Vue 및 React는 VDOM을 사용하는 데이터 기반 보기입니다.
(1) 솔루션: VDOM
- 특정 복잡성으로 인해 계산 수를 줄이기가 어렵습니다.
- 계산, 더 많은 것을 JS 계산으로 옮길 수 있습니까? JS는 매우 빠르게 실행되기 때문에
- vdom - JS로 DOM 구조 시뮬레이션, 최소한의 변경 사항 계산, DOM 조작
(2) JS로 DOM 구조 시뮬레이션
예: JS는 DOM 구조를 시뮬레이션합니다.
HTML 코드
<div id="div1" class="container">
<p>vdom</p>
<ul style="font-size: 20px">
<li>a</li>
</ul>
</div>
JS 코드
{
tag: 'div',
props: {
className: 'container',
id: 'div1'
}
children: [
{
tag: 'p',
children: 'vdom'
},
{
tag: 'ul',
props: {
style: 'font-size: 20px'}
children: [
{
tag: 'li',
children: 'a'
}
]
}
]
}
(3) snabbdom을 통한 vdom 학습
- 배우고 사용하기 쉬운 간단하고 강력한 vdom 라이브러리
- Vue는 vdom 및 diff의 구현을 나타냅니다.
- snabbdom 참조 링크
예시:
<div id="container"></div>
<button id="btn-change">change</button>
<script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom.js"></script>
<script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-class.js"></script>
<script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-props.js"></script>
<script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-style.js"></script>
<script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-eventlisteners.js"></script>
const snabbdom = window.snabbdom
// 定义 patch
const patch = snabbdom.init([
snabbdom_class,
snabbdom_props,
snabbdom_style,
snabbdom_eventlisteners
])
// 定义 h
const h = snabbdom.h
const container = document.getElementById('container')
// 生成 vnode
const vnode = h('ul#list', {
}, [
h('li.item', {
}, 'Item 1'),
h('li.item', {
}, 'Item 2')
])
patch(container, vnode)
document.getElementById('btn-change').addEventListener('click', () => {
// 生成 newVnode
const newVnode = h('ul#list', {
}, [
h('li.item', {
}, 'Item 1'),
h('li.item', {
}, 'Item B'),
h('li.item', {
}, 'Item 3')
])
patch(vnode, newVnode)
// vnode = newVnode // patch 之后,应该用新的覆盖现有的 vnode ,否则每次 change 都是新旧对比
})
변경하기 전에:
변경 후:
(4) vdom 요약
- JS(vnode)로 DOM 구조 시뮬레이션
- 이전 vnode와 새 vnode를 비교하고 가장 작은 업데이트 범위를 얻은 다음 마지막으로 DOM을 업데이트합니다.
- 데이터 기반 보기 모드에서 DOM 작업을 효과적으로 제어
不积跬步无以至千里 不积小流无以成江海
팔로우하고 길을 잃지 말고 업데이트를 계속하려면 클릭하십시오 ...