javascript实现vue
使用JavaScript实现Vue核心功能
通过原生JavaScript可以模拟Vue的核心功能,如数据绑定、指令系统和虚拟DOM。以下是实现Vue响应式系统的关键步骤:
数据劫持(响应式系统)
class Vue {
constructor(options) {
this.$data = options.data();
this.observe(this.$data);
}
observe(data) {
if (!data || typeof data !== 'object') return;
Object.keys(data).forEach(key => {
this.defineReactive(data, key, data[key]);
});
}
defineReactive(obj, key, val) {
this.observe(val);
const dep = new Dep();
Object.defineProperty(obj, key, {
get() {
Dep.target && dep.addSub(Dep.target);
return val;
},
set(newVal) {
if (newVal === val) return;
val = newVal;
dep.notify();
}
});
}
}
依赖收集系统
class Dep {
constructor() {
this.subs = [];
}
addSub(sub) {
this.subs.push(sub);
}
notify() {
this.subs.forEach(sub => sub.update());
}
}
Dep.target = null;
编译器实现
class Compiler {
constructor(el, vm) {
this.$vm = vm;
this.$el = document.querySelector(el);
this.compile(this.$el);
}
compile(el) {
el.childNodes.forEach(node => {
if (node.nodeType === 1) {
this.compileElement(node);
if (node.childNodes.length) {
this.compile(node);
}
} else if (this.isInterpolation(node)) {
this.compileText(node);
}
});
}
isInterpolation(node) {
return node.nodeType === 3 && /\{\{(.*)\}\}/.test(node.textContent);
}
compileText(node) {
const exp = RegExp.$1.trim();
this.update(node, exp, 'text');
}
compileElement(node) {
Array.from(node.attributes).forEach(attr => {
if (attr.name.startsWith('v-')) {
const dir = attr.name.substring(2);
this[dir] && this[dir](node, attr.value);
}
});
}
text(node, exp) {
this.update(node, exp, 'text');
}
update(node, exp, dir) {
const fn = this[dir + 'Updater'];
fn && fn(node, this.$vm[exp]);
new Watcher(this.$vm, exp, val => {
fn && fn(node, val);
});
}
textUpdater(node, value) {
node.textContent = value;
}
}
Watcher实现
class Watcher {
constructor(vm, key, cb) {
this.vm = vm;
this.key = key;
this.cb = cb;
Dep.target = this;
this.vm[this.key]; // 触发getter
Dep.target = null;
}
update() {
this.cb.call(this.vm, this.vm[this.key]);
}
}
基本使用方法
const vm = new Vue({
el: '#app',
data() {
return {
message: 'Hello Vue',
count: 0
};
}
});
// HTML结构示例
/*
<div id="app">
<p>{{ message }}</p>
<button v-text="count"></button>
</div>
*/
实现双向数据绑定
// 在Compiler类中添加model指令处理
model(node, exp) {
this.update(node, exp, 'model');
node.addEventListener('input', e => {
this.$vm[exp] = e.target.value;
});
}
modelUpdater(node, value) {
node.value = value;
}
实现计算属性
class Vue {
constructor(options) {
// ...原有代码
this.initComputed(options.computed);
}
initComputed(computed) {
if (!computed) return;
Object.keys(computed).forEach(key => {
Object.defineProperty(this, key, {
get: typeof computed[key] === 'function'
? computed[key].bind(this)
: computed[key].get.bind(this)
});
});
}
}
这个实现包含了Vue最核心的响应式系统、模板编译和依赖追踪功能。实际Vue.js的实现更加复杂,包含虚拟DOM、组件系统、生命周期管理等更多特性,但这个示例展示了基本原理。







