欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

常见的前端 vue 面试问题,不会就不好问了

最编程 2024-07-14 10:52:32
...

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

  • 实践中不应该把v-forv-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 移动至容器元素上 (比如ulol)或者外面包一层template即可
  • 文档中明确指出永远不要把v-if 和v-for 同时用在同一个元素上,显然这是一个重要的注意事项
  • 源码里面关于代码生成的部分,能够清晰的看到是先处理v-if还是v-for,顺序上vue2vue3正好相反,因此产生了一些症状的不同,但是不管怎样都是不能把它们写在一起的

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面试题大全​

推荐阅读