每个前端都要掌握的[Vue 基本知识] 金三银四 求职必备

152 阅读6分钟

每个前端都要掌握的[Vue 基本知识] 金三银四 求职必备

Vue的优缺点?

优点:渐进式,组件化开发,虚拟dom,单页面路由,数据视图分离

缺点:单页面不利于SEO,不兼容IE,首屏加载时间长

1.渐进式的意思就是Vue的全家桶有很多,你可以选择不用,或者选择几样去用,或者只用一个,比如不用vuex

2.组件化开发就是可以封装复用组件

3.虚拟DOM是因为频繁操作真实DOM是很昂贵的,所以要虚拟DOM解决浏览器性能问题,加入一次操作中有十次更新DOM的动作虚拟DOM不会立即操作DOM,而是将这十次更新的内容保存到本地js对象中,通过js对象渲染到DOM树,避免大量无谓的计算。

4.单页面路由意思就是只在一个页面写内容,一个页面写路由入口。

5.数据视图分离就是MVVM模式,Vue的数据响应式就是MVVM的更新模式 它有三个层级,分别是数据层model 视图层 view 视图模型层ViewModel。 ViewModel通过Observer监听model的数据变化,自动同步更新到view视图层上。 ViewModel负责监听Model中数据的改变并且控制视图的更新,处理用户交互操作;

优点:分离view和model层,降低代码耦合,提高视图逻辑复用性,自动更新DOM利用双向绑定原理,让数据更新后视图也自动更新。 缺点:出现问题很难调试,因为使用了双向数据绑定,页面出现问题很难判断是view层还是model层,数据长期持久不会释放内容,虽然保证了数据一致性,可能造成性能开销,消耗更多内存。

Vue和React的异同点

相同点:都是单向数据流,都是用了虚拟DOM技术,组件化开发 不同点:

1.前者template,后者JSX。

2.数据变化,前者响应式,后者手动setState,

3.React单向绑定,VUE双向绑定。

4.React状态管理工具,Redux,Moobx,Vue状态管理工具,Vuex

Vue和JQuery的区别?为什么不用JQuery而用VUE?

JQuery直接操作DOM,而Vue不直接操作DOM,而是只需操作数据

Vue的虚拟DOM技术,能适配多端

Vue集成了一些库,大大提高开发效率,例如Route、Vuex等等

为什么data是一个函数?为什么要返回一个对象?

如果data是一个函数就类似于每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据,如果单纯写成对象的形式会导致一个变了全都会变的结果,返回一个对象可以防止组件被多个页面使用时,造成的变量互相污染

使用过什么修饰符?

trim去前后空格 number 转换数字类型 stop阻止事件冒泡 captrue 事件之间捕获 self 点击事件绑定本身才触发 once 事件只触发一次 prevent 阻止事件默认行为 native绑定事件在自定义组件上 passive 给移动端滚动事件加.lazy camel 确保变量被识别成驼峰命名 sync 简化子修改父值得步骤

路由模式有几种

hash:哈希模式,根据hash值的更改进行组件切换,而不刷新页面

history:历史模式,依赖于HTML5的pushState和replaceState

abstract:适用于Node

路由的钩子函数

beforeEach 前置守卫 afterEach后置守卫

回调函数:to要进入的路由对象,from要离开的路由对象,next 执行跳转的方法

router.push,router.replace,router-go的区别

router.push:跳转,并向history栈中加一个记录,可以后退到上一个页面

router.replace:跳转,不会向history栈中加一个记录,不可以后退到上一个页面

router.go:传正数向前跳转,传负数向后跳转

路由独享钩子怎么写?

routes: [
  {
    path'/xxx',
    component: xxx,
    //在路由中写
    beforeEnter(to, from, next) => {
      
    }
  }
]

Vue的内部指令有哪些?

  • v-text:元素的textContent
  • v-html:元素的innerHTML
  • v-show:通过样式display改变显隐
  • v-if:通过操作DOM改变显隐
  • v-else:配合v-if
  • v-else-id:配合v-else
  • v-for:循环渲染
  • v-on:绑定事件,缩写@
  • v-bind:绑定变量,缩写:
  • v-model:双向绑定
  • v-slot:插槽
  • v-once:只渲染一次
  • v-pre:跳过元素编译
  • v-cloak:隐藏双括号,有值再显示

