Vueの条件付きレンダリングとループレンダリングを事例まで詳しく解説


知識のポイント

v-if 和 v-else

v-if

v-if ディレクティブは、コンテンツのブロックを条件付きでレンダリングするために使用されます。このコンテンツは、ディレクティブの式が false、0、""、null、未定義、NaN 以外の値を返した場合にのみ表示されます。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>syl-vue-test</title>
    <!-- 引入 vue.js -->
    <script src="vue.min.js"></script>
  </head>
  <body>
    <div id="app">
      <p v-if="display">你好,实验楼</p>
      <p>SYL</p>
    </div>
    <script>
      var app = new Vue({
      
      
        el: "#app",
        data: {
      
      
          display: true,
        },
      });
    </script>
  </body>
</html>

ここに画像の説明を挿入します
v-その他

v-if の "else ブロック" を表すには、v-else ディレクティブを使用します。v-if が false、0、""、null、未定義、および NaN 以外の値を返す場合、その値が表示されます。それ以外の場合、v-elseブロックがレンダリングされます。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>syl-vue-test</title>
    <!-- 引入 vue.js -->
    <script src="vue.min.js"></script>
  </head>
  <body>
    <div id="app">
      <p v-if="display">你好,实验楼</p>
      <p v-else>SYL</p>
    </div>
    <script>
      var app = new Vue({
      
      
        el: "#app",
        data: {
      
      
          display: true,
        },
      });
    </script>
  </body>
</html>

ここに画像の説明を挿入します
注意:v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别。

Vショー

要素を条件付きで表示するためのもう 1 つのオプションは、v-show ディレクティブです。違いは、v-show を持つ要素は常にレンダリングされ、DOM に残ることです。 v-show は、要素の CSS プロパティの表示を切り替えるだけです。そして、v-if は仮想 DOM レベルで動作します。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>syl-vue-test</title>
    <!-- 引入 vue.js -->
    <script src="vue.min.js"></script>
  </head>
  <body>
    <div id="app">
      <p v-show="show">你好,实验楼</p>
    </div>
    <script>
      var app = new Vue({
      
      
        el: "#app",
        data: {
      
      
          show: true,
        },
      });
    </script>
  </body>
</html>

v-if と v-show の比較

一般に、v-if には仮想 DOM diff アルゴリズムが含まれており、スイッチング オーバーヘッドが高くなりますが、v-show は初期レンダリング オーバーヘッドが高くなります。したがって、頻繁に切り替える必要がある場合は v-show を使用することをお勧めします。実行時に条件がほとんど変更されない場合は、v-if を使用することをお勧めします。

v-for は配列データを要素にレンダリングします

ループ レンダリングがよく使用されます。開発では、同じ DOM 構造を持つブロック コードに遭遇することがよくあるため、ループ レンダリングを使用して 1 ステップで正しく処理できます。

v-for は配列データを要素にレンダリングします
メニュー配列をループして完成したメニューにします:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>syl-vue-test</title>
    <!-- 引入 vue.js -->
    <script src="vue.min.js"></script>
    <style>
      * {
      
      
        padding: 0;
        margin: 0;
      }
      ul {
      
      
        width: 100%;
        height: 40px;
        list-style: none;
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: center;
        background: yellowgreen;
      }
      ul li {
      
      
        width: 20%;
        height: 100%;
        color: white;
        line-height: 40px;
        text-align: center;
        text-transform: uppercase; /*大写转换*/
      }
    </style>
  </head>
  <body>
    <div id="app">
      <ul class="nav">
        <li v-for="navItem in nav">{
   
   {navItem}}</li>
      </ul>
    </div>
    <script>
      var app = new Vue({
      
      
        el: "#app",
        data: {
      
      
          nav: ["home", "shop", "contact", "about", "name", "mroe", "histroy"],
        },
      });
    </script>
  </body>
</html>

ここに画像の説明を挿入します

v-for はオブジェクト データを要素にレンダリングします

開発中、取得するデータはオブジェクトの形式であることがよくあります。
オブジェクト データがデータをループアウトする:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>syl-vue-test</title>
    <!-- 引入 vue.js -->
    <script src="vue.min.js"></script>
  </head>
  <body>
    <div id="app">
      <div v-for="val in userInfo">
        <p>{
   
   {val}}</p>
      </div>
    </div>
    <script>
      var app = new Vue({
      
      
        el: "#app",
        data: {
      
      
          userInfo: {
      
      
            name: "whh",
            age: 1,
            sex: "woman",
          },
        },
      });
    </script>
  </body>
</html>

ここに画像の説明を挿入します
注意

JavaScript の制限により、Vue はオブジェクト属性の追加または削除を検出できません。app.userInfo.height=‘180cm’ を直接実行しても応答性の高い操作にはならず、ビューの更新はトリガーされません。リアクティブ プロパティは、Vue.set(object, key, value) メソッドを使用してネストされたオブジェクトに追加する必要があります。
app.userInfo.height=‘170cm’ を直接設定しましたが、ビューの更新に失敗しました:

