【温故知新】Vue

Vue

vue 渲染流程

  • new Vue():初始化
  • => $mount :调用mount 挂载组件
  • => compile():
    • parse:解析,把模板解析为 ast 的抽象语法树,ast 类似 js 对象,它可以描述所有节点(特别像 vdom )
    • optimize:优化,对 ast 做静态节点标记,跳过指令等
    • generate:代码生成,把 ast 生成代码字符串
  • => render function:渲染函数
    • getter:在创建组件的时候对 data 进行遍历,创建 watcher 添加到对应的 dep 依赖收集中
    • set 的时候执行 notify 通知 dep 对应的 update 方法
    • 然后重新打补丁 patch 生成新的 vdom ,diff 比对映射到界面中
  • => render:渲染函数通过 render 执行生成 vdom 虚拟 dom
  • => patch():把 vdom 打补丁生成真实 dom
    • patchVnode
    • updateChildren
  • => DOM

vue 的双向绑定

  • Data 通过 observer 转换成了 getter/setter 的形式来追踪变化。
    当外界通过 Watcher 读取数据时,会触发 getter 从而将 Watch 添加到依赖中。
    当数据发生了变化时,会触发 setter,从而向 Dep 中的依赖(即 Watcher)发送通知
    Watcher 接收到通知后,会向外界发送通知,变化通知到外界后可能会触发视图更新,
    也有可能触发用户的某个回调函数等。

为什么重写数组方法

  • 在 Vue 现有阶段中,对响应式处理利用的是 Object.defineProperty 对数据进行拦截,
    而这个方法并不能监听到数组内部变化,数组长度变化,数组的截取变化等,
    所以我们需要对这些操作进行 hack,让 vue 能监听到其中的变化。
  • 为什么在 Vue3.0 采用了 Proxy,抛弃了 Object.defineProperty?
    原因如下:
    Object.defineProperty 无法低耗费的监听到数组下标的变化,导致通过数组下标添加元素,不能实时响应;
    Object.defineProperty 只能劫持对象的属性,从而需要对每个对象,每个属性进行遍历。如果属性值是对象,还需要深度遍历。 Proxy 可以劫持整个对象, 并返回一个新的对象。
    Proxy 不仅可以代理对象,还可以代理数组。还可以代理动态增加的属性。

vue2 响应原理的弊端

  • 响应化过程需要递归遍历,消耗较大;
  • 属性的添加和删除无法监听;
  • 数组响应化需要额外实现;
  • map、set、class 等无响应式;
  • 修改语法有限制;

vue3 composition api 和 react 中 hooks 区别

  • React 数据更改的时候,会导致重新 render,重新 render 又会重新把 Hooks 重新注册一次,所以 React 的上手难度更高一些
  • Vue Hook 只会被注册调用一次,Vue 能避开这些麻烦的问题,原因在于它对数据的响应是基于 proxy 的,
    对数据直接代理观察。这种场景下,只要任何一个更改 data 的地方,
    相关的 function 或者 template 都会被重新计算,因此避开了 React 可能遇到的性能上的问题
  • Vue Composition API 的 setup() 晚于 beforeCreate 钩子,早于 created 钩子被调用
  • React Hooks 会在组件每次渲染时候运行,而 Vue setup() 只在组件创建时运行一次

MVVM和MVC的区别

  • MVC:Model、View 和 Controller
  • MVVM:Model、View 和 ViewModel

常见的事件修饰符

  • click.stop - 调用 event.stopPropagation() 阻止冒泡
  • click.prevent - 调用 event.preventDefault() 阻止默认行为
  • click.self - 只触发自身,不包含子元素。
  • click.once - 只触发一次回调。
  • click.native – 监听原生事件

项目部署子路径配置

  • 修改静态文件的路径:assetsPublicPath

V-model 实现

  • 子组件通过 v-bind:value 加上 v-on:input 实现

V-bind 绑定动态参数

  • 中括号

Computed 计算属性

  1. 赋值:Setter 方法
  2. 特点:
  • 它支持缓存,只有依赖的数据发生了变化,才会重新计算
  • 不支持异步,当Computed中有异步操作时,无法监听数据的变化
  • computed的值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,
    也就是基于data声明过,或者父组件传递过来的props中的数据进行计算的。
  • 如果一个属性是由其他属性计算而来的,这个属性依赖其他的属性,一般会使用computed
  • 如果computed属性的属性值是函数,那么默认使用get方法,函数的返回值就是属性的属性值;
    在computed中,属性有一个get方法和一个set方法,当数据发生变化时,会调用set方法。

