2020 前端面试题上 vue篇

本文深入探讨Vue.js框架的核心概念,包括双向绑定、v-model原理、组件通信、axios拦截器配置、自定义指令、事件修饰符、Vuex管理、watch与computed区别等。并讲解了性能优化策略,如防抖、节流、图片懒加载等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

没有特别的幸运,那么就特别的努力!!!

vue篇

Vue.js是一套构建用户界面的渐进式框架。与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计。Vue 的核心库只关注视图层,并且非常容易学习,非常容易与其它库或已有项目整合。另一方面,Vue 完全有能力驱动采用单文件组件和Vue生态系统支持的库开发的复杂单页应用。

vue 双向绑定原理

Vue是采用数据劫持结合发布/订阅模式的方式,通过Object.defineProperty() 来劫持各个属性的setter,getter,然后通知订阅者,订阅者会触发它的update方法,对视图进行更新。

v-model 的原理

v-model是vue的一个语法糖,通过v-bind去单项绑定vue实例里面的data数据,然后再通过各种事件比如@change @input等去进行触发事件,从而达到修改实例数据的值

● text 和 textarea 元素使用 value 属性和 input 事件;
● checkbox 和 radio 使用 checked 属性和 change 事件;
● select 字段将 value 作为 prop 并将 change 作为事件

Vue2.X通过Object.defineProperty() 与 Proxy

Object.defineProperty() 的问题主要有三个
1.不能监听数组变化
2.必须遍历对象的每一个属性
3.必须深层遍历嵌套对象(这样递推会花费大量的时间)

Proxy
1.支持数组:Proxy 不需要对数组的方法进行重载,省去了众多 hack
2.针对对象:针对整个对象,而不是对象的某个属性,所以也就不需要对 keys 进行遍历。
3.Proxy 的第二个参数可以有 13 种拦截方法,这比起 Object.defineProperty() 要更加丰富
4.作为新标准被各大浏览器所接受。

scoped样式穿透

*** 对于less或者sass等预编译,是不支持>>>操作符的,可以使用/deep/来替换>>>操作符
方法一: deep

<style lang="less" scoped>
    .wrap /deep/ .box{
        background: red;
    }
</style>

有时候 /deep/ 也会失效
当在scope样式中使用/deep/飘红报错时,可以使用::v-deep代替。

::v-deep

方法二: 深度选择器

<style scoped>
    .parent >>> .child {
        background: red
      }
</style>

三目运算符

微信小程序单条件 class=“{{ index2 ? ‘active’:’ ’ }}”
微信小程序多条件 class="{{ index1 ? ‘active’:’ ’ }} {{ index2 ? ‘activeT’:’ ’ }} {{ index3 ? ‘activeH’:’ ’ }}" (以空格分隔)

VUE 单条件判断 :class=" index1? ‘active’:’ ’ " 或者 :class="{borderbottom:index1}"
VUE 多条件判断 :class="{‘redRoom’: items.status=== 1, ‘greenRoom1’: Number(items.status) === 2, greenRoom2: Number(items.status) > 2}" (以,分隔)

//vue
<div :class="{borderbottom:index1}"></div>
<div :class="{'redRoom': items.status=== 1, 'greenRoom1': Number(items.status) === 2, greenRoom2: Number(items.status) > 2}"></div>

//小程序
<view class="{{ index2 ? 'active':'' }}"></view>
<view class="{{ index1 ? 'active':'' }} {{ index2 ? 'activeT':'' }} {{ index3 ? 'activeH':'' }}"></view>

组件之间的传值通信

  1. 父组件给子组件传值通过props
  2. 子组件给父组件传值通过$emit触发回调
  3. 兄弟组件通信,通过实例一个vue实例eventBus作为媒介,要相互通信的兄弟组件之中,都引入eventBus
  4. 多级组件传递数据,仅仅传递数据不做中间处理, a t t r s / attrs/ attrs/listeners
    $attrs 存放父组件中非绑定Props属性
    $listeners 存放父组件中绑定非原生事件
  5. provide / inject API 主要解决了跨级组件间的通信问题,
    主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入关系
  6. 公共组件仓库vuex
    https://segmentfault.com/a/1190000019208626 参考组件传值6种

