Vue2和Vue3的区别
主要有:
- 组合式API和选择式API
- TypeScript的支持
- this指针的优化
- 生命周期函数将BeforeCreate和created更改为setup
- diff算法的优化->从组件更新到节点更新
- 响应式原理从Object.defineProperty到Proxy+Reflect
- 响应式API的添加,增加了ref/reactive等响应式API
- Vue3支持TreeShaking
Vue3的diff和Vue2的diff
Vue2的diff就是简单的组件属性对比然后以树的形式对children进行遍历对比。
Vue3的diff的区别主要是,Vue2是全部组件内部参数遍历,Vue3的话对于组件中的响应式数据打上标记,组件检查更新时,只需要检查标记变量是否diff,对于组件中的静态变量不需要运算,将整个diff过程从组件更新到节点更新。
Vue3的watch和watchEffect
watch: 会有oldVal和newVal,需要显式得展示需要监视的响应式数据。
watchEffect: 在回调函数中使用响应式数据会自动监视其变化。
<script>
export default{
data(){
return {
count:0,
}
}
watch:{
count(newVal,oldVal){
console.log("发生变化")
}
}
}
</script>
<script>
import {ref} from 'vue'
export default{
setup(){
const count = ref(0)
watcheffect(()=>{
//在回调函数中使用count会自动监视其变化
})
return {count}
}
}
</script>
组件通信
全局:
- 事件总线eventBus
- 外部存储空间Vuex/LocalStorage等等
父子:
- v-bind + props
- attrs
- 依赖注入 provide和inject--->被CompositionAPI的ref和reactive替代
- parent和children
- ref和this.$refs
子父:
- 插槽
- emit
V-model
本质上是v-bind和v-on语法糖
v-bind是单向绑定 v-on是事件监听
<input v-model="message">
<input v-bind:value= "message" @input = "updateMessage">
<script>
export default{
data(){
return {
message:""
}
}
updateMessage(e){
this.message = e.taget.value
}
}
</script>
当然可以使用js实现响应式
<body>
<div>
<input id="input" placeholder="">
<p id="message">Message:</p>
</div>
<script>
let ipt = document.getElementById("input");
let msg = documnet.getElementById("message")
let date = {
message:""
}
ipt.addEventListener("input",function(e){
data.message = e.target.value
msg.innerText = "Message:"+data.message
})
</script>
</body>
生命周期
- beforeCreate
变量创建为赋值
- created
数据赋值完毕
——————————以上在Vue3中为setup——————————
- beforeMount
虚拟DOM构建
- Mounted
真实DOM挂载
- beforeUpdate
数据更新完毕
- Updated
更新数据成功挂载
- beforeDestory和Destoryed
DOM摧毁,一般不调用
特殊:beforeRouteEnter和beforeRouteLeave来处理路由缓存(刚发现activated和deactivated竟然Vue1.0就被停用了吗古早八股害人不浅)
路由跳转组件生命周期调用
父子组件:
父组件beforeCreate->->一直到父组件beforeMount
子组件beforeCreate->->一直到子组件Mounted
父组件Mounted
子组件beforeDestory->destoryed
父组件beforeDestory->destoryed
新旧组件:
新组件beforeCreate->->一直到新组件beforeMount
旧组件beforeDestory->destoryed
新组建Mounted
Vue是什么
MVVM模型中的VM
一款前端界面的开发框架,能够实现组件化开发,具有Vuex(Pinia)作为数据仓库,VueRouter作为路由导航工具,然后具有一系列的指令语法指令比如V-bind等等。
Vue中的设计模式
- 单例模式
全局事件总线
- 代理模式
Vue的响应式原理
- 发布订阅和观察者
到处都是,比如事件总线
- 装饰器模式
自定义指令
- 工厂模式
组件封装、复用,比如hooks内的函数,全局组件
- 迭代器模式
async和await语法糖
watch、method和computed
watch:
- oldVal和newVal
- 响应式监听
- 异步操作
computed:
- 具有缓存
- 自动响应式触发
- 响应式数据不变会直接调用缓存的值
method:
- 无缓存
- 无响应式,单纯的方法
Vue的key的作用
- 作为唯一的标识符
- 帮助Vue在diff算法中追踪节点
ref、reactive和computed
ref:
- 常用于对于基础数据结构实现响应式
- .value调用值
reactive:
- 常用于对于引用数据结构实现响应式
- 不需要.value,内部一定是响应式数据
computed:
- 计算属性
- 响应式数据变动触发
- .value调用
服务端渲染SSR
服务器端生成HTML网页,然后客户端只需要将相关文件渲染成真实DOM就行
优点:
- SEO友好
- 加载快,因为不需要等待js代码执行,数据是填充好的
Vue的路由跳转模式
hash模式:
- 网站地址+#+hash值
- window.location.hash记录hash值进行跳转
- seo相对来说不友好
- 可以自由使用浏览器的前进后退按钮
history模式:
- 创建路由时声明history模式
- 无#,seo友好
- 无法自由使用浏览器的前进后退,因为地址默认是有#的,history类似于重定向到一个地址,所以需要服务端去进行一个重定向配置
- 通过window.history的pushState()和popState()方法等实现
动态组件
<component>
实现自定义动态渲染
<template>
<div>
<button @click="showComponent('ComponentA')">显示组件 A</button>
<button @click="showComponent('ComponentB')">显示组件 B</button>
<!--动态组件-->
<component :is="currentComponent"></component>
</div>
</template>
<script>
import ComponentA from './ComponentA.vue';
import ComponentB from './ComponentB.vue';
export default {
data() {
return {
currentComponent: null,
};
},
methods: {
showComponent(componentName) {
if (componentName === 'ComponentA') {
this.currentComponent = ComponentA;
} else if (componentName === 'ComponentB') {
this.currentComponent = ComponentB;
}
},
},
};
</script>
另外还可以通过路由配置实现动态路由跳转
const routes = [{
path: '/user/:id', // 动态路由占位符 ":id"
component: UserProfile,
}];
Vite和Webpack的区别
- Vite使用的ejs的方法;Webpack使用的cjs的方法
- Vite依托于ejs能够实现按需加载;Webpack需要额外的配置
- Vite支持快速的HMR;Webpack的HMR相对较慢
- Vite配置文件十分轻量;Webpack生态链成熟,但是意味着配置复杂
Vuex中的mutation和action的区别
mutation:
- 处理同步代码
- commit触发
action:
- 处理异步代码
- dispatch触发
为什么使用commit和action主要是因为Vuex是一个单向数据流,把复杂的异步代码单独隔离开来可以更好地管理数据的状态,实现业务逻辑分离,提高代码的可维护性和一致性。
常见Header
- Content-type:application/javascript text/css application/json image/jepg image/png等等
- Etag
- Last-Modified
- Cache-control
场景题
Vue的数据更新但是页面没有响应式更新怎么办?
- nextTick去实现DOM更新后再更新数据。因为DOM更新是异步的,数据如果DOM更新异步的时候更改,就会先被Vue收集,然后在DOM更新之后统一使用nextTick进行更新。
- 另外一种可能性就是data定义了一个值假设是obj,obj具有两个属性,后续又通过赋值的方式给obj定义一个新属性,这个新属性的响应值是不会同步更新到页面上,需要使用this.$set添加属性进行更新,才会实现真正的更新。
this.$set
- object 绑定对象
- key 属性名
- value 绑定初始值
Vue错误捕获
没有什么是一个trycatch无法解决(误)
通用方法trycatch
如果是promise的话使用catch异常穿透,try catch无法捕获promise的错误,会使得整个程序崩溃
其他错误捕获方式比如window.onerror这种全局错误信息捕获,vue的话也有专门的钩子函数去进行异常捕获。
Vue的渲染流程
- 初始化,构建Vue的实例,初始化数据、监听器、事件函数等等。
- 将模板代码编译成JavaScript渲染函数,负责将模板代码以及相关数据等映射成虚拟DOM。
- 构建虚拟DOM
- 将虚拟DOM渲染成真实DOM。
- 响应式监听,通过响应原理监听相关数据。
- 组件批量更新,因为DOM更新是异步的,所以会出现数据更新但是DOM没有更新的情况。
- 销毁阶段。
Vue编译会阻塞吗?
不会阻塞主线程,Vue即使是组件引入也是在微任务等方式进行引入。
super的作用
调用父类的构造函数
如果一定要create内部操作DOM?
可以使用nextTick不然还是在mounted内操作DOM比较好
Vue的template编译流程
- 把模板编译程render函数
- 根据节点调用生成虚拟DOM
- 通过DIFF算法把虚拟DOM映射到真实DOM上
- 响应式监听数据
- 组件批量式更新,重复DIFF的步骤