ホームページ  >  記事  >  ウェブフロントエンド  >  優先順位の比較: v-for と v-if はどちらが高いですか?

優先順位の比較: v-for と v-if はどちらが高いですか?

青灯夜游
青灯夜游転載
2022-08-29 19:52:053235ブラウズ

v-for と v-if ではどちらの方が優先されますか?次の記事では、v-forv-if の優先順位を実際の例とソースコードから説明します。

優先順位の比較: v-for と v-if はどちらが高いですか?

#結論

1. v-for と v-if を同時に使用することはお勧めできません。 (学習ビデオ共有:

vue ビデオ チュートリアル)

2. vue2 の v-for は v-if よりも優先されます。 vue2 はテンプレートのコンパイル時に v-for を処理し、次に v-if を処理するため、生成されたレンダリング関数は最初にループを実行し、その後ループ内で条件判定を実行します。

3. これを行うと発生する問題は次のとおりです。

シナリオ 1:

  • 再レンダリングするたびに、リスト全体を再走査する必要がありますが、実際にはリストの一部しか必要ないため、パフォーマンスが無駄になります。推奨されるアプローチは、計算された属性を通じて必要な部分をフィルタリングしてからレンダリングすることです。これはより効率的です。

    シナリオ 2 の場合:

  • 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を横断し、条件判定が行われることがわかります

    ソースコード

    v-ifとv-Forのソースコードの処理

    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()
    });
    (学習ビデオ共有:

    Web フロントエンド開発基本プログラミング ビデオ)

    以上が優先順位の比較: v-for と v-if はどちらが高いですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

  • 声明:
    この記事はjuejin.cnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。