第一次
vue中diff算法是什么,和vue3的算法有什么差异
答:
https://www.bilibili.com/video/BV1G7411N7Ef/?share_source=copy_web&vd_source=9aa11bbce84d32572e3bbacbbb4ae71e
https://juejin.cn/post/6883788411590279176?searchId=20240121112028874951F2B4DE683D04B3#heading-6
第二次
1.无论宽度如何变化,如何设置保持长宽比为 2/1
方式一:利用定位实现
.wrapper{
position : relative;
background: #ccc;
width: 10%;
padding-bottom : 20%;
}
.inner{
position : absolute;
top : 0; left : 0; right : 0; bottom : 0;
}
</style>
<div class="wrapper">
<div class="inner">这是内容</div>
</div>
说明:其中奥妙就在于padding-bottom:20%, padding-bottom 是相对宽度的.也就是整个Wrapper的高度等于padding-bottom 的高度,Wrapper 没有内容高度.没有内容高度如何往其中放置我们准备的DIV呢?答案是 绝对定位, 所以Wrapper的样式中有position:relative, 方便子元素相对Wrapper的左顶点定位.
方式二:利用vw实现
.wrapper{
position : relative;
background: #ccc;
width: 25vw;
height: 50vw;
}
</style>
<div class="wrapper">
</div>
方式三:利用rem
.wrapper{
position : relative;
background: #ccc;
width: 2rem;
height: 4rem;
}
</style>
<div class="wrapper">
</div>
2.数组有哪些循环方式,那些能 break
循环数组的方式: for in, for of, for, forEach, map, filter,reduce
其中for in, for of, for 能直接使用break中断循环
forEach, map, filter,reduce, 不能使用break中断循环,但是可以使用throw Error阻止循环,用 try ctach包裹保证接下来的代码执行
3.vue 隔代组件怎么通讯的,有哪些方式
vue2
-
props, emits, 一层一层传递或者Vue2.4 版本提供了另一种方法
$attrs/$listeners,$attrs与$listeners是两个对象,$attrs里存放的是父组件中绑定的非 Props 属性,$listeners里存放的是父组件中绑定的非原生事件。
但是inheritAttrs: false, // 可以关闭自动挂载到组件根元素上的没有在props声明的属性 -
$emit/$on, 这种方法通过一个空的Vue实例作为中央事件总线(事件中心),用它来触发事件和监听事件,巧妙而轻量地实现了任何组件间的通信,包括父子、兄弟、跨级。 var Event=new Vue(); Event.on(事件名,data => {});(vue官方不推荐) -
vuex
-
Vue2.2.0新增API,provide/inject, provide / inject API 主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。
-
$parent/$children与ref的方式(不推荐)
vue3:
- ref 和 defineExpose, defineExpose是子组件暴露变量, ref获取子组件调用
- provide 和 inject
- pinia 是一个为 vue3 设计的状态管理库,类似 Vuex 的设计模式,通过定义 store、状态、getter 和 action,来统一管理应用程序的状态和逻辑。
- 在 Vue 3 中,可以使用第三方库 mitt 实现组件之间的通信。mitt 是一个简单且强大的事件总线库(类似于 Vue 2 中的EventBus),它提供了一种方便的方式来在不同组件之间传递事件和数据。
4.js 删除一个dom节点的方式
- 使用Node.removeChild()方法删除dom字节点
var box=document.getElementById("box");
box.parentNode.removeChild(box);
- 使用Node.remove()方法删除dom节点本身
var box=document.getElementById("box");
box.remove();
remove()方法在IE等较旧的浏览器中可能无法正常工作。所以,为了获得更好的兼容性和可靠性,应该选择
removeChild()方法或innerHTML属性
- Node.outerHTML
const inner = document.querySelector('.inner')
inner.outerHTML = ''
- Node.innerHtml
const inner = document.querySelector('.inner')
inner.parentNode.innerHTML = ''
5.闭包的使用场景有哪些
- 封装:没有模块化之前, 闭包可以用于创建私有变量和函数,从而实现信息隐藏和封装。
- 函数式编程:在函数式编程中,闭包是非常有用的工具。通过使用闭包,可以创建高阶函数、延迟执行函数、柯里化等功能。
- 定时器和事件处理:在处理定时器和事件时,闭包可以帮助保存局部状态,从而在稍后的时间点执行所需的逻辑。
- 模块模式:闭包可以用于创建模块,将相关的函数和数据封装在一起,提供一种更加模块化的编程方式。
- 回调函数:在异步编程中,闭包常常与回调函数一起使用,可以捕获周围作用域的状态,并在回调被触发时使用这些状态。
- 循环中的异步操作:在循环中进行异步操作时,使用闭包可以解决由于 JavaScript 中的变量提升导致的问题,确保在异步操作完成时能够获取到正确的循环变量值。
- 缓存:利用闭包缓存计算结果,避免重复计算,提高程序的性能。
6.项目中 vue 的使用规范有哪些
https://v2.cn.vuejs.org/v2/style-guide/
7.vue 性能提升有哪些方式
- v-for 遍历必须为 item 添加 key,且避免同时使用 v-if
- 长列表性能优化
Vue 会通过 Object.defineProperty 对数据进行劫持,来实现视图响应数据的变化,然而有些时候我们的组件就是纯粹的数据展示,不会有任何改变,我们就不需要 Vue 来劫持我们的数据,在大量数据展示的情况下,这能够很明显的减少组件初始化的时间,那如何禁止 Vue 劫持我们的数据呢?可以通过 Object.freeze 方法来冻结一个对象,一旦被冻结的对象就再也不能被修改了。
export default {
data: () => ({
users: {}
}),
async created() {
const users = await axios.get("/api/users");
this.users = Object.freeze(users);
}
};
- Vue 钩子函数之钩子事件 hookEvent,监听组件简化代码
用法:
- 通过 $on(eventName, eventHandler) 侦听一个事件;
- 通过 $once(eventName,eventHandler) 一次性侦听一个事件;
- 通过 $off(eventName, eventHandler) 停止侦听一个事件;
通常实现一个定时器的调用与销毁我可能会以以下方式实现:
export default{
data(){
timer:null // 需要创建实例
},
mounted(){
this.timer = setInterval(()=>{
//具体执行内容
console.log('1');
},1000);
}
beforeDestory(){
clearInterval(this.timer);
this.timer = null;
}
}
这种方法存在的问题是:
vue 实例中需要有这个定时器的实例,感觉有点多余。创建的定时器代码和销毁定时器的代码没有放在一起,不容易维护,通常很容易忘记去清理这个定时器。
使用 监听beforeDestory生命周期可以避免该问题,并且因为只需要监听一次,所以使用 $once 进行注册监听。
export default{
methods:{
fn(){
const timer = setInterval(()=>{
console.log('1');
},1000);
this.$once('hook:beforeDestory',()=>{ // 监听一次即可
clearInterval(timer);
timer = null;
})
}
}
}
- 组件懒加载