组件之间传值得方式有哪些?

  • 父传子,子组件通过props接收
  • 子传父,子组件使用$emit对父组件进行传值
  • 父子之间通过$parent$chidren获取实例进而通信
  • 通过vuex进行状态管理
  • 通过eventBus进行跨组件值传递
  • provideinject,官方不建议使用
  • $ref获取实例,进而传值
  • 路由传值
  • localStorage、sessionStorage

如何设置动态class对象,动态style数据?

  • 动态class对象:<div :class="{ 'is-active': true, 'red': isRed }"></div>
  • 动态class数组:<div :class="['is-active', isRed ? 'red' : '' ]"></div>
  • 动态style对象:<div :style="{ color: textColor, fontSize: '18px' }"></div>

v-if和v-show的区别

v-if 通过操作DOM来控制显隐,适用于按钮鉴权 v-show 通过改变样式display属性控制显隐,适用于频繁显隐的情况

computed和watch有何区别?

  • computed:依赖多个变量计算出一个变量,且具有缓存机制,依赖值不变的情况下,会复用计算值。computed中不能进行异步操作
  • watch:通常监听一个变量的变化,而去做一些事,可异步操作

Vue的生命周期

初始化阶段: new Vue实例化,初始化事件和生命周期函数,钩子函数执行beforeCreate, 钩子函数执行完成实例创建created

挂载阶段: 编辑模板-是否有el选项: 如果有继续检查template选项,返回return函数。生命周期函数执行beforeMount, 真实Dom挂载完毕执行mounted。 如果没有,编译el选项对应的标签作为template,把虚拟>Dom和渲染的数据一并挂到 真实Dom上,真实Dom挂载完毕执行mounted。

更新阶段: data数据改变 更新Dom之前,生命周期钩子函数执行beforeUpdate,虚拟Dom重新渲染, 打补丁到真实Dom,生命周期函数执行updated。此时如果数据继续改变重复执行这个循环

销毁阶段: 当$destory被调用,比如组件Dom被移除v-if,生命周期钩子函数执行beforeDestory, 卸载事件监听器,手动销毁定时器,生命周期钩子函数执行Destoryed。

为什么V-if和V-for不建议在一起使用?

v-for优先级高于v-if,每项都通过v-for渲染出来后再去通过v-if判断显隐,做了很多无用操作,有点多余

vuex的属性有哪些?用处是什么?

  • state:定义初始状态
  • getter:从store从取数据
  • mutation:更改store中状态,只能同步操作
  • action:用于提交mutation,而不直接更改状态,可异步操作
  • module:store的模块拆分

不需要响应式的数据应该怎么处理?

  • 定义在data的return之外

  • 使用Object.freeze进行数据冻结

watch监听怎么使用有哪些属性

immediate:初次加载时立即执行

deep:是否进行深度监听

handler:监听的回调函数

wathc监听器中immediate属性有什么作用?

Vue实例初始化的时候立即调用watch监听回调函数

组件生命周期的执行顺序

父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted

对象属性无法更新视图,属性改变或删除不更新视图,原因及方案?

原因:Object.defineProperty没有对对象的新属性进行劫持 解决方法:

新增属性:Vue.set(target, key, value)

删除属性:Vue.delete(target, key)

直接arr[1] = xxx 无法更新视图怎么办?

这个原因是因为Vue对于性能考虑没有对数组下标进行劫持,而是通过改写成数组原型方法。

splice:arr.splice(index, 1, value)

Vue.set(target, index, value)

他一共有三个参数,分别是目前属性,新增属性,新增的值。

为什么不建议使用index/随机数作为key?

因为index和随机数每次更新他都在改变,会导致每个dom元素不是唯一的,做不到专一性,也很消耗性能, 所以我们选择id 唯一的。

自定义指令的钩子函数

