前端面试(VUE篇)

VUE双向绑定原理

通过数据劫持结合 “发布者-订阅者模式”:

1.实现一个监听器Observer:利用了 Object.defineProperty() 方法重新定义了对象获取属性值(get)和设置属性值(set)的操作来劫持并监听所有属性的setter,getter,如果有变动的,就通知订阅者。

2.实现一个订阅者Watcher,可以收到属性的变化通知并执行相应的函数,从而更新视图。

3.实现一个解析器Compile,可以扫描和解析每个节点的相关指令,并根据初始化模板数据以及初始化相应的订阅器。

VUE生命周期

Vue中实例或者组件从创建到消灭中间经过的一系列过程,在这个过程中,他经历了从开始创建、初始化数据、编译模板、挂载Dom、渲染→更新→渲染、卸载等一系列过程:

创建前后 载入前后 更新前后 销毁前后

1.new Vue()实例:初始化生命周期,事件( o n c e 、 once、 onceoff、 e m i t 、 emit、 emiton)以及定义createElement函数(初始化render时定义)

2.执行beforeCreate

3.数据初始化:定义data数据,方法以及事件,并且完成数据劫持observe、给组件实例配置watcher观察者实例

4.执行created,可以开始调用方法进行数据请求

5.判断当前是否有el参数,如果有,再判断是否有template参数。如果没有el,会等待调用$mount(el)方法。

6.将模板或者el转换为render函数

7.执行beforMount

8.先生产一个虚拟dom,进行保存,然后再开始将render渲染成为真实的dom。渲染成真实dom后,会将渲染出来的真实dom替换掉原来的vm. e l ,然后再将替换后的 el,然后再将替换后的 el,然后再将替换后的el append到页面内。

9.执行mounted mounted函数内可以操作dom,因为这个时候dom已经渲染完成了。

10.当状态数据发生变化时,触发beforeUpdate,开始将变化后的数据渲染到页面上(这里会判断当前的_isMounted是不是为ture,并且_isDestroyed是不是为false,也就是说,保证dom已经被挂载的情况下,且当前组件并未被销毁,才会走update流程)

11.重新生成一个新的虚拟dom(Vnode),然后会拿这个最新的Vnode和原来的Vnode进行比较计算,算出最小的更新范围,从而更新render函数中的最新数据,再将更新后的render函数渲染成真实dom。

12.执行updated

13.实例销毁前,执行beforeDestroy,在这个函数内,还可以操作实例。

14.做一系列的销毁动作,解除各种数据引用,移除事件监听,删除组件_watcher,删除子实例,删除自身self等。同时将实例属性_isDestroyed置为true。

15.销毁完成后,再执行destroyed

父子组件生命周期执行顺序

加载渲染过程
父beforeCreate -> 父created -> 父beforeMount ->
子beforeCreate -> 子created -> 子beforeMount -> 子mounted
-> 父mounted

子组件更新过程
父beforeUpdate -> 子beforeUpdate -> 子updated -> 父updated

父组件更新过程
父beforeUpdate -> 父updated

销毁过程
父beforeDestroy -> 子beforeDestroy -> 子destroyed -> 父destroyed

created mounted区别

1.created是在HTML页面渲染出来之前执行,通常初始化某些属性值,可以在这个钩子函数里发请求,访问后端接口拿数据,然后再渲染成视图
2.mounted是在HTML页面渲染出来之后执行,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作,可以访问和更改数据且修改数据会触发updated、beforeUpdate钩子函数

data为何要return?

不使用return包裹的数据会在项目的全局可见,会造成变量污染;使用return包裹后数据中变量只在当前组件中生效,不会影响其他组件。
当一个组件被定义, data 必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例。如果 data 仍然是一个纯粹的对象,则所有的实例将共享引用同一个数据对象!通过提供 data 函数,每次创建一个新实例后,我们能够调用 data 函数,从而返回初始数据的一个全新副本数据对象。

watch和computed的区别

computed:
计算属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。

watch:
监听某一个值,当被监听的值发生变化时,执行对应的操作。

区别:
watch更加适用于监听某一个值的变化并做对应的操作,比如请求后台接口等,
computed适用于计算已有的值并返回结果

VUE-Router 跳转

在这里插入图片描述

this.$router.push()

router.push(location, onComplete?, onAbort?)
该方法的参数可以是一个字符串路径,或者一个描述地址的对象。

在这里插入图片描述**注:如果提供了 path,params 会被忽略,
params传参是针对name的,query传参是针对path的。query是查询参数。
在这里插入图片描述

同样的规则也适用于 router-link 组件的 to 属性。

