ホームページ > 記事 > ウェブフロントエンド > 優先順位の比較: v-for と v-if はどちらが高いですか?
v-for と v-if ではどちらの方が優先されますか?次の記事では、v-for
と v-if
の優先順位を実際の例とソースコードから説明します。
vue ビデオ チュートリアル)
2. vue2 の v-for は v-if よりも優先されます。 vue2 はテンプレートのコンパイル時に v-for を処理し、次に v-if を処理するため、生成されたレンダリング関数は最初にループを実行し、その後ループ内で条件判定を実行します。 3. これを行うと発生する問題は次のとおりです。シナリオ 1:
globalShow 実際にこの判断は、 false の場合、ループを実行する必要はありませんが、v-if で使用されるため、globalShow が true かどうかに関係なくループを実行する必要があり、これは完全に無駄です。推奨されるアプローチは、v-if を ul コンテナーに移動することです。 4. vue3 の重大な変更では、v-if は vue3 の v-for よりも優先度が高いため、シナリオ 1 でこれらを同時に使用すると、ユーザーは現時点ではまだ v がありません。 -if="user.show" はエラー 5 を報告します。一般に、eslint を使用する場合、エラーも報告されます。対応するルールは次のとおりです: vue /no-use-v-if-with-v- for実際の例例: 次のテンプレートは次のレンダリング関数を生成します
<ul> <li v-for="user in users" v-if="user.isActive" :key="user.id"> {{ user.name }} </li> </ul>生成されたレンダリング関数は次のとおりです
with(this) { return _c('ul', _l((users), function (user) { return (user.isActive) ? _c('li', user.name) : _e() }), 0) }上から生成 レンダリング関数を見ると、
_lが最初に実行されて
userを横断し、条件判定が行われることがわかります
src/compiler/index.js
// 模板解析,生成ast树 const ast = parse(template.trim(), options) if (options.optimize !== false) { optimize(ast, options) } const code = generate(ast, options)ast に基づいてコードを生成します。上記のテンプレートの場合、生成される ast は次のように簡略化されます。
// 可以看出v-for和v-if都解析出来了 ast = { 'type': 1, 'tag': 'ul', 'attrsList': [], 'attrsMap': {}, 'children': [{ 'type': 1, 'tag': 'li', 'attrsList': [], 'attrsMap': { 'v-for': 'user in users', 'v-if': 'user.show' }, // v-if解析出来的属性 'if': 'user.show', 'ifConditions': [{ 'exp': 'user.show', 'block': // 指向el自身 }], // v-for解析出来的属性 'for': 'users', 'alias': 'user', 'iterator1': 'index', 'parent': // 指向其父节点 'children': [ 'type': 2, 'expression': '_s(user)' 'text': '{{user}}', 'tokens': [ {'@binding':'user'}, ] ] }] }
compiler/codegen/index.js
// generate 调用 genElement const code = ast ? genElement(ast, state) : '_c("div")' // genElement里面的处理 if (el.staticRoot && !el.staticProcessed) { return genStatic(el, state) } else if (el.once && !el.onceProcessed) { return genOnce(el, state) // 从这可以看出来,先执行genFor,处理v-for指令,在genFor里面会递归调用genElement,继续处理v-if,genFor会将forProcessed设为true,这样下次进来的时候就不会处理for了 } 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 { // 最后这里处理标签等 const children = el.inlineTemplate ? null : genChildren(el, state, true) code = `_c('${el.tag}'${ data ? `,${data}` : '' // data }${ children ? `,${children}` : '' // children })` } // genFor的代码 const exp = el.for // 对应上面ast的 for: users const alias = el.alias // alias: user // iterator1 对应v-for的(item,key,index) in items的key // iterator2 对应的是index // 通常我们遍历数组 key就是index // 假如我们遍历的是对象 key就是对象的key,index就是遍历的索引 const iterator1 = el.iterator1 ? `,${el.iterator1}` : '' const iterator2 = el.iterator2 ? `,${el.iterator2}` : '' el.forProcessed = true // 下次递归调用genElement的时候就不会重复处理v-for了 return `${altHelper || '_l'}((${exp}),` + `function(${alias}${iterator1}${iterator2}){` // 这里处理完了v-for,递归调用genElement继续处理v-if `return ${(altGen || genElement)(el, state)}` + '})'
最終的には次のようなコードを生成し、それを返します
_l((users), function(user, index) { // 如果有v-if 前面就会有个条件判断,如user.isActive return (user.isActive) ? _c('li', user.name) : _e() });(学習ビデオ共有:
以上が優先順位の比較: v-for と v-if はどちらが高いですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。