乐趣区

关于前端:前端常见vue面试题被问到不会就糟了

v-if 和 v -for 哪个优先级更高

实际中不应该把 v -for 和 v -if 放一起

在 vue2 中,v-for 的优先级是高于 v -if,把它们放在一起,输入的渲染函数中能够看出会先执行循环再判断条件,哪怕咱们只渲染列表中一小部分元素,也得在每次重渲染的时候遍历整个列表,这会比拟节约;另外须要留神的是在 vue3 中则齐全相同,v-if 的优先级高于 v -for,所以 v -if 执行时,它调用的变量还不存在,就会导致异样

通常有两种状况下导致咱们这样做:

为了过滤列表中的我的项目 (比方 v -for=”user in users” v-if=”user.isActive”)。此时定义一个计算属性 (比方 activeUsers),让其返回过滤后的列表即可(比方 users.filter(u=>u.isActive))

为了防止渲染本应该被暗藏的列表 (比方 v -for=”user in users” v-if=”shouldShowUsers”)。此时把 v -if 挪动至容器元素上 (比方 ul、ol)或者外面包一层 template 即可

文档中明确指出永远不要把 v -if 和 v -for 同时用在同一个元素上,显然这是一个重要的注意事项

源码外面对于代码生成的局部,可能清晰的看到是先解决 v -if 还是 v -for,程序上 vue2 和 vue3 正好相同,因而产生了一些症状的不同,然而不管怎样都是不能把它们写在一起的

vue2.x 源码剖析

在 vue 模板编译的时候,会将指令系统转化成可执行的 render 函数

编写一个 p 标签,同时应用 v -if 与 v-for

<div id="app">
  <p v-if="isShow" v-for="item in items">
    {{item.title}}  </p></div>

创立 vue 实例,寄存 isShow 与 items 数据

const app = new Vue({  el: "#app",
  data() {    return {      items: [{ title: "foo"},
        {title: "baz"}]
    }
  },  computed: {isShow() {return this.items && this.items.length > 0}
  }
})

模板指令的代码都会生成在 render 函数中,通过 app.$options.render 就能失去渲染函数

ƒ anonymous() {  with (this) { return 
    _c('div', { attrs: { "id": "app"} }, 
    _l((items), function (item) 
    {return (isShow) ? _c('p', [_v("\n" + _s(item.title) + "\n")]) : _e()}), 0) }
}

_l 是 vue 的列表渲染函数,函数外部都会进行一次 if 判断

初步失去论断:v-for 优先级是比 v -if 高

再将 v -for 与 v -if 置于不同标签

<div id="app">
  <template v-if="isShow">
    <p v-for="item in items">{{item.title}}</p>
  </template></div>

再输入下 render 函数

ƒ anonymous() {  with(this){return 
    _c('div',{attrs:{"id":"app"}},
    [(isShow)?[_v("\n"),
    _l((items),function(item){return _c('p',[_v(_s(item.title))])})]:_e()],2)}
}

这时候咱们能够看到,v-for 与 v -if 作用在不同标签时候,是先进行判断,再进行列表的渲染

咱们再在查看下 vue 源码

源码地位:\vue-dev\src\compiler\codegen\index.js