< router-link > / < router-view>

< router-link> 定义页面中点击的部分。
< router-view> 定义显示部分,就是点击后,区配的内容显示在什么地方。
< router-link> 还有一个非常重要的属性 to,定义点击之后,要到哪里去,点击时会调用.push方法,所以参数和.push一样。

router.replace()

router.replace(location, onComplete?, onAbort?)

跟 router.push 很像,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录。

在 2.2.0+,可选的在 router.push 或 router.replace 中提供 onComplete 和 onAbort 回调作为第二个和第三个参数。这些回调将会在导航成功完成 (在所有的异步钩子被解析之后) 或终止 (导航到相同的路由、或在当前导航完成之前导航到另一个不同的路由) 的时候进行相应的调用。

router.go(n)

这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步

route 与 router的区别

router是为VueRouter的实例,是一个全局的路由对象,含有很多属性和子对象。
在这里插入图片描述
route是当前路由的实例对象,可以从里面获取name,path,params,query等

路由守卫

路由守卫相当于路由跳转时的检票员,需要根据一些条件判断所需跳转至什么页面。比如当点击商城的购物车按钮时,需先判断当前用户是否已登陆,若未登陆,需跳转至登陆页面。
写在main.js文件,或者router文件夹下的index.js文件中

路由守卫分类:
1:全局守卫: beforeEach、 afterEach
2:独享守卫(单个路由里面的钩子): beforeEnter、 beforeLeave
3:组件内守卫:beforeRouteEnter、 beforeRouteUpdate、 beforeRouteLeave

全局守卫

router.beforeEach() 进入之前触发
router.afterEach() 进入之后触发

每个守卫方法接收三个参数:
①to: Route: 即将要进入的目标路由对象(to是一个对象,是将要进入的路由对象,可以用to.path调用路由对象中的属性)
②from: Route: 当前导航正要离开的路由
③next: Function: 这是一个必须需要调用的方法,执行效果依赖 next 方法的调用参数。

全局前置守卫 beforeEach(每次切换前被调用)

1、先在需要配置路由守卫的地方加上 meta: { isAuth: true }
2、经过逻辑判断,决定跳转路由

//全局前置路由守卫————初始化的时候被调用、每次路由切换之前被调用
router.beforeEach((to, from, next) => {
    //如果路由需要跳转
    if (to.meta.isAuth) {
        //判断 如果school本地存储是qinghuadaxue的时候,可以进去
        if (localStorage.getItem('school') === 'qinghuadaxue') {
            next()  //放行
        } else {
            alert('抱歉,您无权限查看!')
        }
    } else {
        // 否则,放行
        next()
    }
})

后置路由守卫 afterEach(每次切换后被调用)

1、路由跳转之后执行的事件,可以用作跳转路由后更改网页名
2、首先路由的meta需要配置title的名字

独享路由守卫(某一个路由所单独享用的路由守卫)

beforeEnter、 beforeLeave
1、独享路由守卫只有前置没有后置
2、写在该路由内

{
    path: '/',
    name: 'Home',
    component: () => import('../views/Home.vue'),
    meta: { isAuth: true },
    beforeEnter: (to, from, next) => {
        if (to.meta.isAuth) { //判断是否需要授权
            if (localStorage.getItem('school') === 'qinghuadaxue') {
                next()  //放行
            } else {
                alert('抱歉,您无权限查看!')
            }
        } else {
            next()  //放行
        }
    }
},

组件内守卫(某一个组件所单独享用的路由守卫)

beforeRouteEnter、 beforeRouteUpdate、 beforeRouteLeave
独享路由守卫只有前置没有后置,直接写在vue文件中

//通过路由规则,进入该组件时被调用
beforeRouteEnter(to,from,next) {
  if(toString.meta.isAuth){
    if(localStorage.getTime('school')==='qinghuadaxue'){
      next()
    }else{
      alert('学校名称错误,无权限查看!')
    }
  } else{
    next()
  }
},

//通过路由规则,离开该组件时被调用
beforeRouteLeave(to,from,next) {
next()
}

VUEX

Vuex可以理解为一种开发模式或框架,通过状态集中管理驱动组件的变化,应用级的状态集中放在store中,改变状态的方式是提交mutations,异步逻辑封装在action中。

使用 Vuex 统一管理状态的好处 :

能够在 vuex 中集中管理共享的数据,利于开发和后期的维护;

能够高效的实现组件之间的数据共享,提高开发效率;

存储在 vuex 中的数据都是响应式的,能够实时保持数据与页面的同步;

Vuex的核心属性:

