闵行网站设计,wordpress 不收录设置,泗泾做网站,WordPress微信域名防封源码简易版Vue
实现ref功能
ref功能主要是收集依赖和触发依赖的过程。
export class Dep { // 创建一个类#xff0c;使用时使用new Depconstructor(value) { // 初始化可传入一个值this._val value;this.effects new Set(); //收集依赖的容器#xff0c;使用set数据结构}…简易版Vue
实现ref功能
ref功能主要是收集依赖和触发依赖的过程。
export class Dep { // 创建一个类使用时使用new Depconstructor(value) { // 初始化可传入一个值this._val value;this.effects new Set(); //收集依赖的容器使用set数据结构}get value() { //对value值进行拦截获取时收集依赖到effects中this.depend();return this._val;}set value(val) { // 设置的同时触发所有收集到的依赖this._val val;this.notice()}depend() {if (currentEffect) {this.effects.add(currentEffect); //将依赖放入effects中}}notice() {this.effects.forEach( fn { //触发所有收集的依赖fn();})}
}let currentEffect null;export function effectWatch(fn) { //收集依赖的函数所有函数必须用这个函数包裹currentEffect fn;fn()currentEffect null;
}// index.js
const a new Dep(10);
let b 0;
effectWatch( () {b a.value 10;console.log(b)
})
a.value 20;实现reactive功能
reactive主要是让对象也可以进行依赖的收集这就需要为对象的每一个key创建对应的Dep。
const targetsMap new Map(); // 用map数据结构来存储因为它的key可以是对象export function reactive(raw) { //传入的raw是一个对象return new Proxy(raw, { //拦截raw上所有的get和setget(target, key) {let depMap targetsMap.get(raw); // 为每一个raw创建对应的mapif (!depMap) {depMap new Map();targetsMap.set(raw, depMap);}let dep depMap.get(key); // 给raw上的每一个值创建Depif (!dep) {dep new Dep();depMap.set(key, dep);}dep.depend();return Reflect.get(target, key)},set(target, key, value) {let depMap targetsMap.get(raw);if (!depMap) {depMap new Map();targetsMap.set(raw, depMap);}let dep depMap.get(key);if (!dep) {dep new Dep();depMap.set(key, dep);}const result Reflect.set(target, key, value)dep.notice();return result;}})
}//test
const user reactive({age: 10
})
let nextAge 0;
effectWatch( () {nextAge user.age 1;console.log(nextAge);
})
user.age;简易版Vue雏形
使用上面的reactive和effectWatch功能可以实现miniVue的雏形
import { effectWatch, reactive } from ./core/index.js;const App {render(context) {effectWatch(() {document.querySelector(#app).textContent ;const element document.createElement(div);const text document.createTextNode(nihao);const text1 document.createTextNode(context.obj.count);element.append(text);element.append(text1);document.querySelector(#app).append(element)})},setup() {const obj reactive({count: 1})window.obj objreturn{obj}}
}App.render(App.setup())
//通过在console中输入obj.count的值修改视图优化
将代码抽离effectWatch在框架中调用视图的清空和append也在框架中调用
export function createApp(rootComponent) {return {mount(rootContainer) {const setupResult rootComponent.setup();effectWatch(() {rootContainer.textContent ;const element rootComponent.render(setupResult);rootContainer.append(element);})}}
}export const App {render(context) {const element document.createElement(div);const text document.createTextNode(nihao);const text1 document.createTextNode(context.obj.count);element.append(text);element.append(text1);return element;},setup() {const obj reactive({count: 1})window.obj objreturn {obj}}
}优化并使用虚拟Dom
在上面的代码中每次都会更新所有节点需要进行优化只更新变化的节点 将节点关键信息转化成一个对象。props是一个对象代表节点上的attrschildren是一个数组可以有多个
export function h(tag, props, children) {return {tag,props,children}
}在App中
import { reactive, h } from ./core/index.js;export const App {render(context) {return h(div, {}, [h(p, {}, nihao), h(p, {}, context.obj.count)])},setup() {const obj reactive({count: 1})window.obj objreturn {obj}}
}此时获取的element只是一个对象需要将其映射成真实的Dom
映射真实Dom
依次处理tag props 和children把他们变成真实的节点
function createElement(tag) {return document.createElement(tag);
}
function patchProps(el, key, prevValue, nextValue) {el.setAttribute(key, nextValue);
}
export function mountElement(element, root) {const { tag, props, children } element;const el createElement(tag);for (const key in props) {const val props[key];patchProps(el, key, null, val);}if (typeof children string) {const textNode document.createTextNode(children);el.append(textNode)} else if (Array.isArray(children)) {children.forEach((v) {mountElement(v, el)})}root.append(el)}