axios拦截器怎么配

// 添加请求拦截器
axios.interceptors.request.use(function (config) {
    // 在发送请求之前做些什么
    return config;
}, function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
});
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
    // 对响应数据做点什么
    return response;
  }, function (error) {
    // 对响应错误做点什么
    return Promise.reject(error);
  })

自定义指令

通过directives指令,里面有几个钩子 最常用的就是bind,只调用一次执行初始化操作,它里面有两个参数 bind(el,binding){} el可以直接操作dom,binding一个对象,里面包含property一些属性。

directives:{ //自定义局部指令
      focus:{
           bind(el,binding){ },
            
           inserted(el,binding){
                 el.focus();
           }
      }
 }
1.自定义preventReClick.js文件
import Vue from 'vue'
 
const preventReClick = Vue.directive('preventReClick', {
  inserted: function (el, binding) {
    el.addEventListener('click', () => {
      if (!el.disabled) {
        el.disabled = true
        setTimeout(() => {
          el.disabled = false
        }, binding.value || 3000)
      }
    })
  }
})
 
export { preventReClick }

2.在main.js中引用
import { preventReClick } from './utils/preventReClick.js'
 
Vue.use(preventReClick)

3.使用
<el-button @click="putHandler(2)" v-preventReClick>完 成</el-button>

事件修饰符

.stop - 阻止冒泡
.prevent - 阻止默认事件
.capture - 阻止捕获
.self - 只监听触发该元素的事件
.once - 只触发一次
.left - 左键事件
.right - 右键事件
.middle - 中间滚轮事件

<!-- 阻止单击事件冒泡 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>

.lazy

在默认情况下, v-model 在 input 事件中同步输入框的值与数据,但你可以添加一个修饰符 lazy ,从而转变为在 change 事件中同步:

<!-- 在 "change" 而不是 "input" 事件中更新 -->
<input v-model.lazy="msg" >

.number

如果想自动将用户的输入值转为 Number 类型(如果原值的转换结果为 NaN 则返回原值),可以添加一个修饰符 number 给 v-model 来处理输入值:

<input v-model.number="age" type="number">

.trim

如果要自动过滤用户输入的首尾空格,可以添加 trim 修饰符到 v-model 上过滤输入:

<input v-model.trim="msg">

vuex

vuex:模块化管理,相当于一个公共组将仓库
vuex五大核心属性:state,getter,mutation,action,module
事实上4个重要参数,module将 store 分割成模块,每个模块包含上面4个参数,使得结构更加完善。

四个重要参数(state,getters , mutations , actions)
查-----> state (物质)-----存放数据 $store.state.XXX
查------> getters 特定的物质------ $store.getters.XX

改-------> mutations 仓库管理员-------- 唯一 改变数据state值
一般放同步数据,不推荐异步写法 且 只能单独改变
改-----> actions 仓库总监 不能之间改变数据,必须通过commit方法 提交给mutations,从而改变state值
异步处理,流程判断mount

运用:Actions
在mounted:{} 方 法 里 面 — — t h i s . 方法里面——this. this.store.dispatch(“getGoods”)
方法2:辅助函数——mapActions——mounted:{}$方法里面 直接this.getGoods()

computed 和 watch vs methods区别

computed-----计算属性 该属性是将数据挂载vue实例上 具有缓存 优点:避免重复计算
watch------监听 起 观察作用 监听已经挂载vue实例上的数据(data里面值)

我们可以使用 methods 来替代 computed,效果上两个都是一样的
computed 是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值。
而使用 methods ,在重新渲染的时候,函数总会重新调用执行。

filter与computed

