美文网首页
列表渲染

列表渲染

作者: greente_a | 来源:发表于2020-05-12 17:12 被阅读0次

    列表渲染适合于一些复用性比较高的元素
    关键词:v-for指令

    有序列表ol和无序列表ul是天然可以适用这种情况的元素。
    如下例子

    <ul id="vm1">
            <li v-for="item in items" :key="item.message">
                {{ item.message }}
            </li>
        </ul>
    
        <script>
            var vm1 = new Vue({
                el: '#vm1',
                data: {
                    items: [
                        { message: 'Foo' },
                        { message: 'Bar' }
                    ]
                }
            })
        </script>
    

    运行结果如图:


    重复化渲染

    我们可以看到,应用v-for,使用一个类似于循环的操作,遍历items中所有的对象,取出message值,这种复用可以减少html复杂而又几乎同质化的元素操作。

    当然,v-for指令还提供了index这个隐藏参数。
    我们可以使用index来确定元素在“数组”中的序列。

        <!-- 大胆猜测一下,内部实现可能是一个jsx语法的each迭代器 -->
        <ul id="vm2">
            <li v-for="(item, index) in items">
                {{ parentMessage }} - {{ index }} - {{ item.message }}
            </li>
        </ul>
    
        <script type="text/javascript">
            var vm2 = new Vue({
                el: '#vm2',
                data:{
                    parentMessage: 'Parent',
                    items: [
                        { message: 'Foo' },
                        { message: 'Bar' }
                    ]
                }
    
            })
        </script>
    
    如图所示~

    当然,v-for也可以用来遍历对象中的属性

        <ul id="vm3">
            <li v-for="value in object">
                {{ value }}
            </li>
        </ul>
    
        <script type="text/javascript">
            var vm3 = new Vue({
                el: '#vm3',
                data: {
                    object: {
                        title: 'Get subscribe and Hit the like button',
                        author: 'Luohuatingyu',
                        publishedAt: '2020-05-12'
                    }
                }
            })
        </script>
    
    内部类似于原生js中的for-in循环

    与此同时,键名作为一个可选参数,也可以出现在参数列表里。

    <!-- 官方解释是用Object.keys()遍历,由于各个浏览器使用的引擎不一致,所以会有些许差异 -->
    
        <ul id="vm3_1">
            <li v-for="(value, name, index) in object">
                No{{ index }}: "{{ name }}" : "{{ value }}"
            </li>
        </ul>
    
        <script type="text/javascript">
            var vm3_1 = new Vue({
                el: '#vm3_1',
                data: {
                    object: {
                        title: 'Get subscribe and Hit the like button',
                        author: 'Luohuatingyu',
                        publishedAt: '2020-05-12'
                    }
                }
            })
        </script>
    

    结果显而易见


    简单拼接

    在开始下面的介绍之前,先介绍一下JavaScript数组中的两类方法

    • 变异方法

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

    • 非变异方法

    filter()
    slice()
    ...

    显而易见,所有的变异方法都是对原数组进行修改的方法,而非变异方法反之,会得到一个新数组
    在Vue中,变异方法的调用,也会触发视图的更新操作
    这为我们提供了一个新思路,如果说,你的项目中不想对原数组进行修改,可以使用计算属性,每次获取一个原数组的拷贝

        <!-- 使用计算属性(不改变原数组) -->
        <ul id="vm4">
            <li v-for="n in evenNumbers">{{ n }}</li>
        </ul>
    
        <script type="text/javascript">
            var vm4 = new Vue({
                el: '#vm4',
                data: {
                  numbers: [ 1, 2, 3, 4, 5 ]
                },
                computed: {
                  evenNumbers: function () {
                    return this.numbers.filter(function (number) {
                      return number % 2 === 0
                    })
                  }
                }
            })
        </script>
    

    结果就像这样


    计算属性

    当然对于计算属性来说,多重循环是不适用的,这里我们可以用Vue中提供的方法。

        <!-- 可以使用even方法来应用于计算属性不适用的情况(例如多重循环) -->
        <div id="vm5">
            <ul v-for="set in sets">
              <li v-for="n in even(set)">{{ n }}</li>
            </ul>
        </div>
    
        <script type="text/javascript">
            var vm5 = new Vue({
                el: '#vm5',
                data: {
                  sets: [[ 1, 2, 3, 4, 5 ], [6, 7, 8, 9, 10]]
                },
                methods: {
                  even: function (numbers) {
                    return numbers.filter(function (number) {
                      return number % 2 === 0
                    })
                  }
                }
            })
        </script>
    

    这样就会有两个ul被渲染出来,对应两个子数组。


    计算属性不适用的情况

    既然v-for号称循环指令,最基本的计数循环也可以做。

    <!-- 使用整数来限制循环次数也是可以的 -->
        <div id="vm6">
          <span v-for="n in 10">{{ n }} </span>
        </div>
    
        <script type="text/javascript">
            var vm6 = new Vue({
                el: "#vm6"
    
            })
        </script>
    
    打印一组数字

    也可以结合template,渲染一组元素

        <!-- 也可以使用template渲染一组元素 -->
        <ul id="vm7">
          <template v-for="item in items">
            <li>{{ item.msg }}</li>
            <li class="divider" role="presentation"></li>
          </template>
        </ul>
    
        <style>
            .divider{
                opacity: 0;
                height: 2em;
                list-style: none;
            }
        </style>
    
        <script type="text/javascript">
            var vm7 = new Vue({
                el: '#vm7',
                data: {
                    items: [
                        { msg: "Hello" },
                        { msg: "Thank you" },
                        { msg: "Thank you very much" },
                        { msg: "How are you" },
                        { msg: "I am fine" }
                    ]
                }
            })
        </script>
    

    效果图如下,中间的空行用来格式控制,但是它们是实际存在的元素。

    格式控制

    有人会问了,那v-if和v-for有什么关系吗?

    在官方的文档中,不建议同时使用。
    如果使用了,优先级如下。

        <!-- 这个示例告诉我们,如果v-for和v-if出现在同一个标记上,那么先执行v-for,然后在v-if里进行判断是否渲染循环中的元素 -->
        <ul id="vm8">
            <li v-for="todo in todos" v-if="!todo.isComplete">
                {{ todo.title }} : {{ todo.content }}
            </li>
        </ul>
    
        <script type="text/javascript">
            var vm8 = new Vue({
                el: '#vm8',
                data: {
                    todos: [
                        { 
                            title: "Work",
                            content: "Coding web page with Vue",
                            isComplete: false
                         },
                         {
                            title: "Sleep",
                            content: "Having a nice sleep",
                            isComplete: true
                         },
                         {
                            title: "Learning",
                            content: "Learning the new abilitily of Vue",
                            isComplete: false
                         }
                    ]
                }
            })
        </script>
    
    v-for和v-if
    可以看到,在每一次循环进行之后,才会进行v-if的判断,要不要渲染这个元素。即v-for的优先级大于v-if

    如果你想做到按条件决定是否循环,请将v-if中的元素包裹在需要判断是否循环的元素外面。

        <ul v-if="todos.length">
          <li v-for="todo in todos">
            {{ todo }}
          </li>
        </ul>
        <p v-else>No todos left!</p>
    

    最后,又到了Vue关于原理的一部分,我也不太理解,贴点伪码。

        <!-- key是Vue中唯一标识一个元素的标记,提供这个标记使得Vue可以跟踪每一个子元素的状态。 -->
        <!-- 默认是就地渲染的,即更新子组件的值,并不修改组件,但是如果对子组件有依赖就很麻烦(比如其中的data-*域) -->
        <!-- 加key可以避免这一问题(目前我还没遇到) -->
        <div v-for="item in items" v-bind:key="item.id">
          <!-- 内容 -->
        </div>
    

    相关文章

      网友评论

          本文标题:列表渲染

          本文链接:https://www.haomeiwen.com/subject/fbzbnhtx.html