面试题答案
一键面试自定义指令钩子函数执行情况
在Vue组件重新渲染时:
- bind:只会在指令第一次绑定到元素时调用一次,组件重新渲染不会再次触发。
- inserted:在被绑定元素插入父节点时调用(仅保证父节点存在,但不一定已被插入文档中),组件重新渲染不会再次触发。
- update:当组件更新,包含自身及其子组件,且元素更新但尚未更新子组件时,会调用此钩子函数。即只要组件重新渲染,该钩子函数就会执行,无论指令的值是否变化。
- componentUpdated:在组件和其所有子组件都更新后调用,组件重新渲染也会执行此钩子函数。
- unbind:只在指令从元素上解绑时调用一次,组件重新渲染不会触发。
性能优化方法
- 防抖与节流:
- 防抖:如果自定义指令中的操作(如复杂DOM操作或数据计算)是基于用户输入等频繁触发的事件,可使用防抖。例如,假设自定义指令是监听input输入触发复杂计算,代码如下:
const myDirective = { inserted: function (el, binding) { let debounceTimer; el.addEventListener('input', function () { clearTimeout(debounceTimer); debounceTimer = setTimeout(() => { // 执行复杂数据计算或DOM操作 const result = complexCalculation(binding.value); el.textContent = result; }, 300); }); } }; function complexCalculation(data) { // 模拟复杂计算 let sum = 0; for (let i = 0; i < data.length; i++) { sum += data[i]; } return sum; }
- 节流:若操作需要按一定频率执行,可使用节流。比如,自定义指令监听滚动事件触发复杂DOM操作,代码如下:
const myDirective = { inserted: function (el, binding) { let canRun = true; el.addEventListener('scroll', function () { if (!canRun) return; canRun = false; // 执行复杂DOM操作 complexDOMOperation(binding.value); setTimeout(() => canRun = true, 200); }); } }; function complexDOMOperation(data) { // 模拟复杂DOM操作,如创建多个元素并添加到el中 const fragment = document.createDocumentFragment(); for (let i = 0; i < data.length; i++) { const p = document.createElement('p'); p.textContent = `Item ${i}: ${data[i]}`; fragment.appendChild(p); } el.appendChild(fragment); }
- 缓存计算结果:如果数据计算结果不会频繁变化,可缓存计算结果。例如:
const myDirective = { inserted: function (el, binding) { let cache; function updateDOM() { if (!cache) { cache = complexCalculation(binding.value); } el.textContent = cache; } el.addEventListener('input', updateDOM); updateDOM(); } }; function complexCalculation(data) { // 模拟复杂计算 let sum = 0; for (let i = 0; i < data.length; i++) { sum += data[i]; } return sum; }
- 按需更新:在
update
钩子函数中,通过对比前后数据,判断是否真的需要执行复杂操作。例如:const myDirective = { update: function (el, binding, vnode, oldVnode) { if (binding.value!== oldVnode.data.directives[0].value) { // 执行复杂操作 const result = complexCalculation(binding.value); el.textContent = result; } } }; function complexCalculation(data) { // 模拟复杂计算 let sum = 0; for (let i = 0; i < data.length; i++) { sum += data[i]; } return sum; }