ここに画像の説明を挿入します

Vue.set(object, key, value) メソッドを使用します。

Vue.set(app.userInfo, "height", "170cm");

ここに画像の説明を挿入します

したがって、オブジェクト メソッドを使用する場合、ビューの更新をトリガーしたい場合は、多くの場合、Vue.set() を使用して操作する必要があります。

キー属性

Vue にヒントを与えて各ノードの ID を追跡し、既存の要素を再利用したり並べ替えたりできるようにするには、項目ごとに一意のキー属性を提供する必要があります。理想的なキー値は、各アイテムの一意の ID です。この特別なプロパティは Vue 1.x の track-by と同等ですが、プロパティのように機能するため、動的値をバインドするには v-bind が必要です (ここでは省略表現を使用しています)。

<div v-for="item in items" :key="item.id">
  <!-- 内容 -->
</div>

注意:key 并不与 v-for 特别关联,建议尽可能在使用 v-for 时提供 key,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。

配列更新の検出

配列を操作する一部のメソッドはコンパイラによって検出され、ビューの更新を要求されます。

突然変異法

  • 押す()
  • ポップ()
  • シフト()
  • シフト解除()
  • スプライス()
  • 選別()
  • 逆行する()

上記の配列操作メソッドは、元の配列を直接変更し (ミューテーション メソッドと呼ばれます)、ビューを自動的に更新します。

配列を置き換える

JavaScript 標準オブジェクト ライブラリを学習したことがある方は、一部の配列メソッドが元の配列を直接変更しないことをご存知でしょう。ここでは、これらを非突然変異メソッドと呼びます (filter()、slice()、concat() など)。これらはすべて、では、Vue でこれらのメソッドを使用してビューを更新するにはどうすればよいでしょうか?非突然変異メソッドによって返された新しい配列を古い配列に直接割り当てるには、配列置換メソッドを使用する必要があります。

this.nav = this.nav.slice(1, 4);

注意

JavaScript の制限により、Vue は次の変更された配列を検出できません。

  • インデックスを使用して項目を直接設定する場合 (例: vm.items[indexOfItem] = newValue)。
  • 配列の長さを変更する場合、たとえば、vm.items.length = newLength となります。

例:

var app = new Vue({
  data: {
    items: ["a", "b", "c"],
  },
});
app.items[1] = "x"; // 不是响应性的
app.items.length = 2; // 不是响应性的`在这里插入代码片`

このように で値を直接変更することに問題はありませんが、応答性が悪く、ビューの更新をトリガーできないため、他のメソッドに置き換える必要があります。
たとえば、操作 app.items[indexOfItem] = newValue は、次の 2 つのメソッドで置き換えることができます。

// Vue.set
Vue.set(vm.items, indexOfItem, newValue);
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue);

フィルターを表示

元のデータを実際に変更またはリセットすることなく、フィルター処理または並べ替えられた配列のコピーを表示します。この場合、フィルター処理または並べ替えられた配列を返す計算プロパティを作成できます。例:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>syl-vue-test</title>
    <!-- 引入 vue.js -->
    <script src="vue.min.js"></script>
  </head>
  <body>
    <div id="app">
      <span v-for="number in oddNumber">{
   
   {number}}</span>
    </div>
    <script>
      var app = new Vue({
      
      
        el: "#app",
        data: {
      
      
          numberArray: [1, 2, 3, 4, 5, 6, 7, 8],
        },
        computed: {
      
      
          // 计算 numberArray 中为奇数的 oddNumber 奇数数组
          oddNumber: function () {
      
      
            return this.numberArray.filter(function (number) {
      
      
              return number % 2 === 1;
            });
          },
        },
      });
    </script>
  </body>
</html>

ここに画像の説明を挿入します

計算されたプロパティを使用したくない場合は、次のようなメソッドを直接使用して操作することもできます。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>syl-vue-test</title>
    <!-- 引入 vue.js -->
    <script src="vue.min.js"></script>
  </head>
  <body>
    <div id="app">
      <!-- v-for 内直接调用方法 -->
      <span v-for="number in getOddNumber()">{
   
   {number}}</span>
    </div>
    <script>
      var app = new Vue({
      
      
        el: "#app",
        data: {
      
      
          numberArray: [1, 2, 3, 4, 5, 6, 7, 8],
        },
        methods: {
      
      
          // 定一个一个获取数组内奇数的方法 filter 数组对象的过滤方法
          getOddNumber: function () {
      
      
            return this.numberArray.filter(function (number) {
      
      
              return number % 2 === 1;
            });
          },
        },
      });
    </script>
  </body>
</html>

ここに画像の説明を挿入します

v-for は値の範囲をループします