Watch

  • 它不支持缓存,数据变化时,它就会触发相应的操作
  • 支持异步监听
  • 监听的函数接收两个参数,第一个参数是最新的值,第二个是变化之前的值
  • 当一个属性发生变化时,就需要执行相应的操作
  • 监听数据必须是data中声明的或者父组件传递过来的props中的数据,当发生变化时,会出大其他操作,函数有两个的参数:
    • immediate:组件加载立即触发回调函数
    • deep:深度监听,发现数据内部的变化,在复杂数据类型中使用,例如数组中的对象发生变化。
      需要注意的是,deep无法监听到数组和对象内部的变化。
    • watch 可以监听对象的单个属性

Computed 计算属性和 Methods 方法的区别

  • 同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的
  • 计算属性是基于它们的响应式依赖进行缓存的,方法访问多少次就执行多少次

Watch 和 Computed 的区别

  • computed 只有当依赖的数据变化时才会计算, 当数据没有变化时, 它会读取缓存数据。
  • watch 每次都需要执行函数。 watch 更适用于数据变化时的异步操作。

keep-alive

  • 用法:如果需要在组件切换的时候,保存一些组件的状态防止多次渲染,就可以使用 keep-alive 组件包裹需要保存的组件。
  • keep-alive 属性:include 字符串或正则表达式,只有名称匹配的组件会被匹配;exclude 字符串或正则表达式。任何名称匹配的组件都不会被缓存;max 数字。最多可以缓存多少组件实例;
  • keep-alive 生命周期:activated、deactivated
  • 步骤
    • 获取 keep-alive 下第一个子组件的实例对象,通过他去获取这个组件的组件名
    • 通过当前组件名去匹配原来 include 和 exclude,判断当前组件是否需要缓存,不需要缓存,直接返回当前组件的实例vNode
    • 需要缓存, 判断他当前是否在缓存数组里面: 存在,则将他原来位置上的 key 给移除,同时将这个组件的 key 放到数组最后面(LRU)
    • 不存在,将组件 key 放入数组,然后判断当前 key数组是否超过 max 所设置的范围,超过,那么削减未使用时间最长的一个组件的 key 最后将这个组件的 keepAlive 设置为 true

$nextTick 原理及作用

  • nextTick 的核心是利用了如 Promise 、MutationObserver、setImmediate、setTimeout的原生 JavaScript 方法来模拟对应的微/宏任务的实现,
    本质是为了利用 JavaScript 的这些异步回调任务队列来实现 Vue 框架中自己的异步回调队列。

Vue 中给 data 中的对象属性添加一个新的属性时会发生什么

  • 给 obj 添加 b 属性 ,obj.b 可以成功添加,但是视图并未刷新。
    这是因为在Vue实例创建时,obj.b并未声明,因此就没有被Vue转换为响应式的属性,自然就不会触发视图的更新,
    这时就需要使用Vue的全局 api $set()

Vue template 到 render 的过程

  • vue的模版编译过程主要如下:template -> ast -> render函数

Vue自定义指令

  • 全局定义:Vue.directive(“focus”,{})
  • 局部定义:directives:{focus:{}}
  • 钩子函数
    • bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
    • inSerted:被绑定元素插入父节点时调用(仅保证父节点存在,但不一定已被插入文档中)。
    • update:所在组件的VNode更新时调用,但是可能发生在其子VNode更新之前调用。指令的值可能发生了改变,也可能没有。但是可以通过比较更新前后的值来忽略不必要的模板更新。
    • ComponentUpdate:指令所在组件的 VNode及其子VNode全部更新后调用。
    • unbind:只调用一次,指令与元素解绑时调用。

assets 和 static 的区别

  • 相同点: assets 和 static 两个都是存放静态资源文件。项目中所需要的资源文件图片,字体图标,样式文件等都可以放在这两个文件下,这是相同点
  • 不相同点:assets 中存放的静态资源文件在项目打包时,
    也就是运行 npm run build 时会将 assets 中放置的静态资源文件进行打包上传,所谓打包简单点可以理解为压缩体积,代码格式化。
    而压缩后的静态资源文件最终也都会放置在 static 文件中跟着 index.html 一同上传至服务器。
    static 中放置的静态资源文件就不会要走打包压缩格式化等流程,而是直接进入打包好的目录,直接上传至服务器。
    因为避免了压缩直接进行上传,在打包时会提高一定的效率,
    但是 static 中的资源文件由于没有进行压缩等操作,所以文件的体积也就相对于 assets 中打包后的文件提交较大点。
    在服务器中就会占据更大的空间。

V-for 和 v-if 优先级

  • v-for 优先级更高

