Vue相关面试题

本文详细探讨了Vue的双向数据绑定原理,组件中data为何必须是函数,v-if与v-show的区别,v-for的key值作用,数据更新不触发视图的解决方法,$nextTick的使用场景,vue-router的钩子函数执行顺序,Vuex的核心概念和运行机制,以及axios的封装技巧。这些是Vue开发者面试中的常见问题,理解并掌握这些知识点对于提升Vue技能至关重要。
摘要由CSDN通过智能技术生成


一、vue双向数据绑定原理

数据双向绑定 vue.js是采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty() 来对Vue的数据进行数据劫持,在数据变动时发布消息给订阅者,触发相应的监听回调来渲染视图。

observer:会对data里所有属性进行数据劫持和数据代理,使数据拥有get和set方法
compile:对模板进行解析,将模板中的变量替换成数据,然后初始化渲染页面视图
watcher:负责数据监听,当数据发生改变通知订阅者,调用视图更新函数更新视图

Object.defineProperty()方法

语法:

Object.defineProperty(obj, prop, descriptor)

三个参数:

obj: 必需。目标对象;
prop: 必需。需定义或修改的属性的名字;
descriptor: 必需。目标属性所拥有的特性;

<input type="text" id="in"/>
输入的值为:<span id="out"></span>
 <script>
     var int = document.getElementById('in');
     var out = document.getElementById('out');
     var obj = {};
     Object.defineProperty(obj, 'msg', {
         enumerable: true,
         configurable: true,
         set (newVal) {
             out.innerHTML = newVal;
         }
     })
     int.addEventListener('input', function(e) {
         obj.msg = e.target.value;
     })
 </script>

二、组件中data为什么是个函数

组件中定义data属性,只能是一个函数

<script>
export default {
  data() {
    return {
      name:"只能是函数"
    };
  }
};
</script>
  • 组件实例对象data必须为函数,目的是为了防止多个组件实例对象之间共用一个data,产生数据污染。

三、v-if和v-show的区别

共同点v-ifv-show 都能实现元素的显示隐藏

区别

v-if 是动态的向DOM树内添加或者删除DOM元素;
v-show 是通过设置DOM元素的display样式属性控制显隐;

v-if 切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件;
v-show只是简单的基于css切换;

v-if更适合数据的筛选和初始渲染
v-show更适合元素的切换

四、v-if和v-for的优先级

首先:永远不要把 v-ifv-for 同时用在同一个元素上
其次:当 Vue 处理指令时,v-forv-if 具有更高的优先级

v-forv-if优先,如果每一次都需要遍历整个数组,将会影响速度

// 错误写法
<li
  v-for="user in users"
  v-if="user.isActive"
  :key="user.id"
>
  {{ user.name }}
</li>

如上情况,即使100个user中之需要使用一个数据,也会循环整个数组。

// 正确写法
computed: {
 activeUsers: function () {
   return this.users.filter(function (user) {
     return user.isActive
   })
 }
}
<ul>
 <li
    v-for="user in activeUsers"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>

五、v-for中的key值的作用

key值代表唯一

当我们在使用v-for时,需要给单元加上key

<ul>
    <li v-for="item in data" :key="item.id">...</li>
</ul>

key是给每一个vnode的唯一id,也是diff的一种优化策略,可以根据key,更准确, 更快的找到对应的vnode节点

在这里插入图片描述

我们需要使用key来给每个节点做一个唯一标识,Diff算法就可以正确的识别此节点,找到正确的位置区插入新的节点。

key的作用主要是为了高效的更新虚拟DOM。另外vue中在使用相同标签名元素的过渡切换时,也会使用到key属性,其目的也是为了让vue可以区分它们

六、修改数据页面不更新的原因和解决方案

原因:对象是引用类型,直接改变对象的某属性但是指向地址没变,vue不一定能监控到,所以当我们新建一个对象,就直接改变了他的指向地址。

使用下面这些方法操作数组,其数据会被vue监测

push()、pop()、shift()、unshift()、splice()、sort()、reverse()可被vue监测到。

解决方案

Vue.set( target, propertyName/index, value )

参数:
target:要修改的对象或数组
propertyName/index:属性或下标
value:修改后的value值

Object.assign()

直接使用 Object.assign() 添加到对象的新属性不会触发更新

$forceUpdate

$forceUpdate迫使Vue 实例重新渲染

小结

  • 如果为对象添加少量的新属性,可以直接采用Vue.set()

  • 如果需要为新对象添加大量的新属性,则通过Object.assign()创建新对象

  • 如果你需要进行强制刷新时,可采取$forceUpdate() (不建议)

七、$nextTick()

1. 什么是Vue.nextTick()??

在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM

理解nextTick(),是将回调函数延迟在下一次dom更新数据后调用,
简单的理解是:当数据更新了,在dom中渲染后,自动执行该函数