開発中には、文字のスプライシングやページングなど、値が必要な状況に遭遇することがありますが、Vue では v-for を使用して簡単に実装できます。 10 ページのページネーションをループアウトします。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>syl-vue-test</title>
    <!-- 引入 vue.js -->
    <script src="vue.min.js"></script>
  </head>
  <body>
    <div id="app">
      <!-- :style 绑定样式 -->
      <span v-for="number in 10" :style="styleObject">{
   
   {number}}</span>
    </div>
    <script>
      var app = new Vue({
      
      
        el: "#app",
        data: {
      
      
          // 指定分页样式
          styleObject: {
      
      
            fontSize: "14px",
            color: "#fff",
            background: "green",
            padding: "5px 10px",
            border: "1px solid #fff",
          },
        },
      });
    </script>
  </body>
</html>

ここに画像の説明を挿入します

v-for を v-if とともに使用する

ループ内のネストされたコントロールは開発において非常に一般的であり、Vue でも使用できます。
たとえば、配列に要素がある場合はループで表示され、要素がない場合はプロンプト メッセージが表示されます。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>syl-vue-test</title>
    <!-- 引入 vue.js -->
    <script src="vue.min.js"></script>
  </head>
  <body>
    <div id="app">
      <div v-if="numbers.length">
        <div v-for="item in numbers">{
   
   {item}}</div>
      </div>
      <div style="color:red" v-else>请添加数组元素</div>
    </div>
    <script>
      var app = new Vue({
      
      
        el: "#app",
        data: {
      
      
          numbers: [1, 2, 3, 4],
        },
      });
    </script>
  </body>
</html>

ここに画像の説明を挿入します

配列番号:[]: に要素がありません。

包括的な演習、マルチレベルのクールなメニューのレンダリング

この演習では、配列レンダリング、オブジェクト レンダリング、v-if、v-show、キー イベント メソッド、その他の知識を統合します。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>syl-vue-test</title>
    <style>
      * {
      
      
        padding: 0;
        margin: 0;
      }
      a {
      
      
        text-decoration: none;
        color: #fff;
      }
      ul {
      
      
        list-style: none;
      }
      nav,
      ul {
      
      
        width: 100%;
        display: flex; /* 开启弹性盒模型 布局方式*/
        flex-direction: row;
        justify-content: center;
        background: yellowgreen;
      }
      nav > ul > li {
      
      
        width: 20%;
        height: 100%;
        text-align: center;
        line-height: 50px;
      }
      nav > ul > li:hover {
      
      
        box-shadow: 1px 0px 10px #fff;
      }
      nav > ul > li > ul {
      
      
        display: flex;
        flex-direction: column;
      }
      nav > ul > li > ul > li {
      
      
        box-shadow: 1px 0px 10px #fff;
      }
      nav > ul > li > a {
      
      
        text-transform: uppercase;
      }
    </style>
    <!-- 引入 vue.js -->
    <script src="vue.min.js"></script>
  </head>
  <body>
    <div id="app">
      <nav>
        <ul>
          <!-- 循环渲染一级菜单 -->
          <!-- 鼠标移入触发 currentIndex(index) 函数,更正 current 是当前菜单的 index,鼠标移出重置 current 为空,事件回调方法在 methods 中实现-->
          <li
            v-for="(nav,index) in navbar"
            :key="index"
            @mouseover="currentIndex(index)"
            @mouseout="changeIndex"
          >
            <!-- nav.name 一级菜单名字 -->
            <a href="javascript:;">{
   
   {nav.name}}</a>
            <!-- 如果 nav.child 存在,说明有子菜单,再次循环渲染子菜单 -->
            <!-- 子菜单 v-show  如果当前菜单的 index 等于 鼠标移入那个菜单的下标我们就展示出子菜单-->
            <ul v-if="nav.child" v-show="current===index">
              <li v-for="item in nav.child">
                <a href="javascript:;">{
   
   {item}}</a>
              </li>
            </ul>
          </li>
        </ul>
      </nav>
    </div>
    <script>
      var app = new Vue({
      
      
        el: "#app",
        data: {
      
      
          // navbar 模拟后台获取到的菜单列表
          navbar: [
            {
      
      
              name: "home",
              child: ["homeItem", "homeItem"],
            },
            {
      
      
              name: "contact",
              child: ["contactItem", "contactItem"],
            },
            {
      
      
              name: "about",
            },
          ],
          // current 当前鼠标在那个菜单上,初始时没有值
          current: null,
        },
        methods: {
      
      
          // 更正 当前鼠标移入的是哪个菜单的 index
          currentIndex: function (index) {
      
      
            this.current = index;
          },
          // 鼠标移出 重置 current 值
          changeIndex: function () {
      
      
            this.current = null;
          },
        },
      });
    </script>
  </body>
</html>

おすすめ

転載: blog.csdn.net/Argonaut_/article/details/129254230