一、模板语法
1.最基本的数据绑定形式是文本插值,使用双大括号:
<span>Message: {{ msg }}</span>
2.原始HTML:双大括号会将数据解释为纯文本,而不是 HTML。若想插入 HTML,使用 v-html指令:
<p>Using text interpolation: {{ rawHtml }}</p>
<p>Using v-html directive: <span v-html="rawHtml"></span></p>
3.Attribute 绑定:响应式地绑定一个 attribute,应该使用 v-bind:
<div v-bind:id="dynamicId"></div>
简写
<div :id="dynamicId"></div>
4.布尔型 Attribute:依据 true / false 值来决定 attribute 是否应该存在于该元素上,例如disanled:
<button :disabled="isButtonDisabled">Button</button>
5.动态绑定多个值
<div v-bind="objectOfAttrs"></div>
const objectOfAttrs = {
id: 'container',
class: 'wrapper'
}
6、使用 JavaScript 表达式
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
<div :id="`list-${id}`"></div>
7.调用函数
<time :title="toTitleDate(date)" :datetime="date">
{{ formatDate(date) }}
</time>
8.指令 Directives:一个指令的任务是在其表达式的值变化时响应式地更新 DOM。以 v-if 为例:
<p v-if="seen">Now you see me</p>
二、声明响应式状态
1.ref():在组合式 API 中,推荐使用 ref() 函数来声明响应式状态:
import { ref } from 'vue'
const count = ref(0)
ref
() 接收参数,并将其包裹在一个带有 .value
属性的 ref 对象中返回:
const count = ref(0)
console.log(count) // { value: 0 }
console.log(count.value) // 0
count.value++
console.log(count.value) // 1
2.<script setup>
中的顶层的导入、声明的变量和函数可在同一组件的模板中直接使用
<script setup>
import { ref } from 'vue'
const count = ref(0)
function increment() {
count.value++
}
</script>
<template>
<button @click="increment">
{{ count }}
</button>
</template>
3.Reactive Proxy vs. Original:reactive()
返回的是一个原始对象的 Proxy,它和原始对象是不相等的
const raw = {}
const proxy = reactive(raw)
// 代理对象和原始对象不是全等的
console.log(proxy === raw) // false
三、计算属性
<script setup>
import { reactive, computed } from 'vue'
const author = reactive({
name: 'John Doe',
books: [
'Vue 2 - Advanced Guide',
'Vue 3 - Basic Guide',
'Vue 4 - The Mystery'
]
})
// 一个计算属性 ref
const publishedBooksMessage = computed(() => {
return author.books.length > 0 ? 'Yes' : 'No'
})
</script>
<template>
<p>Has published books:</p>
<span>{{ publishedBooksMessage }}</span>
</template>
可写计算属性:通过同时提供 getter 和 setter 来创建:
<script setup>
import { ref, computed } from 'vue'
const firstName = ref('John')
const lastName = ref('Doe')
const fullName = computed({
// getter
get() {
return firstName.value + ' ' + lastName.value
},
// setter
set(newValue) {
// 注意:我们这里使用的是解构赋值语法
[firstName.value, lastName.value] = newValue.split(' ')
}
})
</script>
四、Class 与 Style 绑定
1.绑定 HTML class
<div :class="{ active: isActive }"></div>
:class 指令也可以和一般的 class attribute 共存。
const isActive = ref(true)
const hasError = ref(false)
<div
class="static"
:class="{ active: isActive, 'text-danger': hasError }"
></div>
渲染结果:
<div class="static active"></div>
绑定的对象并不一定需要写成内联字面量的形式,也可以直接绑定一个对象:
<div :class="classObject"></div>
const classObject = reactive({
active: true,
'text-danger': false
})
2.绑定数组:可以给 :class
绑定一个数组来渲染多个 CSS class:
const activeClass = ref('active')
const errorClass = ref('text-danger')
<div :class="[activeClass, errorClass]"></div>
渲染结果:
<div class="active text-danger"></div>
在数组中有条件地渲染某个class,使用三元表达式:
<div :class="[isActive ? activeClass : '', errorClass]"></div>
3.在组件上使用:对于只有一个根元素的组件,当使用了 class
attribute 时,这些 class 会被添加到根元素上并与该元素上已有的 class 合并。
<!-- 子组件模板 -->
<p class="foo bar">Hi!</p>
<!-- 在使用组件时 -->
<MyComponent class="baz boo" />
渲染HTML
<p class="foo bar baz boo">Hi!</p>
当 isActive 为真时,被渲染的 HTML 会是:
<p class="foo bar active">Hi!</p>
组件有多个根元素,需要指定哪个根元素来接收这个class
<!-- MyComponent 模板使用 $attrs 时 -->
<p :class="$attrs.class">Hi!</p>
<span>This is a child component</span>
<MyComponent class="baz" />
这将被渲染为:
<p class="baz">Hi!</p>
<span>This is a child component</span>
4.绑定对象::style
支持绑定 JavaScript 对象值,对应的是Html元素属性
const activeColor = ref('red')
const fontSize = ref(30)
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
5.绑定数组
<div :style="[baseStyles, overridingStyles]"></div>
五、条件渲染
1、v-if:指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回真值时才被渲染
<h1 v-if="awesome">Vue is awesome!</h1>
2、v-else:一个 v-else
元素必须跟在一个 v-if
或者 v-else-if
元素后面,否则它将不会被识别。
<button @click="awesome = !awesome">Toggle</button>
<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no 😢</h1>
3.v-else-if:
提供的是相应于 v-if
的“else if 区块”。它可以连续多次重复使用,和 v-else
类似,一个使用 v-else-if
的元素必须紧跟在一个 v-if
或一个 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>
4.<template>
上的 v-if:
v-if
是一个指令,他必须依附于某个元素
v-else
和 v-else-if
也可以在 <template>
上使用。
<template v-if="ok">
<h1>Title</h1>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</template>
5.v-show:
可以用来按条件显示一个元素的指令是 v-show
。其用法基本一样:
不同之处在于 v-show
会在 DOM 渲染中保留该元素;v-show
仅切换了该元素上名为 display
的 CSS 属性。
v-show
不支持在 <template>
元素上使用,也不能和 v-else
搭配使用
<h1 v-show="ok">Hello!</h1>
6. v-if与v-show的区别?什么时候使用v-if?
隐藏时候v-show是css方式隐藏,v-if是dom节点直接移除
什么时候用v-if?频繁切换显示与隐藏用v-show,反之用v-if
7.v-if
和 v-for:
先执行v-for,再执行v-if 资源浪费
六、列表渲染
1.v-for:指令基于一个数组来渲染一个列表
const items = ref([{ message: 'Foo' }, { message: 'Bar' }])
<li v-for="item in items">
{{ item.message }}
</li>
对于多层嵌套的 v-for
,作用域的工作方式和函数的作用域很类似。每个 v-for
作用域都可以访问到父级作用域
<li v-for="item in items">
<span v-for="childItem in item.children">
{{ item.message }} {{ childItem }}
</span>
</li>
也可以使用 of 作为分隔符来替代 in,这更接近 JavaScript 的迭代器语法:
<div v-for="item of items"></div>
2.v-for
与对象:可以使用 v-for
来遍历一个对象的所有属性。遍历的顺序会基于对该对象调用 Object.keys()
的返回值来决定
const myObject = reactive({
title: 'How to do lists in Vue',
author: 'Jane Doe',
publishedAt: '2016-04-10'
})
<ul>
<li v-for="value in myObject">
{{ value }}
</li>
</ul>
提供第二个参数表示属性名 (例如 key):
<li v-for="(value, key) in myObject">
{{ key }}: {{ value }}
</li>
第三个参数表示位置索引:
<li v-for="(value, key, index) in myObject">
{{ index }}. {{ key }}: {{ value }}
</li>
3.<template>
上的 v-for
<ul>
<template v-for="item in items">
<li>{{ item.msg }}</li>
<li class="divider" role="presentation"></li>
</template>
</ul>
4.通过 key 管理状态
为了给 Vue 一个提示,以便它可以跟踪每个节点的标识,从而重用和重新排序现有的元素,你需要为每个元素对应的块提供一个唯一的 key
attribute
<div v-for="item in items" :key="item.id">
<!-- 内容 -->
</div>
使用 <template v-for> 时,key 应该被放置在这个 <template> 容器上:
<template v-for="todo in todos" :key="todo.name">
<li>{{ todo.name }}</li>
</template>
5.组件上使用 v-for
可以直接在组件上使用 v-for
,和在一般的元素上使用没有区别 (要提供一个key值)
<MyComponent v-for="item in items" :key="item.id" />
但是,这不会自动将任何数据传递给组件,因为组件有自己独立的作用域。
为了将迭代后的数据传递到组件中,还需要传递 props:
<MyComponent
v-for="(item, index) in items"
:item="item"
:index="index"
:key="item.id"
/>