面试题答案
一键面试Vue响应式数据绑定原理
- Object.defineProperty:Vue 2.x 使用
Object.defineProperty
来进行数据劫持。通过这个方法,Vue 可以在获取(getter
)和设置(setter
)对象属性时进行自定义操作。例如:
let data = { name: 'John' };
Object.defineProperty(data, 'name', {
get() {
console.log('获取 name 属性');
return value;
},
set(newValue) {
console.log('设置 name 属性为', newValue);
value = newValue;
}
});
- 依赖收集与派发更新:当数据被读取时,会进行依赖收集,将使用到该数据的地方(
Watcher
)收集起来。当数据变化时,通过setter
触发派发更新,通知所有依赖(Watcher
)重新计算,从而更新视图。 - Vue 3.x 的 Proxy:Vue 3.x 使用
Proxy
代替Object.defineProperty
。Proxy
可以直接代理整个对象,而不是像Object.defineProperty
那样需要对每个属性进行遍历设置。这使得对对象的拦截操作更加强大且高效。例如:
let data = { name: 'John' };
let proxy = new Proxy(data, {
get(target, prop) {
console.log('获取属性', prop);
return target[prop];
},
set(target, prop, value) {
console.log('设置属性', prop, '为', value);
target[prop] = value;
return true;
}
});
处理大量数据时的性能优化策略
- 虚拟滚动:
- 原理:只渲染当前视口可见的数据项,当用户滚动时,动态替换渲染的数据。
- 举例:使用
vue-virtual-scroll-list
组件。假设我们有一个包含大量用户信息的列表:
<template>
<div>
<virtual-scroll-list
:data="users"
:key-field="id"
:height="400"
:item-size="50"
>
<template #default="{ item }">
<div>{{ item.name }}</div>
</template>
</virtual-scroll-list>
</div>
</template>
<script>
import VirtualScrollList from 'vue-virtual-scroll-list';
export default {
components: { VirtualScrollList },
data() {
return {
users: Array.from({ length: 10000 }, (_, i) => ({ id: i, name: `User ${i}` }))
};
}
};
</script>
- 数据分批加载:
- 原理:将大量数据分成多个批次,每次只加载部分数据,当用户需要更多数据时,再加载下一批。
- 举例:假设我们从服务器获取用户列表,每次请求加载 10 条数据:
<template>
<div>
<ul>
<li v-for="user in loadedUsers" :key="user.id">{{ user.name }}</li>
</ul>
<button @click="loadMore">加载更多</button>
</div>
</template>
<script>
export default {
data() {
return {
totalUsers: [],
loadedUsers: [],
pageSize: 10,
currentPage: 0
};
},
created() {
this.fetchUsers();
},
methods: {
async fetchUsers() {
const response = await fetch(`/api/users?page=${this.currentPage}&limit=${this.pageSize}`);
const users = await response.json();
this.totalUsers = [...this.totalUsers, ...users];
this.loadedUsers = this.totalUsers.slice(0, (this.currentPage + 1) * this.pageSize);
},
loadMore() {
this.currentPage++;
this.fetchUsers();
}
}
};
</script>
- 计算属性缓存:
- 原理:对于依赖于其他数据的计算属性,Vue 会缓存其计算结果,只有当依赖数据变化时才重新计算。
- 举例:假设有一个购物车列表,需要计算总价格:
<template>
<div>
<ul>
<li v-for="item in cartItems" :key="item.id">{{ item.name }} - {{ item.price }}</li>
</ul>
<p>总价格: {{ totalPrice }}</p>
</div>
</template>
<script>
export default {
data() {
return {
cartItems: [
{ id: 1, name: '商品1', price: 10 },
{ id: 2, name: '商品2', price: 20 }
]
};
},
computed: {
totalPrice() {
return this.cartItems.reduce((acc, item) => acc + item.price, 0);
}
}
};
</script>
这样,只有当 cartItems
中的数据变化时,totalPrice
才会重新计算,提高了性能。