vue知识点整理

 1、你了解diff算法吗?

简单总结:

patchVnode函数:

  • 如果oldVnode有子节点而VNode没有,则删除el子节点

  • 如果oldVnode没有子节点而VNode有,则将VNode的子节点真实化后添加到el

  • 如果两者都有子节点,则执行updateChildren函数比较子节点 (核心diff算法

updateChildren函数具体逻辑执行顺序:

updateChildren温馨提示:算法顺序:

  1. 头头比较
  2. 尾尾比较
  3. old头new尾
  4. old尾new头
  5. 如果上述都不匹配:尝试在oldChildren中寻找和newStartVnode的具有相同key的Vnode

详见:https://liulibin.blog.youkuaiyun.com/article/details/114916799

2、vue常用的修饰符有哪些?应用场景

表单修饰符:

  1. lazy:在我们填完信息,光标离开标签的时候,才会将值赋予给value,也就是在change事件之后再进行信息同步
  2. trim:自动过滤用户输入的首空格字符,而中间的空格不会过滤
  3. number:自动将用户的输入值转为数值类型,但如果这个值无法被parseFloat解析,则会返回原来的值
<input type="text" v-model.lazy="value">
<input type="text" v-model.trim="value">
<input v-model.number="age" type="number">

事件修饰符:

  • stop 阻止了事件冒泡,相当于调用了event.stopPropagation方法

  • prevent 阻止了事件的默认行为,相当于调用了event.preventDefault方法

  • self 只当在 event.target 是当前元素自身时触发处理函数

  • once 绑定了事件以后只能触发一次,第二次就不会触发

  • capture 使事件触发从包含这个元素的顶层开始往下触发

  • passive 在移动端,当我们在监听元素滚动事件的时候,会一直触发onscroll事件会让我们的网页变卡,因此我们使用这个修饰符的时候,相当于给onscroll事件整了一个.lazy修饰符

  • native 让组件变成像html内置标签那样监听根元素的原生事件,否则组件上使用 v-on 只会监听自定义事件

鼠标按钮修饰符:

  • left 左键点击

  • right 右键点击

  • middle 中键点击

键盘修饰符:

  • 普通键(enter、tab、delete、space、esc、up...)

  • 系统修饰键(ctrl、alt、meta、shift...)

详见:https://liulibin.blog.youkuaiyun.com/article/details/114964657

3、循环绑定key值有必要写吗?为什么

当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。key的作用主要是为了高效的更新虚拟DOM

详见:https://liulibin.blog.youkuaiyun.com/article/details/114966729

4、说说你对keep-alive的理解是什么?怎么缓存当前的组件?缓存后怎么更新?

keep-alive可以设置以下props属性:

  • include - 字符串或正则表达式。只有名称匹配的组件会被缓存

  • exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存

  • max - 数字。最多可以缓存多少组件实例

设置了 keep-alive 缓存的组件,会多出两个生命周期钩子(activateddeactivated):

  • 首次进入组件时:beforeRouteEnter > beforeCreate > createdmounted > activated > ... ... > beforeRouteLeave > deactivated

  • 再次进入组件时:beforeRouteEnter >activated > ... ... > beforeRouteLeave > deactivated

举个栗子:

当我们从首页–>列表页–>商详页–>再返回,这时候列表页应该是需要keep-alive

首页–>列表页–>商详页–>返回到列表页(需要缓存)–>返回到首页(需要缓存)–>再次进入列表页(不需要缓存),这时候可以按需来控制页面的keep-alive

注意:服务器端渲染期间avtived不被调用

详见:https://liulibin.blog.youkuaiyun.com/article/details/105050112

5、你有写过自定义指令吗?自定义指令的应用场景有哪些?

详见:https://liulibin.blog.youkuaiyun.com/article/details/114966397

6、什么是虚拟DOM?如何实现一个虚拟DOM?

7、vue组件中data为什么必须是一个函数?

因为JavaScript的特性所导致,在component中,data必须以函数的形式存在,不可以是对象。

组建中的data写成一个函数,数据以函数返回值的形式定义,这样每次复用组件的时候,都会返回一份新的data,相当于每个组件实例都有自己私有的数据空间,它们只负责各自维护的数据,不会造成混乱。而单纯的写成对象形式,就是所有的组件实例共用了一个data,这样改一个全都改了。

8、vue生命周期的理解、执行顺序

vue3生命周期

  • beforecatecreated(它们被setup方法本身所取代)
  • onBeforeMount – 在挂载开始之前被调用:相关的 render 函数首次被调用。
  • onMounted – 组件挂载时调用
  • onBeforeUpdate – 数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。
  • onUpdated – 由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
  • onBeforeUnmount – 在卸载组件实例之前调用。在这个阶段,实例仍然是完全正常的。
  • onUnmounted – 卸载组件实例后调用。调用此钩子时,组件实例的所有指令都被解除绑定,所有事件侦听器都被移除,所有子组件实例被卸载。
  • onActivated – 被 keep-alive 缓存的组件激活时调用。
  • onDeactivated – 被 keep-alive 缓存的组件停用时调用。
  • onErrorCaptured – 当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播

对比:

  • beforeCreate -> 使用 setup()
  • created -> 使用 setup()
  • beforeMount -> onBeforeMount
  • mounted -> onMounted
  • beforeUpdate -> onBeforeUpdate
  • updated -> onUpdated
  • beforeDestroy -> onBeforeUnmount
  • destroyed -> onUnmounted
  • errorCaptured -> onErrorCaptured
     

9、父子组件传值?你知道的传值有哪些

  • 父子关系的组件数据传递选择 props  与 $emit进行传递,也可选择ref

  • 兄弟关系的组件数据传递可选择$bus,其次可以选择$parent进行传递

  • 祖先与后代组件数据传递可选择attrslisteners或者 Provide与 Inject

  • 复杂关系的组件数据传递可以通过vuex存放共享的变量

详见:https://liulibin.blog.youkuaiyun.com/article/details/115064992

10、router和route的区别

$route是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name等路由信息参数。而$router是“路由实例”对象包括了路由的跳转方法,钩子函数等

11、vue-router导航钩子

全局导航钩子:beforeEach(to, from, next)、beforeResolve(to, from, next)、afterEach(to, from ,next)

组件内钩子:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave

单独路由独享组件:beforeEnter

12、vue2的双向数据绑定原理

13、vue3的双向数据绑定原理

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

编码阶段

  • 尽量减少data中的数据,data中的数据都会增加getter和setter,会收集对应的watcher
  • v-if和v-for不能连用
  • 如果需要使用v-for给每项元素绑定事件时使用事件代理
  • SPA 页面采用keep-alive缓存组件
  • 在更多的情况下,使用v-if替代v-show
  • key保证唯一
  • 使用路由懒加载、异步组件
  • 防抖、节流
  • 第三方模块按需导入
  • 长列表滚动到可视区域动态加载
  • 图片懒加载

SEO优化

  • 预渲染
  • 服务端渲染SSR

打包优化

  • 压缩代码
  • Tree Shaking/Scope Hoisting
  • 使用cdn加载第三方模块
  • 多线程打包happypack
  • splitChunks抽离公共文件
  • sourceMap优化

用户体验

  • 骨架屏
  • PWA

还可以使用缓存(客户端缓存、服务端缓存)优化、服务端开启gzip压缩等。

15、hash路由和history路由实现原理说一下

hash : window.onhashchange

history : history.pushState 和 window.onpopstate

16、你的接口请求一般放在哪个生命周期中?

接口请求一般放在mounted中,但需要注意的是服务端渲染时不支持mounted,需要放到created中。

17、虚拟Dom以及key属性的作用

由于在浏览器中操作DOM是很昂贵的。频繁的操作DOM,会产生一定的性能问题。这就是虚拟Dom的产生原因。

Vue2的Virtual DOM借鉴了开源库snabbdom的实现。

Virtual DOM本质就是用一个原生的JS对象去描述一个DOM节点。是对真实DOM的一层抽象。(也就是源码中的VNode类,它定义在src/core/vdom/vnode.js中。)

VirtualDOM映射到真实DOM要经历VNode的create、diff、patch等阶段。

「key的作用是尽可能的复用 DOM 元素。」

新旧 children 中的节点只有顺序是不同的时候,最佳的操作应该是通过移动元素的位置来达到更新的目的。

需要在新旧 children 的节点中保存映射关系,以便能够在旧 children 的节点中找到可复用的节点。key也就是children中节点的唯一标识。

16、Computed/Watch/methods

computed: 

  • 如果绑定的是v-model,则set/get方法都要有,默认是get
  • 计算属性是基于它们的依赖进行缓存的,只在相关依赖发生改变时它们才会重新求值

watch:主要用于监控vue实例的变化,它监控的变量当然必须在data里面声明才可以,它可以监控一个变量,也可以是一个对象

  • deep:true 对应的是引用类型
  • 默认是false , 基本类型

methods:则必须要有一定的触发条件才能执行,如点击事件;

18、vue.nextTick()的理解及使用

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

详见:https://liulibin.blog.youkuaiyun.com/article/details/115000337

19、Vue.js中ajax请求代码应该写在组件的methods中还是vuex的actions中?

20、vuex有哪几种属性?

21、说说你对vue的mixin的理解,有哪些应用场景?

在日常的开发中,我们经常会遇到在不同的组件中经常会需要用到一些相同或者相似的代码,这些代码的功能相对独立

这时,可以通过Vuemixin功能将相同或者相似的代码提出来

详见:https://liulibin.blog.youkuaiyun.com/article/details/114999149

22、SPA(单页应用)首屏加载速度慢怎么解决?

加载慢的原因:

在页面渲染的过程,导致加载速度慢的因素可能如下:

  • 网络延时问题

  • 资源文件体积是否过大

  • 资源是否重复发送请求去加载了

  • 加载脚本的时候,渲染内容堵塞了

解决方案:

常见的几种SPA首屏优化方式

  • 减小入口文件积

  • 静态资源本地缓存

  • UI框架按需加载

  • 图片资源的压缩

  • 组件重复打包

  • 开启GZip压缩

  • 使用SSR

详见:https://liulibin.blog.youkuaiyun.com/article/details/115064769

23、如何给SPA做SEO

下面给出基于VueSPA如何实现SEO的三种方式

  1. SSR服务端渲染

将组件或页面通过服务器生成html,再返回给浏览器,如nuxt.js

  1. 静态化

目前主流的静态化主要有两种:

(1)一种是通过程序将动态页面抓取并保存为静态页面,这样的页面的实际存在于服务器的硬盘中

(2)另外一种是通过WEB服务器的 URL Rewrite的方式,它的原理是通过web服务器内部模块按一定规则将外部的URL请求转化为内部的文件地址,一句话来说就是把外部请求的静态地址转化为实际的动态页面地址,而静态页面实际是不存在的。这两种方法都达到了实现URL静态化的效果

  1. 使用Phantomjs针对爬虫处理

原理是通过Nginx配置,判断访问来源是否为爬虫,如果是则搜索引擎的爬虫请求会转发到一个node server,再通过PhantomJS来解析完整的HTML,返回给爬虫。

24、Vue3.0里为什么要用 Proxy API 替代 defineProperty API ?

Object.defineProperty只能遍历对象属性进行劫持

Proxy直接可以劫持整个对象,并返回一个新对象,我们可以只操作新的对象达到响应式目的

Proxy有多达13种拦截方法,不限于applyownKeysdeletePropertyhas等等,这是Object.defineProperty不具备的

正因为defineProperty自身的缺陷,导致Vue2在实现响应式过程需要实现其他的方法辅助(如重写数组方法、增加额外setdelete方法)

Proxy不兼容IE,也没有 polyfill, defineProperty能支持到IE9

详见:https://liulibin.blog.youkuaiyun.com/article/details/115078363

25、Vue3.0的设计目标是什么?做了哪些优化?

详见:https://liulibin.blog.youkuaiyun.com/article/details/115078834

26、Vue3.0 性能提升主要是通过哪几方面体现的?

详见:https://liulibin.blog.youkuaiyun.com/article/details/115079218

27、Vue3.0 所采用的 Composition Api 与 Vue2.x 使用的 Options Api 有什么不同?

  • 在逻辑组织和逻辑复用方面,Composition API是优于Options API

  • 因为Composition API几乎是函数,会有更好的类型推断。

  • Composition API对 tree-shaking 友好,代码也更容易压缩

  • Composition API中见不到this的使用,减少了this指向不明的情况

  • 如果是小型组件,可以继续使用Options API,也是十分友好的

详见:https://liulibin.blog.youkuaiyun.com/article/details/115079453

28、说说Vue 3.0中Treeshaking特性?举例说明一下?

通过Tree shakingVue3给我们带来的好处是:

  • 减少程序体积(更小)

  • 减少程序执行时间(更快)

  • 便于将来对程序架构进行优化(更友好)

详见:https://liulibin.blog.youkuaiyun.com/article/details/115080332

29、兄弟组件之间传递 或者 层级比较深 自定义事件传递

$on $emit $off(关闭 beforeDestroy)

event.js 
```
import vue from "vue"
export default new vue()
```

30、slot插槽

具名插槽、作用域插槽

vue之slot属性_景尘的博客-优快云博客_slot属性

31、动态组件

场景:例如:详情页里面的模块顺序不唯一,动态组件循环去渲染对应顺序组件

```

<component :is="comName"/>

```

32、异步组件

场景:页面加载性能优化,初始化时不加载,配合v-if

<script>
import name from "../ddd/name.vue"  //同步加载

export default {
    components:{
        name,
        name:()=>import("../ddd/name.vue) //异步加载
    }
}

</script>

33、组件抽离公共逻辑 mixin

多个组件有相同的逻辑,抽离出来(例如,自己封装了一个组件,有多个子传父的方法,可以使用,或者多个组件相同业务逻辑也可使用)

```
<script>
import mymixin from "mymixin.js"
export default {
    mixins:[mymixin],
    mounted(){
        this.showName()// 获取 mymixin 方法等
    }
}

</script>
```
mixin.js
```
export default {
    data(){
        return {

        }
    },
    methods:{
        showName(){
            console.log()
        }
    },
    mounted(){

    }
}
```

34、何时需要使用beforeDestroy

1、解除自定义事件event.$off

2、清楚计时器

3、解绑自定义的DOM事件,如window scroll等

35、监听data变化的核心api是什么

object.defineProperty()

36、vue如何监听数组变化

object.defineProperty不能监听数组变化

重新定义原型,重写push/pop等方法,实现监听

见 core/observer/array.js

const arrayProto = Array.prototype

const arrayMethods = Object.create(arrayProto)

37、类似于 window.alert() 提示组件,怎么实现

Vue.extend + vm.$mount 组合

 38、vue初始化页面闪动问题

34、$set

// 使用
Vue $sett(object, key, value) 
function set (target: Array<any> | Object, key: any, val: any): any {
  if (process.env.NODE_ENV !== 'production' &&
    (isUndef(target) || isPrimitive(target))
  ) {
    warn(`Cannot set reactive property on undefined, null, or primitive value: ${(target: any)}`)
  }
  // 数组
  if (Array.isArray(target) && isValidArrayIndex(key)) {
    target.length = Math.max(target.length, key)
    target.splice(key, 1, val)
    return val
  }
  // 对象
  if (key in target && !(key in Object.prototype)) {
    target[key] = val
    return val
  }
  const ob = (target: any).__ob__
  if (target._isVue || (ob && ob.vmCount)) {
    process.env.NODE_ENV !== 'production' && warn(
      'Avoid adding reactive properties to a Vue instance or its root $data ' +
      'at runtime - declare it upfront in the data option.'
    )
    return val
  }
  if (!ob) {
    target[key] = val
    return val
  }
  defineReactive(ob.value, key, val)
  ob.dep.notify()
  return val
}

操作数组的更新方法:使用splice替换将数组的旧值替换成了新值

操作对象的方法,比数组稍微麻烦一些:

  • 首先if (key in target && !(key in Object.prototype))判断这个key是不是当前对象的key 和 这个key 不是object原型的key。说明这个key本来就在对象上面已经定义过了的,直接修改值就可以了,可以自动触发响应。
  • 这时候给对象添加了__obj__属性,然后又做了判断if (target._isVue || (ob && ob.vmCount))的意思是:当前的target对象是vue实例对象或者是根数据对象,那么就会抛出错误警告
  • 这一步才是最核心的地方defineReactive(ob.value, key, val)这个方法的意思是给新加的属性添加依赖,以后再直接修改这个新的属性的时候就会触发页面渲染。ob.dep.notify()这个方法可以理解成渲染函数,所以页面就会进行重新渲染

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

景尘

你的励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值