vue3学习随便记6

Posted sjg20010414

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue3学习随便记6相关的知识,希望对你有一定的参考价值。

条件渲染

v-if

有v-if并没有v-end,所以v-if必须用在元素上,靠元素本身的配对来决定起止。如

<h1 v-if="awesome">Vue is awesome!</h1>

有 v-else

<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no 😢</h1>

也有 v-else-if  (这个使用频率不高)

<div v-if="type === 'A'">
  A
</div>
<div v-else-if="type === 'B'">
  B
</div>
<div v-else-if="type === 'C'">
  C
</div>
<div v-else>
  Not A/B/C
</div>

v-show

和 v-if 对应的有 v-show,这个前面的帖子已经分析过。

v-if 和 v-for 一起使用

v-if 和 v-for 一般不应该一起使用,而两者如果一起使用,v-if 的优先级是要高于 v-for 的。

列表渲染

用 v-for 把一个 JS 数组映射成一组元素

<html>

<head>
    <script src="vue.global.js"></script>
</head>

<body>
    <div id="list-rendering">
        <ul>
            <li v-for="item in items">
                 item.message 
            </li>
        </ul>
        <hr>
        <ul>
            <li v-for="(item, index) in items">
                 parentMessage  -  index  -  item.message 
            </li>
        </ul>
        <hr>
        <ul>
            <li v-for="item of items">
                 item.message 
            </li>
        </ul>
    </div>
    <script>
        const ListRendering = 
            data() 
                return 
                    parentMessage: 'Parent',
                    items: [
                         message: 'Foo' ,
                         message: 'Bar' ,
                         message: 'Tee' 
                    ]
                
            
        
        Vue.createApp(ListRendering).mount('#list-rendering')
    </script>
</body>

</html>

渲染结果为

 如果不使用索引,那么第三种 of 语法其实更符合 javascript 的迭代器风格,只是多数情况我们习惯了 in 语法。对于 v-for 块,它可以使用父作用域的所有属性,例如第二段中的 parentMessage。

用 v-for 遍历对象

<html>

<head>
    <script src="vue.global.js"></script>
</head>

<body>
    <div id="object-rendering">
        <ul>
            <li v-for="value in myObject">
                 value 
            </li>
        </ul>
        <hr>
        <ul>
            <li v-for="(value, key) in myObject">
                 key :  value 
            </li>
        </ul>
        <hr>
        <ul>
            <li v-for="(value, key, index) in myObject">
                 index .  key :  value 
            </li>
        </ul>
    </div>
    <script>
        const ObjectRendering = 
            data() 
                return 
                    myObject: 
                        title: 'How to do list in vue',
                        author: 'Jane Doe',
                        publishedAt: '2022-01-01'
                    
                
            
        
        Vue.createApp(ObjectRendering).mount('#object-rendering')
    </script>
</body>

</html>

用 v-for 遍历对象和遍历数组并没有什么不同,只是遍历对象通常随带key(也可以同时用index,但意义不大)。vue内部按 Object.keys() 顺序来遍历,所以,不同的浏览器JS引擎遍历结果有可能不一致,应该是 JS 对对象的键散列算法决定了顺序。

维护状态

v-for 渲染元素列表,默认使用“就地更新”策略,即两个数据项顺序改变,Vue不是去移动DOM节点来匹配数据项的顺序,而是就地更新每个元素。虽然这个模式是高效的,但 Vue 推荐在多数情况下,为每个DOM节点绑定一个唯一的key(这是Vue识别节点的通用机制),从而可以识别跟踪和复用重排这些节点。

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

不绑定 key 适合于简单的 DOM 渲染或者刻意需要就地更新来获取性能提升。

数组更新检测

变更方法

Vue3 中被侦听的数组的变更方法会被包裹,从而它们会触发视图的更新。被包裹过的方法包括:

4个队列操作方法 push()pop()shift()unshift(),任意位置增删 splice(),排序 sort(),逆序 reverse()

替换数组

对于非变更方法(不会变更原始数组的方法),例如 filter()concat() slice(),它们总是返回一个新数组,要实现响应,可以用这个新数组替换旧数组。Vue在替换数组时,会最大程度复用相同的元素。

<html>

<head>
    <script src="vue.global.js"></script>
</head>

<body>
    <div id="list-rendering">
        <ul>
            <li v-for="item in items">
                 item.message 
            </li>
        </ul>
        <hr>
        <ul>
            <li v-for="(item, index) in items">
                 parentMessage  -  index  -  item.message 
            </li>
        </ul>
        <hr>
        <ul>
            <li v-for="item of items">
                 item.message 
            </li>
        </ul>
        <button @click="change1">修改数组1</button>
        <button @click="change2">修改数组2</button>
    </div>
    <script>
        const ListRendering = 
            data() 
                return 
                    parentMessage: 'Parent',
                    items: [
                         message: 'Foo' ,
                         message: 'Bar' ,
                         message: 'Tee' 
                    ]
                
            ,
            methods: 
                change1() 
                    this.items.push(message: 'Baz ' + (new Date()))
                ,
                change2() 
                    this.items = this.items.filter(item => item.message.match(/Ba/))
                
            
        
        Vue.createApp(ListRendering).mount('#list-rendering')
    </script>