state:定义初始化状态
getters:获取、过滤、编辑状态,相当于计算属性
mutations:设置状态
actions:异步提交mutations ------ commit(‘setLocal’, lang)
modules:把状态管理模块化,各自的组件构成各自的模块

getters接收两个参数,第一个参数是state

vuex跨模块调用:

模块 B 的 actions 调用模块 A 的 state:

const actions = {
async [‘shop’] (store, config = {}) {
const { commit, dispatch, state, rootState } = store
console.log(rootState) // 打印根 state
console.log(rootState.vip) // 打印其他模块的 state
try {
const { data: { code, data } } = await api.post(‘shop/getShopBaseInfo’, config)
if (code === 1001) commit(‘receive’, data)
} catch(error) { console.log(error) }
}
}

actions 中的 shop 方法, 有 2 个参数, 第一个是 store, 第二个是 dispatch 调用时传过来的参数,
store 这个对象又包含了 4 个键, 其中 commit 是调用 mutations 用的, dispatch 是调用 actions 用的, state 是当前模块的 state, 而 rootState 是根 state

模块 B 的 actions调用模块 A 的 actions

dispatch(‘vip/get’, {}, {root: true})

,第一个参数是其他模块的 actions 路径,
第二个是传给 actions 的数据, 如果不需要传数据, 也必须预留,
第三个参数是配置选项, 申明这个 acitons 不是当前模块的

模块 B 的 actions调用模块 A 的 mutations

commit(‘vip/receive’, data, {root: true})

模块 B 的 actions 调用模块 A 的 getters

const actions = {
async [‘shop’](store, config = {}) {
const { commit, dispatch, state, rootState, rootGetters } = store
console.log( rootGetters[‘vip/get’] ) // 打印其他模块的 getters
}
}

store 又多了一个键: rootGetters
rootGetters 就是 vuex 中所有的 getters, 你可以用 rootGetters[‘xxxxx’] 来取其他模块的getters

————————————————————更新分割线——————————————————————

父组件如何调用子组件中的方法

在Vue3中,父组件调用子组件的方法可以通过expose和ref来实现。首先,在父组件中,我们可以使用ref指令来关联子组件,并定义一个ref来表示子组件实例,例如:

1、通过调用实例获取子组件的数据和方法

子组件通过defineExpose暴露对象和方法 :
//暴露数据方法
defineExpose({
state,
play,
});

父组件通过ref实例获取:

//定义子组件实例,名称要和上面的ref相同
const childComp = ref(null);
//访问demo组件的方法或对象
const onTry = () => {
  //获取到子组件的 title 数据 
  let msg = childComp.value.state.title;
  //调用子组件的 play方法
  childComp.value.play();
};

2、通过选项式API调用
父组件注册子组件

  components: {
    child,
  },

通过this.$ refs 指针访问子组件

  let msg = this.$refs.childComp.message;
  this.$refs.childComp.play();
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue的生命周期是指Vue组件实例在创建、更新和销毁过程中经历的一系列钩函数。具体来说,Vue生命周期包括以下几个阶段和对应的钩函数: 1. 创建阶段: - beforeCreate:在实例被创建之前被调用。此时,实例的数据、计算属性和方法都还未初始化,无法访问。 - created:在实例被创建后立即调用。此时,实例的数据、计算属性和方法已经初始化完成,但还未被挂载到DOM上。 2. 挂载阶段: - beforeMount:在挂载开始之前被调用。此时,模板编译已经完成,但还未将实例挂载到DOM上。 - mounted:在挂载完成之后被调用。此时,实例已经被挂载到DOM上,可以进行DOM操作和异步请求。 3. 更新阶段: - beforeUpdate:在数据更新之前被调用。此时,实例的数据发生变化,但DOM尚未更新。 - updated:在数据更新之后被调用。此时,实例的数据已经更新,DOM也已经重新渲染。 4. 销毁阶段: - beforeDestroy:在实例销毁之前被调用。此时,实例仍然可以访问及操作。 - destroyed:在实例销毁之后被调用。此时,实例及其相关的所有东西都已被清理,监听器和事件已被移除。 通过在这些钩函数中编写代码,可以在不同阶段执行相应的操作,比如初始化数据、发送请求、更新DOM等。这些钩函数提供了灵活的扩展和定制组件行为的机会,使开发者能够更好地控制和理解组件的生命周期。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [前端开发面试题—Vue的生命周期](https://blog.csdn.net/weixin_53231455/article/details/126446179)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [前后端分离vue.js+spring boot 计算机软件工程课程设计毕业设计 前端 后端](https://download.csdn.net/download/Amzmks/88275824)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值