js实现vue组件
使用原生JavaScript实现类似Vue的组件功能
基础组件结构
创建一个简单的组件系统需要实现数据绑定、模板渲染和事件处理。以下是一个基础实现框架:
class Component {
constructor(options) {
this.$options = options;
this.$data = options.data();
this.$el = document.querySelector(options.el);
this._proxyData();
this._compile();
}
_proxyData() {
for (const key in this.$data) {
Object.defineProperty(this, key, {
get() {
return this.$data[key];
},
set(newVal) {
this.$data[key] = newVal;
this._update();
}
});
}
}
_compile() {
const template = this.$options.template;
this.$el.innerHTML = template;
this._bindMethods();
this._bindEvents();
}
_bindMethods() {
if (this.$options.methods) {
for (const methodName in this.$options.methods) {
this[methodName] = this.$options.methods[methodName].bind(this);
}
}
}
_bindEvents() {
const elements = this.$el.querySelectorAll('[v-on]');
elements.forEach(element => {
const eventName = element.getAttribute('v-on');
const methodName = element.getAttribute('@click');
element.addEventListener(eventName, this[methodName]);
});
}
_update() {
this._compile();
}
}
数据绑定实现
实现双向数据绑定需要处理模板中的插值和指令:
class Component {
// ... 其他代码同上
_compile() {
const template = this.$options.template;
let html = template;
// 处理插值表达式
html = html.replace(/\{\{(.*?)\}\}/g, (_, exp) => {
return this._getValue(exp.trim());
});
// 处理v-model指令
const elements = this.$el.querySelectorAll('[v-model]');
elements.forEach(element => {
const prop = element.getAttribute('v-model');
element.value = this[prop];
element.addEventListener('input', (e) => {
this[prop] = e.target.value;
});
});
this.$el.innerHTML = html;
this._bindMethods();
this._bindEvents();
}
_getValue(exp) {
return exp.split('.').reduce((obj, key) => {
return obj[key];
}, this);
}
}
组件使用示例
创建一个计数器组件示例:
// 定义组件
const CounterComponent = new Component({
el: '#app',
data() {
return {
count: 0,
message: 'Hello World'
};
},
template: `
<div>
<p>{{ message }}</p>
<p>Count: {{ count }}</p>
<button v-on="click" @click="increment">+</button>
<button v-on="click" @click="decrement">-</button>
<input v-model="message" type="text">
</div>
`,
methods: {
increment() {
this.count++;
},
decrement() {
this.count--;
}
}
});
HTML部分:
<div id="app"></div>
<script src="component.js"></script>
组件生命周期
添加基础的生命周期钩子:
class Component {
constructor(options) {
this.$options = options;
this.$data = options.data();
this.$el = document.querySelector(options.el);
this.callHook('beforeCreate');
this._proxyData();
this._compile();
this.callHook('created');
}
callHook(hook) {
if (this.$options[hook]) {
this.$options[hook].call(this);
}
}
// ... 其他方法
}
优化渲染性能
避免每次数据变更都完全重新渲染:
class Component {
// ... 其他代码
_update() {
const elements = this.$el.querySelectorAll('[v-text]');
elements.forEach(element => {
const exp = element.getAttribute('v-text');
element.textContent = this._getValue(exp);
});
const inputs = this.$el.querySelectorAll('[v-model]');
inputs.forEach(input => {
const prop = input.getAttribute('v-model');
if (input.value !== this[prop]) {
input.value = this[prop];
}
});
}
}
这个实现提供了Vue组件的核心功能,包括数据响应式、模板渲染、事件绑定和方法调用。实际使用时可以根据需求进一步扩展功能,如添加计算属性、组件嵌套等特性。