bind指令绑定到指定元素时调用,只调用一次 inserted 指定元素插入父节点 update 所在组件的VNode更新时调用 componnetUpdated 所在组件及子组件VNode 全部更新后调用 unbind 只调用一次,指令与元素解绑时调用

说说nextTick的用处

修改数据不能马上得到最新的DOM信息,所以需要使用nextTick,在nextTick回调中可以获取最新DOM信息, 获取更新最新DOM后的元素。

宏任务和微任务

宏任务:异步AJAX请求,script中的js文件外层同步代码,文件操作,定时器,所有的事件处理,数据请求

微任务:Promise.then.catch,Proxy,async/await

JavaScript事件循环执行机制

Js的事件循环执就是Event-loop,是javascript为解决异步编程的一种机制。

1.进入到script标签,就进入了第一次事件循环

2.遇到同步代码立即执行

3.遇到宏任务,放到宏任务队列中

4.遇到微任务,放到微任务队列中

5.执行完所有同步代码,执行微任务代码

6.微任务代码执行完毕,本次队列清空

7.寻找下一个宏任务,重复步骤一,以此反复直到清空所有宏任务,这种不断重复的执行机制就叫事件循环。

Vue双向数据绑定怎么实现的?

vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的 Vue2是采用Object.defineProperty劫持setter和getter数据变化发布消息给订阅者触发相应的回调来渲染视图。(也就是说数据和视图同步,数据变化视图变化,视图变化数据也随之变化。)

Vue3是采用Proxy劫持整个对象,而不是对象中的某个属性,Proxy的功能更强大,可以直接监听数组变化,还可以阻止对象上的默认行为。

为什么只对对象劫持,而要对数组进行方法重写?

数组的元素大概率是成百上千的,所以对数组下标进行劫持的话会非常消耗性能。Vue通过对数组原型上方法的重写,实现数组的响应式

Vue.set方法的原理?

Vue.set(target, key, value)

第一步:判断target是数组的话,则调用target.splice(key, 1, value)

第二步:判断target是对象的话,再判断传入的key是否已存在target中

是:直接target[key] = value

否:调用defineReactive(target, key, val)进行响应式处理

Vue.delete方法的原理?

Vue.delete(target, key) 第一步:判断target是否为数组,是的话调用target.splice(key, 1)

第二步:判断target是对象的话,调用delete关键字删除属性,并调用__ob__.dep.notify进行更新通知

nextTick的原理?

维护一个数组,每次调用时讲回调函数压入这个数组,然后优先选择微任务,在微任务回调中去执行数组中的所有回调,同时维护一个布尔值,确保每一次队列进行一次执行数组所有回调

计算属性中methods和computed哪个好?

computed比较好,computed有缓存机制,可以节省性能。而method则每次更新都会重新计算,不考虑缓存

自定义v-model

export default: {  
  model: {  
    event: 'change',  
    prop: 'checked'    
  }  
}

动态指令和参数如何使用

<aButton @[someEvent]="handleSomeEvent()" :[someProps]="1000" />

Vue的el属性和$mount优先级

如果同时存在的话 el>$mount

props怎么自定义验证

props: {  
    num: {  
      default1,  
      validator: function (value{  
         // 返回值为false则验证不通过,报错  
         return [12345 ].indexOf(value) !== -1  
      }  
    }  
  }  
}

如果子组件改变props里面的数据会发生什么?

基础类型:如果父传给子的是基础类型,修改则会报错 引用类型:如果父传给子的是引用类型,修改属性则会同时修改父组件的数据

插槽slot的理解

插槽就是一个占位符,将定义的内容展示出来,自定义的组件如果写内容是不会显示出来的,所以要用slot插槽来解决这个问题 分为三种,匿名插槽,具名插槽,作用域插槽

1.匿名插槽也是默认的,一个组件只有一个,没有指定name时默认展示这个插槽

2.具名插槽带有具体名字的在slot中定义name一个组件可以出现多个

3.作用域插槽和匿名,具名插槽类似只是可以传递数据给父组件,让父组件收到数据决定如何渲染该插槽。