<template>
  <div class="hello">
    <div>
      <button id="firstBtn" @click="testClick()" ref="aa">{{testMsg}}</button>
    </div>
  </div>
</template>
 
<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      testMsg:"原始值",
    }
  },
  methods:{
    testClick:function(){
      let that=this;
      that.testMsg="修改后的值";
      console.log(that.$refs.aa.innerText);   //that.$refs.aa获取指定DOM,输出:原始值
    }
  }
}
</script>

2. 使用this.$nextTick()

methods:{
    testClick:function(){
      let that=this;
      that.testMsg="修改后的值";
      that.$nextTick(function(){
        console.log(that.$refs.aa.innerText);  //输出:修改后的值
      });
    }
  }

注意:Vue 实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新。$nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用 $nextTick,则可以在回调中获取更新后的 DOM

3. Vue.nextTick(callback) 使用原理:

原因是,Vue是异步执行dom更新的,一旦观察到数据变化,Vue就会开启一个队列,然后把在同一个事件循环 (event loop) 当中观察到数据变化的 watcher 推送进这个队列。如果这个watcher被触发多次,只会被推送到队列一次。这种缓冲行为可以有效的去掉重复数据造成的不必要的计算和DOM操作。而在下一个事件循环时,Vue会清空队列,并进行必要的DOM更新。

当你设置 vm.someData = ‘new value’DOM 并不会马上更新,而是在异步队列被清除,也就是下一个事件循环开始时执行更新时才会进行必要的DOM更新。如果此时你想要根据更新的 DOM 状态去做某些事情,就会出现问题。。为了在数据变化之后等待 Vue 完成更新 DOM ,可以在数据变化之后立即使用 Vue.nextTick(callback) 。这样回调函数在 DOM 更新完成后就会调用。

八、vue-router钩子函数和执行顺序

vue-router的导航守卫实际和组件的生命周期都是同一类型的钩子函数,在一个特定时间内会触发。
导航守卫有三个类型,分别是全局的钩子(针对整个路由器实例),单个路由对象的钩子和组件内的钩子。

const router = new VueRouter({
  mode: "history",
  base: process.env.BASE_URL,
  routes,
});
//全局前置守卫
router.beforeEach((to, from, next) => {
});
// 全局解析守卫
router.beforeResolve((to, from, next) => {
});
// 全局后置钩子
router.afterEach((to, from) => {
});

以上三个都是全局钩子,无论是哪个路由对象被激活,这些钩子都会被触发,只是触发的时机不同。

单个路由对象的钩子:

{
    path: "/",
    name: "Home",
    component: Home,
    // 路由独享守卫
    beforeEnter: (to, from, next) => {
    },
 }

组件内的钩子:

beforeRouteEnter(to, from, next) {
    // 在渲染该组件的对应路由被 confirm 前调用
    // 不!能!获取组件实例 `this`
    // 因为当守卫执行前,组件实例还没被创建
  },
  beforeRouteUpdate(to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 可以访问组件实例 `this`
  },
  beforeRouteLeave(to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 可以访问组件实例 `this`
  }

而在Vue-Router中,导航守卫的执行顺序如下所示
在这里插入图片描述

九、Vuex的核心概念和运行机制

1. 什么是Vuex?

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,它采用集中式存储和管理程序的所有组件的数据

在这里插入图片描述
2. Vuex核心概念 五部分组成

  • state 所有的数据都存储在state中 state是一个对象
  • mutations 可以直接操作state中的数据
  • actions 只能调用mutations的方法
  • getters 类似计算属性实现对state中的数据做一些逻辑性的操作
  • modules 将仓库分模块存储

3. Vuex运行机制

在组件中通过dispatch来调用actions中的方法
actions中通过commit来调用mutations中的方法
mutations中可以直接操作state中的数据,state的数据只要一发生改变立马响应到组件中

十、axios的封装

一般我会在项目的src目录中,新建一个utils文件夹,然后在里面新建一个request.js

request.js具体内容

//导入axios依赖包
import axios  from "axios";

//2. 创建axios的实例化对象
const Server = axios.create({
    baseURL:'',//后期请求接口的基地址
    timeout: 5000,//5s超时时间
});

//3. 设置请求拦截器配置
Server.interceptors.request.use(function(config){//成功的时候
	return config
},function(error){//失败
    return Promise.reject(error);
})

//4. 配置相应拦截器的信息
Server.interceptors.response.use(function(response){
    if(response.status == 200){
        return response.data;
    }
	return response;
},function(error){//失败
    return Promise.reject(error);
});

//5. 导出模块
export default Server;

在main.js中全局使用

// 引入axios
import  axios  from "./utils/request"
Vue.prototype.$axios = axios;

以上是我总结的vue相关面试题,可能有的不足、表达不全面,可以在下面评论,互相学习,谢谢观看!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值