export function genElement (el: ASTElement, state: CodegenState): string {if (el.parent) {el.pre = el.pre || el.parent.pre}  if (el.staticRoot && !el.staticProcessed) {return genStatic(el, state)
  } else if (el.once && !el.onceProcessed) {return genOnce(el, state)
  } else if (el.for && !el.forProcessed) {return genFor(el, state)
  } else if (el.if && !el.ifProcessed) {return genIf(el, state)
  } else if (el.tag === 'template' && !el.slotTarget && !state.pre) {return genChildren(el, state) || 'void 0'
  } else if (el.tag === 'slot') {return genSlot(el, state)
  } else {    // component or element
    ...
}

在进行 if 判断的时候,v-for 是比 v -if 先进行判断

最终论断:v-for 优先级比 v -if 高

vue3.0 个性你有什么理解的吗?
Vue 3.0 正走在公布的路上,Vue 3.0 的指标是让 Vue 外围变得更小、更快、更弱小,因而 Vue 3.0 减少以下这些新个性:

(1)监测机制的扭转

3.0 将带来基于代理 Proxy 的 observer 实现,提供全语言笼罩的反馈性跟踪。这打消了 Vue 2 当中基于 Object.defineProperty 的实现所存在的很多限度:

只能监测属性,不能监测对象

检测属性的增加和删除;

检测数组索引和长度的变更;

反对 Map、Set、WeakMap 和 WeakSet。

新的 observer 还提供了以下个性:

用于创立 observable 的公开 API。这为中小规模场景提供了简略轻量级的跨组件状态治理解决方案。

默认采纳惰性察看。在 2.x 中,不论反应式数据有多大,都会在启动时被察看到。如果你的数据集很大,这可能会在利用启动时带来显著的开销。在 3.x 中,只察看用于渲染应用程序最后可见局部的数据。

更准确的变更告诉。在 2.x 中,通过 Vue.set 强制增加新属性将导致依赖于该对象的 watcher 收到变更告诉。在 3.x 中,只有依赖于特定属性的 watcher 才会收到告诉。

不可变的 observable:咱们能够创立值的“不可变”版本(即便是嵌套属性),除非零碎在外部临时将其“解禁”。这个机制可用于解冻 prop 传递或 Vuex 状态树以外的变动。

更好的调试性能:咱们能够应用新的 renderTracked 和 renderTriggered 钩子准确地跟踪组件在什么时候以及为什么从新渲染。

(2)模板

模板方面没有大的变更,只改了作用域插槽,2.x 的机制导致作用域插槽变了,父组件会从新渲染,而 3.0 把作用域插槽改成了函数的形式,这样只会影响子组件的从新渲染,晋升了渲染的性能。

同时,对于 render 函数的方面,vue3.0 也会进行一系列更改来不便习惯间接应用 api 来生成 vdom。

(3)对象式的组件申明形式

vue2.x 中的组件是通过申明的形式传入一系列 option,和 TypeScript 的联合须要通过一些装璜器的形式来做,尽管能实现性能,然而比拟麻烦。3.0 批改了组件的申明形式,改成了类式的写法,这样使得和 TypeScript 的联合变得很容易。

此外,vue 的源码也改用了 TypeScript 来写。其实当代码的性能简单之后,必须有一个动态类型零碎来做一些辅助治理。当初 vue3.0 也全面改用 TypeScript 来重写了,更是使得对外裸露的 api 更容易联合 TypeScript。动态类型零碎对于简单代码的保护的确很有必要。

(4)其它方面的更改

vue3.0 的扭转是全面的,下面只波及到次要的 3 个方面,还有一些其余的更改:

反对自定义渲染器,从而使得 weex 能够通过自定义渲染器的形式来扩大,而不是间接 fork 源码来改的形式。

反对 Fragment(多个根节点)和 Protal(在 dom 其余局部渲染组建内容)组件,针对一些非凡的场景做了解决。

基于 treeshaking 优化,提供了更多的内置性能。

vue 中应用了哪些设计模式
1. 工厂模式 – 传入参数即可创立实例

虚构 DOM 依据参数的不同返回根底标签的 Vnode 和组件 Vnode

2. 单例模式 – 整个程序有且仅有一个实例

vuex 和 vue-router 的插件注册办法 install 判断如果零碎存在实例就间接返回掉

3. 公布 - 订阅模式 (vue 事件机制)

4. 观察者模式 (响应式数据原理)

5. 装璜模式: (@装璜器的用法)

6. 策略模式 策略模式指对象有某个行为, 然而在不同的场景中, 该行为有不同的实现计划 - 比方选项的合并策略

Vue 模板编译原理
Vue 的编译过程就是将 template 转化为 render 函数的过程 分为以下三步

第一步是将 模板字符串 转换成 element ASTs(解析器)第二步是对 AST 进行动态节点标记,次要用来做虚构 DOM 的渲染优化(优化器)第三步是 应用 element ASTs 生成 render 函数代码字符串(代码生成器)

相干代码查看

export function compileToFunctions(template) {  // 咱们须要把 html 字符串变成 render 函数
  // 1. 把 html 代码转成 ast 语法树  ast 用来形容代码自身造成树结构 不仅能够形容 html 也能形容 css 以及 js 语法
  // 很多库都使用到了 ast 比方 webpack babel eslint 等等
  let ast = parse(template);  // 2. 优化动态节点
  // 这个有趣味的能够去看源码  不影响外围性能就不实现了
  //   if (options.optimize !== false) {//     optimize(ast, options);
  //   }

  // 3. 通过 ast 从新生成代码
  // 咱们最初生成的代码须要和 render 函数一样
  // 相似_c('div',{id:"app"},_c('div',undefined,_v("hello"+_s(name)),_c('span',undefined,_v("world"))))
  // _c 代表创立元素 _v 代表创立文本 _s 代表文 Json.stringify-- 把对象解析成文本
  let code = generate(ast);  //   应用 with 语法扭转作用域为 this  之后调用 render 函数能够应用 call 扭转 this 不便 code 外面的变量取值
  let renderFn = new Function(`with(this){return ${code}}`);  return renderFn;
}

为什么在 Vue3.0 采纳了 Proxy, 摈弃了 Object.defineProperty?
Vue 组件间通信有哪几种形式?
Vue3.0 和 2.0 的响应式原理区别?
vue 中应用了哪些设计模式?
Vue 的生命周期办法有哪些 个别在哪一步发申请?
你有对 Vue 我的项目进行哪些优化?
理解 nextTick 吗?
vue cli 我的项目中 src 目录每个文件夹和文件的用法
理解 nextTick 吗?
v-model 的原理?
Vue 组件间通信有哪几种形式?
更多面试题请点击:👉开发者网站 – 前端常见 vue 面试题大全

退出移动版