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的主要内容,如果未能解决你的问题,请参考以下文章