一、基础
Vue3笔记
- 文本模板
<span>Message: {{ msg }}</span>
- 原始html
<p>Using v-html directive: <span v-html="rawHtml"></span></p>
- 一次性插值
<span v-once>这个将不会改变: {{ msg }}</span>
- html attribute
<div v-bind:id="dynamicId"></div>
- bool attribute
<button v-bind:disabled="isButtonDisabled">按钮</button>
- 使用表达式
<div v-bind:id="'list-' + id"></div>
- v-bind 指令可以用于响应式地更新 HTML attribute
<a v-bind:href="url"> ... </a>
- v-on 指令,它用于监听 DOM 事件
<a v-on:click="doSomething"> ... </a>
- 动态参数
<a v-bind:[attributeName]="url"> ... </a>
- 修饰符
<form v-on:submit.prevent="onSubmit">...</form>
- v-bind 缩写
<a :href="url"> ... </a>
- v-on 缩写
<a @click="doSomething"> ... </a>
- 模板表达式都被放在沙盒中,只能访问一个受限的全局变量列表,如 Math 和 Date。你不应该在模板表达式中试图访问用户定义的全局变量
- 组件的 data 选项是一个函数。Vue 会在创建新组件实例的过程中调用此函数。它应该返回一个对象,然后 Vue 会通过响应性系统将其包裹起来,并以 $data 的形式存储在组件实例中。
- 这些实例 property 仅在实例首次创建时被添加,所以你需要确保它们都在 data 函数返回的对象中。
- Vue 自动为 methods 绑定 this,以便于它始终指向组件实例。
- 在定义 methods 时应避免使用箭头函数,因为这会阻止 Vue 绑定恰当的 this 指向。
- 防抖和节流,引入 Lodash
<script src="https://unpkg.com/lodash@4.17.20/lodash.min.js"></script>
<script>
app.component('save-button', {
created() {
// 使用 Lodash 实现防抖
this.debouncedClick = _.debounce(this.click, 500)
},
unmounted() {
// 移除组件时,取消定时器
this.debouncedClick.cancel()
},
methods: {
click() {
// ... 响应点击 ...
}
},
template: `
<button @click="debouncedClick">
Save
</button>
`
}
)
</script>
- 对于任何包含响应式数据的复杂逻辑,你都应该使用计算属性,如果你不希望有缓存,请用 method 来替代
<div id="computed-basics">
<p>Has published books:</p>
<span>{{ publishedBooksMessage }}</span>
</div>
Vue.createApp({
data() {
return {
author: {
name: 'John Doe',
books: [
'Vue 2 - Advanced Guide',
'Vue 3 - Basic Guide',
'Vue 4 - The Mystery'
]
}
}
},
computed: {
// 计算属性的 getter
publishedBooksMessage() {
// `this` 指向 vm 实例
return this.author.books.length > 0 ? 'Yes' : 'No'
}
}
}).mount('#computed-basics')
- 计算属性默认只有 getter,不过在需要时你也可以提供一个 setter
computed: {
fullName: {
// getter
get() {
return this.firstName + ' ' + this.lastName
},
// setter
set(newValue) {
const names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
- 虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器
- 绑定 HTML Class
// 对象语法
// way1
<div
class="static"
:class="{ active: isActive, 'text-danger': hasError }"
></div>
// way2
<div :class="classObject"></div>
data() {
return {
isActive: true,
error: null
}
},
computed: {
classObject() {
return {
active: this.isActive && !this.error,
'text-danger': this.error && this.error.type === 'fatal'
}
}
}
// 数组语法
<div :class="[activeClass, errorClass]"></div>
data() {
return {
activeClass: 'active',
errorClass: 'text-danger'
}
}
- 条件渲染
<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-show 的元素始终会被渲染并保留在 DOM 中。v-show 不支持<template> 元素,也不支持 v-else。
<h1 v-show="ok">Hello!</h1>
- 一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。
- 不推荐同时使用 v-if 和 v-for。当 v-if 与 v-for 一起使用时,v-if 具有比 v-for 更高的优先级。
- v-for
<ul id="v-for-object" class="demo">
<li v-for="value in myObject">
{{ value }}
</li>
</ul>
Vue.createApp({
data() {
return {
myObject: {
title: 'How to do lists in Vue',
author: 'Jane Doe',
publishedAt: '2016-04-10'
}
}
}
}).mount('#v-for-object')
- 建议尽可能在使用 v-for 时提供 key attribute,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。
- v-for维护状态
<div v-for="item in items" :key="item.id">
<!-- 内容 -->
</div>
- 当它们处于同一节点,v-if 的优先级比 v-for 更高,这意味着 v-if 将没有权限访问 v-for 里的变量,可以把 v-for 移动到 <template> 标签中来修正
<template v-for="todo in todos" :key="todo.name">
<li v-if="!todo.isComplete">
{{ todo.name }}
</li>
</template>
- 任何数据都不会被自动传递到组件里,因为组件有自己独立的作用域。为了把迭代数据传递到组件里,我们要使用 props
<my-component
v-for="(item, index) in items"
:item="item"
:index="index"
:key="item.id"
></my-component>
- 事件处理方法
<div id="event-with-method">
<!-- `greet` 是在下面定义的方法名 -->
<button @click="greet">Greet</button>
</div>
Vue.createApp({
data() {
return {
name: 'Vue.js'
}
},
methods: {
greet(event) {
// `methods` 内部的 `this` 指向当前活动实例
alert('Hello ' + this.name + '!')
// `event` 是原生 DOM event
if (event) {
alert(event.target.tagName)
}
}
}
}).mount('#event-with-method')
//////////////////////////////////
// 需要传参且处理事件
<button @click="warn('Form cannot be submitted yet.', $event)">
Submit
</button>
// ...
methods: {
warn(message, event) {
// 现在可以访问到原生事件
if (event) {
event.preventDefault()
}
alert(message)
}
}
- 多事件处理
<!-- 这两个 one() 和 two() 将执行按钮点击事件 -->
<button @click="one($event), two($event)">
Submit
</button>
// ...
methods: {
one(event) {
// 第一个事件处理器逻辑...
},
two(event) {
// 第二个事件处理器逻辑...
}
}
- 事件修饰符
<!-- 阻止单击事件继续冒泡 -->
<a @click.stop="doThis"></a>
<!-- 提交事件不再重载页面 -->
<form @submit.prevent="onSubmit"></form>
<!-- 修饰符可以串联 -->
<a @click.stop.prevent="doThat"></a>
<!-- 只有修饰符 -->
<form @submit.prevent></form>
<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div @click.capture="doThis">...</div>
<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div @click.self="doThat">...</div>
- 按键修饰符
<!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
<input @keyup.enter="submit" />
- 你可以用 v-model 指令在表单<input>、<textarea> 及 <select> 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但 v-model 本质上不过是语法糖。它负责监听用户的输入事件来更新数据,并在某种极端场景下进行一些特殊处理。
- text 和 textarea 元素使用 value property 和 input 事件;
checkbox 和 radio 使用 checked property 和 change 事件;
select 字段将 value 作为 prop 并将 change 作为事件。