</body>

</html>

上述代码中,change1 是变更方法 push 触发更新,change2 是替换数组触发更新。

显示过滤/排序后的结果

如果不想实际变更或者替换掉原始数组,但需要显示数组经过过滤或排序后的版本,我们可以创建一个计算属性,返回过滤或排序后的数组。

<html>

<head>
    <script src="vue.global.js"></script>
</head>

<body>
    <div id="list-rendering">
        <ul>
            <li v-for="n in evenNumbers" :key="n">
                 n 
            </li>
        </ul>
        <button @click="change">修改</button>
    </div>
    <script>
        const ListRendering = 
            data() 
                return 
                    numbers: [1, 2, 3, 4, 5]
                
            ,
            computed: 
                evenNumbers() 
                    return this.numbers.filter(number => number % 2 === 0)
                
            ,
            methods: 
                change() 
                    this.numbers.push(Math.floor(Math.random()*100))
                    console.log(this.numbers)
                
            
        
        Vue.createApp(ListRendering).mount('#list-rendering')
    </script>
</body>

</html>

 从运行结果来看,我们知道,对于vm的属性中的数组(vm.numbers),会被包裹成一个 Proxy,而计算属性 evenNumbers 则返回数组(console(this.evenNumbers) 将打印出数组)。

在 v-for 里使用值的范围

v-for 迭代的对象,除了数组、对象,也可以是一个整数n,此时,表示1~n的一个序列。

<div id="range" class="demo">
  <span v-for="n in 10"> n  </span>
</div>

上述代码显示12345678910

在 <template> 中使用 v-for

        <ul>
            <template v-for="item in items" :key="item.message">
                <li> item.message </li>
                <li class="divider" role="presentation"></li>
            </template>
        </ul>

v-for 与 v-if 一起使用

v-for 与 v-if 一起使用是不被推荐的,如果的确一起使用,需要注意优先级和相关的坑。

<li v-for="todo in todos" v-if="!todo.isComplete">
   todo.name 
</li>

上面的代码是错误的!原因是 v-for 和 v-if 一起使用,v-if 的优先级高于 v-for,从而 todo 是找不到的!解决办法是把 v-if 移到 v-for 内,外面用 <template>

<template v-for="todo in todos" :key="todo.name">
  <li v-if="!todo.isComplete">
     todo.name 
  </li>
</template>

在组件上使用 v-for 

因为组件就是自定义的元素,所以,可以用 v-for 来产生一堆组件实例

<html>

<head>
    <script src="vue.global.js"></script>
</head>

<body>
    <div id="todo-list">
        <form v-on:submit.prevent="addNewTodo">
            <label for="new-todo">添加待办事项</label>
            <input v-model="newTodoText" id="new-todo" placeholder="例如: 收拾房间" />
            <button>添加</button>
        </form>
        <ul>
            <todo-item v-for="(todo, index) in todos" :key="todo.id"
                :title="todo.title" @remove="todos.splice(index, 1)"
            ></todo-item>
        </ul>
    </div>
    <script>
        const app = Vue.createApp(
            data() 
                return 
                    newTodoText: '',
                    todos: [
                        
                            id: 1,
                            title: '收拾碗筷'
                        ,
                        
                            id: 2,
                            title: '清除垃圾'
                        ,
                        
                            id: 3,
                            title: '拖地'
                        
                    ],
                    nextTodoId: 4
                
            ,
            methods: 
                addNewTodo() 
                    this.todos.push(
                        id: this.nextTodoId++,
                        title: this.newTodoText
                    )
                    this.newTodoText = ''
                
            
        )
        app.component('todo-item', 
            template: `
                <li>
                     title 
                    <button @click="$emit('remove')">移除</button>
                </li>
            `,
            props: ['title'],
            emits: ['remove']
        )
        app.mount('#todo-list')
    </script>
</body>

</html>

 

我们观察组件模板,组件通过 props 定义了属性 title,以便组件实例可以从外部接收数据,组件用emits 定义了可发射事件 remove,以便组件实例可以从外部响应 remove事件。通常,额外定义的emits事件往往转嫁到HTML已有的某个事件上,例如,这里click事件的处理方式是调用实例API函数$emit('remove') 来触发 remove 事件。

以上是关于vue3学习随便记6的主要内容,如果未能解决你的问题,请参考以下文章

vue3学习随便记7

vue3学习随便记7

vue3学习随便记11

vue3学习随便记10

vue3学习随便记10

vue3学习随便记8