js 实现vue模板
使用原生 JavaScript 实现 Vue 模板功能
通过原生 JavaScript 可以实现类似 Vue 的模板功能,包括数据绑定、指令处理和模板渲染。以下是具体实现方法:
数据绑定实现
创建一个简单的数据绑定系统,使用 Object.defineProperty 或 Proxy 实现数据响应式:
class Vue {
constructor(options) {
this.$options = options
this.$data = options.data
this.observe(this.$data)
this.compile()
}
observe(data) {
if (!data || typeof data !== 'object') return
Object.keys(data).forEach(key => {
let value = data[key]
const dep = new Dep()
Object.defineProperty(data, key, {
get() {
Dep.target && dep.addSub(Dep.target)
return value
},
set(newVal) {
if (newVal !== value) {
value = newVal
dep.notify()
}
}
})
this.observe(value)
})
}
}
class Dep {
constructor() {
this.subs = []
}
addSub(sub) {
this.subs.push(sub)
}
notify() {
this.subs.forEach(sub => sub.update())
}
}
模板编译
实现模板编译功能,处理插值表达式和指令:
class Vue {
// ...其他代码
compile() {
const el = document.querySelector(this.$options.el)
this.compileNode(el)
}
compileNode(node) {
if (node.nodeType === 1) {
this.compileElement(node)
} else if (node.nodeType === 3) {
this.compileText(node)
}
if (node.childNodes && node.childNodes.length) {
Array.from(node.childNodes).forEach(childNode => {
this.compileNode(childNode)
})
}
}
compileText(node) {
const reg = /\{\{(.*?)\}\}/g
const textContent = node.textContent
if (reg.test(textContent)) {
const key = RegExp.$1.trim()
node.textContent = this.$data[key]
new Watcher(this, key, value => {
node.textContent = value
})
}
}
compileElement(node) {
Array.from(node.attributes).forEach(attr => {
if (attr.name.startsWith('v-')) {
const dir = attr.name.substring(2)
const exp = attr.value
if (dir === 'model') {
node.value = this.$data[exp]
node.addEventListener('input', e => {
this.$data[exp] = e.target.value
})
new Watcher(this, exp, value => {
node.value = value
})
}
}
})
}
}
观察者模式实现
创建 Watcher 类实现观察者模式:
class Watcher {
constructor(vm, key, cb) {
this.vm = vm
this.key = key
this.cb = cb
Dep.target = this
this.value = vm.$data[key]
Dep.target = null
}
update() {
this.value = this.vm.$data[this.key]
this.cb(this.value)
}
}
使用方法示例
<div id="app">
<input v-model="message" />
<p>{{ message }}</p>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
</script>
功能扩展
- 计算属性:可以通过添加 computed 选项并创建对应的 getter 函数实现
- 方法处理:在 Vue 实例上添加 methods 选项,并在模板中绑定事件
- 生命周期钩子:在特定阶段触发回调函数
- 组件系统:通过创建子类或工厂函数实现组件功能
这种实现方式展示了 Vue 核心功能的基本原理,实际 Vue 源码更加复杂和完善,包含虚拟 DOM、diff 算法等高级特性。







