Detailed explanation of Vue's conditional and loop rendering to cases


Knowledge points

v-if 和 v-else

v-if

The v-if directive is used to conditionally render a block of content. This content will only be rendered if the directive's expression returns a value other than false, 0, "", null, undefined and 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>

Insert image description here
v-else

Use the v-else directive to represent the "else block" of v-if. When v-if returns a value other than false, 0, "", null, undefined and NaN, it is rendered. Otherwise, the v-else block is rendered. element.

<!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>

Insert image description here
注意:v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别。

v-show

Another option for conditionally displaying elements is the v-show directive. The difference is that elements with v-show will always be rendered and remain in the DOM. v-show simply toggles the element's CSS property display. And v-if operates from the virtual DOM level.

<!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 and v-show comparison

Generally speaking, v-if involves the virtual DOM diff algorithm and has higher switching overhead, while v-show has higher initial rendering overhead. Therefore, if you need to switch very frequently, it is better to use v-show; if the conditions rarely change at runtime, it is better to use v-if.

v-for renders array data into elements

Loop rendering is often used. In development, we often encounter block codes with the same DOM structure, so we can use loop rendering to get it right in one step.

v-for renders the array data into elements
loops the menu array into a completed menu:

<!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>

Insert image description here

v-for renders object data into elements

In development, the data we obtain is often in the form of objects.
Object data loops out data:

<!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>

Insert image description here
注意

Due to JavaScript limitations, Vue cannot detect the addition or deletion of object attributes. Directly performing app.userInfo.height=‘180cm’ will not constitute a responsive operation and will not trigger a view update. Reactive properties must be added to nested objects using the Vue.set(object, key, value) method.
Directly set app.userInfo.height=‘170cm’, but the view failed to update:

Insert image description here

Use the Vue.set(object, key, value) method:

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

Insert image description here

Therefore, when using object methods, if you want to trigger view updates, you often need to use Vue.set() to operate.

key attribute

To give Vue a hint so that it can keep track of the identity of each node and thus reuse and reorder existing elements, you need to provide a unique key attribute for each item. The ideal key value is a unique id for each item. This special property is equivalent to Vue 1.x's track-by, but it works like a property, so you need to v-bind to bind the dynamic value (using the shorthand here).

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

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

Array update detection

Some methods of operating arrays will be detected by the compiler, which will prompt the view to be updated.

mutation method

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

The above array operation methods will directly change the original array, which are called mutation methods, and will cause the view to automatically update.

replace array

Anyone who has studied the JavaScript standard object library knows that some array methods do not directly change the original array. They are called non-mutation methods here, such as filter(), slice(), and concat(). They all return a new array. So, how can we use these methods in Vue to update the view? We must use the array replacement method to directly assign the new array returned by the non-mutation method to the old array.

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

注意

Due to JavaScript limitations, Vue cannot detect the following changed arrays:

  • When you set an item directly using the index, for example: vm.items[indexOfItem] = newValue.
  • When you modify the length of the array, for example: vm.items.length = newLength.

example:

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

There is no problem with directly changing the value like this, but it is not responsive and cannot trigger view updates. It needs to be replaced by other methods.
For example, the operation app.items[indexOfItem] = newValue can be replaced by the following two methods.

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

show filter

Displays a filtered or sorted copy of an array without actually changing or resetting the original data. In this case, you can create a computed property that returns a filtered or sorted array. example:

<!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>

Insert image description here

If you don't want to use calculated properties, you can also use methods directly to operate, for example:

<!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>

Insert image description here

v-for loops through a range of values

During development, we will encounter situations where we need a value, whether it is character splicing or paging, we all need to use it. In Vue, we can use v-for to easily implement it. Loop out 10 pages of pagination:

<!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>

Insert image description here

Use v-for with v-if

Nested controls in loops are very common in development, and we can also use them in Vue.
For example, if the array has elements, it will be rendered in a loop, and if there are no elements, the prompt message will be rendered:

<!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>

Insert image description here

There are no elements in the array numbers:[]:

Comprehensive exercises, multi-level cool menu rendering

This exercise integrates array rendering, object rendering, v-if, v-show, key event methods and other knowledge.

<!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>

Guess you like

Origin blog.csdn.net/Argonaut_/article/details/129254230