v-if、v-show、v-html 的原理

  • v-if会调用addIfCondition方法,生成vnode的时候会忽略对应节点,render的时候就不会渲染;
  • v-show会生成vnode,render的时候也会渲染成真实节点,只是在render过程中会在节点的属性中修改show属性值,也就是常说的display;
  • v-html会先移除节点下的所有节点,调用html方法,通过addProp添加innerHTML属性,归根结底还是设置innerHTML为v-html的值。

v-if和v-show的区别

  • 手段:v-if是动态的向DOM树内添加或者删除DOM元素;v-show是通过设置DOM元素的display样式属性控制显隐;
  • 编译过程:v-if切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件;v-show只是简单的基于css切换;
  • 编译条件:v-if是惰性的,如果初始条件为假,则什么也不做;只有在条件第一次变为真时才开始局部编译; v-show是在任何条件下,无论首次条件是否为真,都被编译,然后被缓存,而且DOM元素保留;
  • 性能消耗:v-if有更高的切换消耗;v-show有更高的初始渲染消耗;
  • 使用场景:v-if适合运营条件不大可能改变;v-show适合频繁切换。

vue 性能优化

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

template和jsx的有什么分别

  • template和jsx的都是render的一种表现形式
  • 不同的是:JSX相对于template而言,具有更高的灵活性,在复杂的组件中,更具有优势,而 template 虽然显得有些呆滞。
    但是 template 在代码结构上更符合视图与逻辑分离的习惯,更简单、更直观、更好维

vue初始化页面闪动问题

  • v-cloak

eventBus事件总线

  • new Vue() 创建事件中心,$emit / $on

project / inject

  • project 钩子用来发送数据或方法
  • inject钩子用来接收数据或方法
// 父
{
  provide:() => {
   return {
      num: this.num
   };
  }
}
// 子
{inject: ['num']}

$attrs / $listeners

  • $attrs:继承所有的父组件属性(除了prop传递的属性、class 和 style ),一般用在子组件的子元素上
  • l i s t e n e r s : 该 属 性 是 一 个 对 象 , 里 面 包 含 了 作 用 在 这 个 组 件 上 的 所 有 监 听 器 , 可 以 配 合 v − o n = " listeners:该属性是一个对象,里面包含了作用在这个组件上的所有监听器,可以配合 v-on=" listenersvon="listeners" 将所有的事件监听器指向这个组件的某个特定的子元素。(相当于子组件继承父组件的事件)

Vue-route

hash 和 history 原理及区别

  • 同 react

Vue-router跳转和location.href有什么区别

  • 静态跳转,刷新跳转

params和query的区别

  • 用法:query要用path来引入,params要用name来引入,接收参数都是类似的,分别是 this. r o u t e . q u e r y . n a m e 和 t h i s . route.query.name 和 this. route.query.namethis.route.params.name 。
  • url地址显示:query更加类似于我们ajax中get传参,params则类似于post,说的再简单一点,前者在浏览器地址栏中显示参数,后者则不显示

Vue-router 导航守卫有哪些

  • 全局前置/钩子:beforeEach、beforeResolve、afterEach
  • 路由独享的守卫:beforeEnter
  • 组件内的守卫:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave

VueX

vuex

  • Vue Components∶ Vue组件。HTML页面上,负责接收用户操作等交互行为,执行dispatch方法触发对应action进行回应。
  • dispatch∶操作行为触发方法,是唯一能执行action的方法。
  • actions∶ 操作行为处理模块。负责处理Vue Components接收到的所有交互行为。
    包含同步/异步操作,支持多个同名方法,按照注册的顺序依次触发。向后台API请求的操作就在这个模块中进行,
    包括触发其他action以及提交mutation的操作。该模块提供了Promise的封装,以支持action的链式触发。
  • commit∶状态改变提交操作方法。对mutation进行提交,是唯一能执行mutation的方法。
  • mutations∶状态改变操作方法。是Vuex修改state的唯一推荐方法,其他修改方式在严格模式下将会报错。
    该方法只能进行同步操作,且方法名只能全局唯一。操作之中会有一些hook暴露出来,以进行state的监控等。
  • state∶ 页面状态管理容器对象。集中存储Vuecomponents中data对象的零散数据,
    全局唯一,以进行统一的状态管理。页面显示所需的数据从该对象中进行读取,
    利用Vue的细粒度数据响应机制来进行高效的状态更新。
  • getters∶ state对象读取方法。图中没有单独列出该模块,应该被包含在了render中,Vue Components通过该方法读取全局state对象。

双向绑定和 vuex 是否冲突

  • 当在严格模式中使用 Vuex 时,在属于 Vuexstate 上使用 v-model 会导致出错。
  • 解决方案:1. 给 <Input> 中绑定 value,然后侦听 input 或者 change 事件,在事件回调中调用一个方法;2. 使用带有 setter 的双向绑定计算属性;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值