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