面试题答案
一键面试1. Vue 的 v - bind 动态属性绑定实现
假设我们有一个 商品列表组件
,模板代码如下:
<template>
<div>
<ul>
<li v - for="(product, index) in products" :key="index">
<img
:alt="product.name"
:src="getImageSrc(product.spec)"
/>
<p>{{ product.name }}</p>
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
products: [
{ name: '商品1', spec: '规格1' },
{ name: '商品2', spec: '规格2' }
],
imageResources: [
{ spec: '规格1', src: '图片路径1' },
{ spec: '规格2', src: '图片路径2' }
]
};
},
methods: {
getImageSrc(spec) {
return this.imageResources.find(image => image.spec === spec).src;
}
}
};
</script>
在上述代码中,通过 v - for
遍历商品列表,使用 v - bind
(: 是 v - bind 的缩写
)动态绑定 alt
属性为商品名称,通过调用 getImageSrc
方法动态获取图片的 src
属性。
2. 性能优化
- 使用计算属性代替方法调用:
- 上面代码中
getImageSrc
方法每次渲染都会被调用,对于大量商品列表会影响性能。可以使用计算属性来优化。 - 修改代码如下:
- 上面代码中
<template>
<div>
<ul>
<li v - for="(product, index) in products" :key="index">
<img
:alt="product.name"
:src="imageSrcs[index]"
/>
<p>{{ product.name }}</p>
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
products: [
{ name: '商品1', spec: '规格1' },
{ name: '商品2', spec: '规格2' }
],
imageResources: [
{ spec: '规格1', src: '图片路径1' },
{ spec: '规格2', src: '图片路径2' }
]
};
},
computed: {
imageSrcs() {
return this.products.map(product => {
return this.imageResources.find(image => image.spec === product.spec).src;
});
}
}
};
</script>
- 这样,计算属性
imageSrcs
只有在依赖数据(products
或imageResources
)发生变化时才会重新计算,提高了性能。
- 图片懒加载:
- 使用
IntersectionObserver API
或第三方库(如vue - lazyload
)实现图片懒加载。 - 以
vue - lazyload
为例,安装npm install vue - lazyload
后,在main.js
中配置:
- 使用
import Vue from 'vue';
import VueLazyload from 'vue - lazyload';
Vue.use(VueLazyload);
- 模板中修改图片绑定:
<template>
<div>
<ul>
<li v - for="(product, index) in products" :key="index">
<img
v - lazy="imageSrcs[index]"
:alt="product.name"
/>
<p>{{ product.name }}</p>
</li>
</ul>
</div>
</template>
- 这样只有当图片进入视口时才会加载,减少了初始渲染时的请求数量,提升性能。
- 虚拟列表:
- 当商品列表非常长时,可以使用虚拟列表技术,如
vue - virtual - scroll - list
。 - 安装
npm install vue - virtual - scroll - list
,在组件中使用:
- 当商品列表非常长时,可以使用虚拟列表技术,如
<template>
<div>
<virtual - scroll - list
:data="products"
:height="300"
:item - height="50"
key - field="name"
>
<template #default="{ item }">
<img
:alt="item.name"
:src="getImageSrc(item.spec)"
/>
<p>{{ item.name }}</p>
</template>
</virtual - scroll - list>
</div>
</template>
<script>
import VirtualScrollList from 'vue - virtual - scroll - list';
export default {
components: {
VirtualScrollList
},
data() {
return {
products: Array.from({ length: 1000 }, (_, i) => ({ name: `商品${i + 1}`, spec: `规格${i % 2 === 0? '规格1' : '规格2'}` })),
imageResources: [
{ spec: '规格1', src: '图片路径1' },
{ spec: '规格2', src: '图片路径2' }
]
};
},
methods: {
getImageSrc(spec) {
return this.imageResources.find(image => image.spec === spec).src;
}
}
};
</script>
- 虚拟列表只渲染可见区域的商品,大大减少了 DOM 数量,提高了渲染性能。