<li v-for="n in evenNumbers">{{ n }}</li>

data: {
  numbers: [ 1, 2, 3, 4, 5 ]
},
computed: {
  evenNumbers: function () {
    return this.numbers.filter(function (number) {
      return number % 2 === 0
    })
  }
}

计算属性——判断是否有图片

<img class="cImg" :src="formatFull(item.picture)" alt="">

computed: {
    formatFull() {
     return function(image) {
        if(image) {
          return ourl + image
        }else {
            return defaultImg
        }
      }
    }
  },

watch

watch可以监听哪些值?
vue中的watch监听,除了监听data中的数据 — 还可以监听props、 r o u t e 、 route、 routeemit、computed

export default {
        data() {
            return {
                floorData:nul
        },
        watch:{  // 监听props
        floorData:(newVal,oldVal) => {
                console.log(newVal,oldVal);
            }
 } }

//监听路由
watch:{   //监听路由变化
    $route( to , from ){  
       console.log( to , from )
        // to , from 分别表示从哪跳转到哪,都是一个对象
        // to.path  ( 表示的是要跳转到的路由的地址 eg: /home );
     }
}

示例:
新建 userinfo = { name: “小明”, age: “18”, }
vue中watch监听name的方法

 // 1. 可以结合计算属性的方法实现
 {
  ......
   watch: {
     nm () {
       console.log(this.nm)
     }
   },
    computed: {
      nm () { return this.userinfo.name }
   }
  ...... 
}

// 2. 可以通过配置 deep 为true实现
// 监听对象的某个值
{
  ......
   watch: {
     'userinfo.name' () {
       console.log(this.nm)
     }
   }
  ......  
}

// 直接监听整个属性,消耗大
{
  ......
   watch: {
     userinfo () {
       handler () {
           console.log(this.nm)
       },
       deep: true
     }
   }
  ......  
}        

v-if & v-show & v-for

v-show / v-if
v-if判断条件少 v-show适用于频繁切换
v-if:直接操作dom树的新增和移除。
v-show隐藏则是为该元素添加css–display:none,dom元素还在。

当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级。
解决方案:
v-for和v-if不应该一起使用,必要情况下应该替换成computed 计算属性,filter过滤。

v-bind & v-mode

v-bind:绑定属性: :style :src :class

<div :class="[Type==2?'timeDate active':'timeDate']"></div>

v-mode:在表单控件或者组件上创建 双向绑定。(可以理解数据的双向绑定)
表单事件——@change,@input 实时触发,@click

vue生命周期

生命周期: Vue 实例从创建到销毁的过程,就是生命周期。
从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、销毁等一系列过程,称之为 Vue 的生命周期。

beforeCreate 虚拟dom创建前 el,data都是undefined =>用于加入loading动画
created 虚拟dom创建完成,el是underfinded 而data(数据)是初始化 =>结束loading动画

beforeMount 元素挂载前, el,data已经初始化 =>虚拟dom解析, 数据未渲染
mounted 元素挂载后 => 对应的数据渲染完成

beforeUpdate 更新前
updated 更新后

beforeDestroy 销毁前 => 用于定时器的清除,事件销毁等
destroyed 销毁后

$set , $get()

vue中set用途——vue实例已经创建好了,有时候需要再次给数据赋值时,并不能在视图中改变
Vue.set(object,key,value) //设置,添加属性 data里面对象
//第一个操作对象,第二个键名,第三个键值

 var vm=new Vue({
        el:'#itapp',
        data:{
            user:{
                id:1001,
                name:'tom'
            }
        },

this.$set(object,key,value)   //实例方法,添加属性(推荐)
    //this.$set(this.user,'age',25);

get()读取时会触发

trim 过滤首位空格

如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符:

<input v-model.trim="msg">

谈谈你对 keep-alive 的了解

keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,避免重新渲染

  1. 用于缓存组件
  2. 对应两个钩子函数 activated 和 deactivated ------当组件激活时触发activated,当组件移除时触发deactivated

组件中 data 为什么是一个函数?

组件中data必须是一个函数,不然data里面的属性会相互影响
如果data是一个对象,这样作用域就没有隔离,子组件中的data会相互影响

vue 父组件调用子组件方法

父组件-------- this.$ref

//父组件
<template>
  <div>
    <button @click="clickParent">点击</button>
    <child ref="mychild"></child>
  </div>
</template>
 
<script>
  import Child from './child';
  export default {
    name: "parent",
    components: {
      child: Child
    },
    methods: {
      clickParent() {
        this.$refs.mychild.parentHandleclick("嘿嘿嘿");
      }
    }
  }
</script>
//子组件
<template>
  <div>
    child
  </div>
</template>
 
<script>
  export default {
    name: "child",
    props: "someprops",
    methods: {
      parentHandleclick(e) {
        console.log(e)
      }
    }
  }
</script>

vue-router 路由模式有几种?

默认hash

  1. hash 支持所有浏览器,
    hash发生变化的url都会被浏览器记录下来,
    hashchange 事件来监听 hash 值的变化
  2. History HTML5 提供了 History API 来实现 URL 的变化,
    URL中的#号就被去除了。
    可以使用 popstate 事件来监听 url 的变化
    history.pushState() 或 history.replaceState() 不会触发 popstate 事件,这时我们需要手动触发页面跳转(渲染)
  3. abstract 支持所有 JavaScript 运行环境

动态路由

2种方案:

  1. 后端处理,前端处理就比较方便,Router.addRoutes()
  2. 前端处理,再路由界面添加属性meta:{},再借助路由守卫(to,from,next)

delete与vue.delete区别?

delte会删除数组的值,但是它依然会在内存中占位置
而vue.delete会删除数组在内存中的占位

let arr1 = [1,2,3]
let arr2 = [1,2,3]
delete arr1[1]
this.$delete(arr2,2)
console.log(arr1)    //【1, empty, 3】
console.log(arr2)    //【1,2】

Vue2.0 v-for 中 :key 到底有什么用?

1.用 id 作为 key 就行了
2.永远不要用 index 作为 key
3. 通过这个key 我们的diff操作可以更准确·更快速

vue相对于jq好处,优点

vue将数据层和视图层分离开。采用虚拟dom,减少了dom操作,(虚拟dom 是js对象模拟dom,在操作过程中不会直接操作dom,等待虚拟dom操作完成,只改变开始时和结束时变化,这里面才有diff算法)
所以说 vue不管代码结构,操作性能,模块化,单页面运用都要优于jq

axios怎么做到同步

es7 async/await

ajax与axios的区别?

axios提供并发封装(同时进行多个请求,不在乎返回顺序),体积小
axios 是一个基于Promise 用于浏览器和 node 的 HTTP 客户端,本质上也是对原生XHR的封装

sass与less区别

a.编译环境不同,sass在服务端处理,less在浏览器端处理
b.变量符号不一样,less用@ sass用$
c.sass支持条件语句,less不支持

你都做过哪些Vue的性能优化?

尽量减少data中的数据,data中的数据都会增加getter和setter,会收集对应的watcher
v-if和v-for不能连用
SPA 页面采用keep-alive缓存组件
使用路由懒加载、异步组件
防抖、节流
图片懒加载
第三方模块按需导入

结语

由于精力时间及篇幅有限,这篇就先写到这。大家慢慢来不急!!!
下篇内容我会写下
webpack相关配置,性能优化
js相关基础,闭包,原型,原型链,防抖,节流等
css一些相关样式
es6
浏览器
服务器,nginx等

在面试中,很多领域并没有真正的答案,能回答到什么样的深度,还是得靠自己真正的去使用和研究。

希望能帮助到大家,同时祝愿大家在开发旅途中愉快!!!

拿着 不谢 请叫我“锤” !!!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值