八股文-Vue篇
这个问题具体要看项目和业务情况,因为组件的加载顺序是,会先执行父组件的前3个生命周期,再执行子组件的前4个生命周期。如果业务是父组件引入子组件,并且优先加载子组件的数据,那么在父组件中当前请求要放在。如果请求是在methods里封装好的,在beforeCreate里是拿不到methods的方法的。如果使用了keep-alive组件,当前组件会额外增加两个生命周期。中,让子组件的请求先去执行,让子组
一、Vue2
1. 关于生命周期
1.1 生命周期有哪些?发送请求在created还是mounted?
生命周期 | 描述 |
---|---|
beforeCreate | 组件实例被创建之前(没有dom,没有$data) |
created | 组件实例已经完全创建(没有dom,有$data) |
beforeMount | 组件挂载之前(没有dom,有$data) |
mounted | 组件被挂载到实例上之后(有dom,有$data) |
beforeUpdate | 组件数据发生变化,更新之前 |
updated | 组件数据更新之后 |
beforeDestroy | 组件实例销毁之前 |
destroyed | 组件实例销毁之后 |
mounted可以操作dom又可以操作data,还可以操作子组件;而在created的时候不能操作dom也不能操作子组件。
发送请求是异步任务,会在同步任务执行完毕之后执行,即获取到数据也是会在mounted执行完之后。
这个问题具体要看项目和业务情况,因为组件的加载顺序是,会先执行父组件的前3个生命周期,再执行子组件的前4个生命周期。如果业务是父组件引入子组件,并且优先加载子组件的数据,那么在父组件中当前请求要放在mounted
中,让子组件的请求先去执行,让子组件的数据先加载出来。
1.2 为什么发送请求不在beforeCreate里?beforeCreate和created有什么区别?
如果请求是在methods里封装好的,在beforeCreate里是拿不到methods的方法的。
beforeCreate阶段没有$data ,拿不到methods方法,created阶段有$data,拿得到methods方法。
1.3 在created中如何获取dom?
- 用异步代码获取,例如setTimeout
- 使用vue的
this.$nextTick
1.4 一旦进入到组件会执行哪些生命周期?
beforeCreate
、created
、beforeMount
、mounted
1.5 第二次或者第N次进去组件会执行哪些生命周期?
如果当前组件加入了keep-alive,只会执行activated
;
如果没有加入keep-alive依然执行前四个生命周期beforeCreate
、created
、beforeMount
、mounted
1.6 父子组件生命周期执行顺序?
父组件 beforeCreate
created
beforeMount
子组件 beforeCreate
created
beforeMount
mounted
父组件 mounted
1.7 加入keep-alive会执行哪些生命周期?
如果使用了keep-alive组件,当前组件会额外增加两个生命周期。
activated
:被 keep-alive 缓存的组件激活时调用
deactivated
:被 keep-alive 缓存的组件失活时调用。
如果当前组件加入了keep-alive,第一次进入这个组件会执行5个生命周期:beforeCreate
created
beforeMount
mounted
activated
1.8 你在什么情况下用过哪些生命周期?说一说生命周期使用场景?
created
:单一组件进行请求
mounted
:有父子组件关系的时候,进行请求;同步操作dom
activated
:处理缓存
beforeDestroy
:关闭页面的时候进行数据记录
2. 关于组件
2.1 组件通讯方式
父传子:
- v-bind绑定props。不能传孙,且有多个子组件时需要一个一个操作;子不能直接修改父组件的数据
- 子组件直接使用父组件数据
this.$parent
。子能直接修改父组件的数据 - 依赖注入provide、inject。不用逐级传递,可以实现直接传递给孙
子传父:
- 子组件自定义事件
this.$emit
。 - 父组件直接使用子组件数据:
this.$children[index].xxx
或this.$refs[name].xxx
兄弟互传:
- EventBus(
$on
接收方,$emit
发送方)
2.2 父组件如何直接修改子组件的值
this.$children[index].xxx
或 this.$refs[name].xxx
2.3 子组件如何直接修改父组件的值
this.$parent.xxx
2.4 如何找到父组件
this.$parent
2.5 如何找到根组件
this.$root
2.6 keep-alive
用来缓存当前组件
2.7 slot插槽
- 匿名插槽
- 具名插槽
- 作用域插槽:对组件传递 props 那样,向一个插槽的出口上传递 attributes
2.8 provide、inject
依赖注入,用来实现给后辈组件传递数据
2.9 如何封装组件
抽取复用部分内容,用slot插槽去实现父组件可以自定义部分特殊的内容;通过v-bind绑定props去实现获取父组件数据;通过自定义事件去实现给父组件传递数据。
3. 关于Vuex
3.1 vuex有哪些属性
Vuex是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间的数据共享。
State
用来存储公共数据源。全局共享属性。Mutation
用于同步变更state中的数据。Action
用于异步变更state中的数据,但是在Action中还是要用过触发Mutation的方式间接变更数据。Getter
用于对Store中的数据进行加工处理形成新的数据(类似于计算属性),Store中数据发生变化,Getter中的数据也会变化。针对state数据进行二次计算。moudle
属性是将store分割成模块。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块。
3.2 vuex使用state值
this.$store.state.xxx
computed: { ...mapState(['全局数据名称1','全局数据名称2',...]) }
区别:使用this.$store的方式可以直接修改(不推荐),使用辅助函数的方式不能直接修改
3.3 vuex的getters值修改
getters不可以修改
3.4 vuex的mutations和actions的区别
相同点:都是来存放全局方法的;不能有return值
区别:mutation是同步的,actions是异步的;mutation是用来修改state的,action是用来提交mutation的
3.5 vuex持久化存储
vuex本身不是持久化存储,它只是一个全局数据管理仓库。
实现方式:
- 自己写localStorage
- 使用vuex-persistedstate插件
3.6 vuex是单向数据流还是双向数据流
vuex是单向数据流
4. 关于路由
4.1 路由的模式和区别
路由模式:history、hash
区别:
- 表象不同:hash路径有一个#,history/
- history找不到当前页面会发送请求,而hash不会
- 项目打包前端自测的时候,hash可以看到内容,hsitory默认情况是看不到内容的
4.2 子路由和动态路由
详请->
Vue Router基础知识整理
4.3 路由传值
详请->
Vue Router基础知识整理
4.4 路由故障
当前页跳当前页,路径不变,参数变
import Vue from 'vue'
import VueRouter from 'vue-router'
// 解决路由重复跳转错误
const routerPush = VueRouter.prototype.push;
VueRouter.prototype.push = function (location) {
return routerPush.call(this, location).catch(err => { })
};
Vue.use(VueRouter)
4.5 $router 和 $route的区别
$router
路由管理对象(路由跳转)$route
路由单体对象,指某一条路由(获取当前路径相关)
4.6 导航守卫
-
全局守卫:全局前置守卫
router.beforeEach
:路由进入前;全局后置钩子router.afterEach
:路由进入后 -
路由独享守卫:
beforeEnter
只在进入路由时触发 -
组件内守卫:
beforeRouteEnter
在渲染该组件的对应路由被验证前调用、beforeRouteUpdate
在当前路由改变,但是该组件被复用时调用、beforeRouteLeave
在导航离开渲染该组件的对应路由时调用
5. 关于API
5.1 $set
场景:直接通过数组下标去修改数组造成相应丢失
this.$set(target,key,value)
5.2 $nextTick
等待下一次 DOM 更新刷新的工具方法。异步的。
获取更新后的dom;等待dom更新完再执行后续操作。
官方说明:当你在 Vue 中更改响应式状态时,最终的 DOM 更新并不是同步生效的,而是由 Vue 将它们缓存在一个队列中,直到下一个“tick”才一起执行。这样是为了确保每个组件无论发生多少状态改变,都仅执行一次更新。nextTick()
可以在状态改变后立即使用,以等待 DOM 更新完成。
5.3 $refs
用来获取dom
5.4 $el
获取当前组件的节点
5.5 $data
获取当前组件的data数据
5.6 $children
获取当前组件的所有子组件(一个数组)
5.7 $parent
找到当前组件的父组件,无则返回自身
5.8 $root
找到当前组件的根组件,无则返回自身
5.9 data定义数据
return里外的区别
外:需要用this;不被劫持(没有get/set),不支持双向绑定
内:被劫持,双向绑定
5.10 computed计算属性
计算结果要修改的话要通过set写法
计算属性computed:(可依赖多个属性):
- 缓存:计算属性基于其依赖进行缓存。
- 性能优化:当依赖没有改变时,多次访问计算属性不会触发重新计算
- 同步:计算属性是同步的,并在渲染过程中进行计算。
- 简洁性:对于简单的数据转换和组合,计算属性提供了更简洁的语法。
5.11 watch
监听属性watch:(只监听一个属性,可监听到数据变化前的值):
- 异步:监听属性允许你在数据变化后执行异步操作。
- 执行机制:监听属性在数据改变后触发,而不是在渲染过程中。
- 可访问DOM:在监听属性函数中,你可以访问组件的DOM。
- 对复杂逻辑的支持:如果你需要进行复杂的逻辑判断或操作,监听属性是更好的选择。
初始化的时候先执行一次:immediate:true
对象数据深层监听:deep:true
5.12 methods和computed的区别
computed返回结果有缓存, methods没有。当返回结果在dom中多次用到的时候,用computed性能更佳。
5.13 computed、watch的区别
监听属性watch:(只监听一个属性,可监听到数据变化前的值):
- 异步:监听属性允许你在数据变化后执行异步操作。
- 执行机制:监听属性在数据改变后触发,而不是在渲染过程中。
- 可访问DOM:在监听属性函数中,你可以访问组件的DOM。
- 对复杂逻辑的支持:如果你需要进行复杂的逻辑判断或操作,监听属性是更好的选择。
计算属性computed:(可依赖多个属性):
- 缓存:计算属性基于其依赖进行缓存。
- 性能优化:当依赖没有改变时,多次访问计算属性不会触发重新计算
- 同步:计算属性是同步的,并在渲染过程中进行计算。
- 简洁性:对于简单的数据转换和组合,计算属性提供了更简洁的语法。
5.14 props和data谁的优先级更高
props
> methods
> data
> computed
> watch
6. 过关于指令
6.1 如何自定义指令
全局:main.js
局部:组件内
Vue2自定义指令说明文档
Vue3自定义指令说明文档
vue2vue3指令钩子有所区别
6.2 vue单向绑定
双向绑定:v-model
单向绑定:v-bind,props接收
6.3 v-if 和 v-for 优先级
vue2中v-for的优先级高于v-if
vue3中v-if的优先级高于v-for
不建议在同一节点一起用
6.4 v-if 和 v-show的区别
- 控制手段:v-show隐藏则是为该元素添加css–display:none,dom元素依旧还在。v-if显示隐藏是将dom元素整个添加或删除
- 编译过程:v-if切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件;v-show只是简单的基于css切换
- 编译条件:v-if是真正的条件渲染,它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。只有渲染条件为假时,并不做操作,直到为真才渲染
- 初次加载v-i
7. 关于原理
7.1 $nextTick原理
功能:等待下一次 DOM 更新刷新的工具方法。获取更新后的dom。异步。
$nextTick(callback) {
return Promise.resolve().then(() => {
callback();
})
}
官方说明:当你在 Vue 中更改响应式状态时,最终的 DOM 更新并不是同步生效的,而是由 Vue 将它们缓存在一个队列中,直到下一个“tick”才一起执行。这样是为了确保每个组件无论发生多少状态改变,都仅执行一次更新。nextTick()
可以在状态改变后立即使用,以等待 DOM 更新完成。nextTick()
可以在状态改变后立即使用,以等待 DOM 更新完成。你可以传递一个回调函数作为参数,或者 await 返回的 Promise。
7.2 双向绑定原理
通过Object.defineProperty
劫持数据发生的改变,如果数据发生了改变(在set进行赋值的),触发update方法进行更新节点内容({{str}}),从而实现数据双向绑定的原理。
双向数据绑定是采⽤数据劫持结合发布者-订阅者模式的⽅式,通过Object.defineProperty()
来劫持各个属性的setter
,getter
,在数据发生变动时发布消息给订阅者,触发相应的监听回调。这样就可以实现数据的双向绑定 关键点是Object.defineProperty()
劫持属性。
8. 其他相关
8.1 什么是渐进式框架
渐进式框架(Progressive Framework)是一种软件开发框架的设计理念,它允许开发者根据项目需求逐步引入和应用框架的不同特性和功能。
8.2 scoped原理
**作用:**让样式在本组件中生效,不影响其他组件
**原理:**给元素节点新增自定义属性,然后css根据属性选择器添加样式
8.3 vue中怎么做样式穿透
::v-deep
【博主:努力的小朱同学】vue 之 CSS进行样式穿透的方法(/deep/、::v-deep、>>> 、:deep、额外的全局<style>)
二、Vue3
1. Vue2和Vue3的区别
双向绑定原理
- Vue2.0x 的响应式是通过
Object.defineProperty
对数据进行劫持,并结合发布订阅者模式实现。 Vue 利用 Object.defineProperty 创建一个 observe 来劫持监听所有的属性,把这些属性(遍历data)全部转为 getter 和 setter。Vue 中每个组件实例都会对应一个 watcher 实例,它会在组件渲染的过程中把使用过的数据属性通过 getter 收集为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。(Vue2后期添加的属性劫持不到,会造成数据更新但视图没有更新) - vue3.0x的响应式是通过ES6种的
Proxy
代理,Proxy能够拦截目标对象上的操作(如获取、设置等),从而实现对数据的追踪和更新。与之前版本不同的是,Vue.js 3无需再手动编写getter和setter函数,只需要将原始数据包装成Proxy对象后就可以开始追踪和更新。Proxy 不仅可以代理对象,还可以代理数组。还可以代理动态增加的属性。
生命周期
tip:setup 是围绕 beforeCreate 和 created 生命周期钩子运行的,所以不需要显式地去定义
根节点
Vue3 支持多个根节点,也就是 fragment;而Vue2只支持一个根节点
API风格
-
Vue2 是
选项API(Options API
),一个逻辑会散乱在文件不同位置(data、props、computed、watch、生命周期钩子等),导致代码的可读性变差。当需要修改某个逻辑时,需要上下来回跳转文件位置。 -
Vue3 除了选项式API外还支持
组合式API(Composition API)
则很好地解决了这个问题,可将同一逻辑的内容写到一起,增强了代码的可读性、内聚性,其还提供了较为完美的逻辑复用性方案。
2. Vue3如果用setup怎么组织代码?
用hooks,就是让功能模块细分(提升项目的可维护性)
3. Vue3的setup写法怎么使用this?
import { getCurrentInstanc e} from "vue";
const this = getCurrentInstance();
const { ctx } = getCurrentInstance();
4. Vue3常用api
API 参考:https://cn.vuejs.org/api/
5. Vue3常用的响应式数据类型
ref()
:接受一个内部值,返回一个响应式的、可更改的 ref 对象,此对象只有一个指向其内部值的属性 .value。(基本类型)reactive()
:返回一个对象的响应式代理。(复杂类型)toRef()
:可以将值、refs 或 getters 规范化为 refs (3.3+)。也可以基于响应式对象上的一个属性,创建一个对应的 ref。这样创建的 ref 与其源属性保持同步:改变源属性的值将更新 ref 的值,反之亦然。(解构一个值)toRefs()
:将一个响应式对象转换为一个普通对象,这个普通对象的每个属性都是指向源对象相应属性的 ref。每个单独的 ref 都是使用 toRef() 创建的。(解构多个值)
6. Teleport组件
Vue3 提供 Teleport 组件可将部分 DOM 移动到 Vue app 之外的位置。比如项目中常见的 Dialog 弹窗
<button @click="dialogVisible = true">显示弹窗</button>
<teleport to="body">
<div class="dialog" v-if="dialogVisible">
我是弹窗,我直接移动到了body标签下 </div>
</teleport>
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)