1. 数据绑定方式
JavaScript(原生)
手动操作 DOM:通过document.querySelector()等方法获取 DOM 元素,然后直接修改其属性或内容。
示例:
<div id="counter">0</div>
<button onclick="increment()">+1</button>
<script>
function increment() {
const counter = document.getElementById('counter');
const currentValue = parseInt(counter.textContent);
counter.textContent = currentValue + 1; // 手动更新DOM
}
</script>
特点:数据和 DOM 是分离的,需要手动维护两者的同步。
Vue(声明式绑定)
双向数据绑定:使用v-model指令实现表单元素与数据的双向绑定。
单向数据绑定:使用{{ }}插值或v-bind指令将数据渲染到 DOM。
示例:
<div id="app">
<div>{{ counter }}</div>
<button @click="increment">+1</button>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
counter: 0
},
methods: {
increment() {
this.counter++; // 数据变化自动更新DOM
}
}
});
</script>
特点:数据和 DOM 自动同步,开发者只需关注数据的变化。
2. DOM 操作方式
JavaScript
直接操作 DOM:频繁调用appendChild()、removeChild()、innerHTML等方法。
示例:动态添加列表项
const list = document.getElementById('myList');
const newItem = document.createElement('li');
newItem.textContent = 'New Item';
list.appendChild(newItem);
问题:DOM 操作代价高,代码复杂且难以维护。
Vue
虚拟 DOM(Virtual DOM):Vue 通过虚拟 DOM diff 算法高效更新真实 DOM,开发者无需手动操作。
示例:渲染列表
<ul>
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
</ul>
<script>
new Vue({
data: {
items: [{ id: 1, name: 'Item 1' }]
},
methods: {
addItem() {
this.items.push({ id: 2, name: 'Item 2' }); // 自动更新列表
}
}
});
</script>
特点:Vue 自动处理 DOM 更新,代码更简洁,性能更优。
3. 响应式原理
JavaScript
无内置响应式:数据变化不会自动更新 DOM,需要手动监听事件并更新。
示例:监听输入框变化
<input id="name" type="text">
<div id="greeting">Hello, </div>
<script>
const input = document.getElementById('name');
const greeting = document.getElementById('greeting');
input.addEventListener('input', () => {
greeting.textContent = `Hello, ${input.value}`; // 手动更新
});
</script>
Vue
基于 Object.defineProperty ()(Vue 2)或 Proxy(Vue 3):Vue 自动追踪数据变化并更新 DOM。
示例:
const app = new Vue({
data: {
name: ''
},
computed: {
greeting() {
return `Hello, ${this.name}`; // 自动响应数据变化
}
}
});
特点:数据变化时,Vue 会自动更新依赖该数据的 DOM 元素。
4. 代码组织与组件化
JavaScript
全局变量与函数:代码容易变得混乱,可维护性差。
示例:
// 全局变量
let counter = 0;
// 全局函数
function updateCounter() {
counter++;
document.getElementById('counter').textContent = counter;
}
Vue
组件化架构:将页面拆分为独立的、可复用的组件,每个组件有自己的状态和逻辑。
示例:
// 定义组件
Vue.component('counter-component', {
data() {
return {
count: 0
};
},
template: `
<div>
<span>{{ count }}</span>
<button @click="count++">+1</button>
</div>
`
});
特点:组件化使代码更清晰、可维护性更高,适合大型应用。
5. 事件处理
JavaScript
原生事件绑定:使用addEventListener()手动绑定事件,需自行管理事件生命周期。
示例:
<button id="myButton">Click me</button>
<script>
const button = document.getElementById('myButton');
button.addEventListener('click', () => {
console.log('Button clicked');
button.removeEventListener('click', /* ... */); // 需手动解绑
});
</script>
问题:容易造成内存泄漏(如未正确解绑事件)。
Vue
声明式事件绑定:使用@click等指令绑定事件,自动管理生命周期。
示例:
<button @click="handleClick">Click me</button>
<script>
new Vue({
methods: {
handleClick() {
console.log('Button clicked');
}
}
});
</script>
特点:组件销毁时自动解绑事件,减少内存泄漏风险。
6. 路由管理
JavaScript
手动实现路由:监听hashchange或popstate事件,手动切换视图。
示例:
window.addEventListener('hashchange', () => {
const route = window.location.hash.slice(1);
if (route === '/home') {
document.getElementById('content').innerHTML = 'Home Page';
} else if (route === '/about') {
document.getElementById('content').innerHTML = 'About Page';
}
});
问题:代码复杂,缺乏路由守卫、懒加载等高级功能。
Vue
Vue Router(官方路由库):提供完整的路由解决方案,支持:
嵌套路由
路由守卫(如登录验证)
懒加载(() => import(‘./Component.vue’))
过渡动画
import VueRouter from 'vue-router';
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About, meta: { requiresAuth: true } }
];
const router = new VueRouter({ routes });
// 全局路由守卫
router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth && !isAuthenticated()) {
next('/login');
} else {
next();
}
});
7. 生命周期管理
JavaScript
手动管理:需要开发者手动控制初始化、渲染和销毁逻辑。
function initComponent() {
const element = document.createElement('div');
element.innerHTML = 'Component';
document.body.appendChild(element);
// 清理函数
function destroy() {
element.remove();
// 释放资源
}
}
Vue
完整的生命周期钩子:提供created、mounted、updated、destroyed等钩子。
示例:
new Vue({
created() {
// 数据初始化
this.fetchData();
},
mounted() {
// DOM 已渲染
this.$el.querySelector('button').focus();
},
beforeDestroy() {
// 清理定时器、事件监听器等
clearInterval(this.timer);
}
});