这是我参与「第五届青训营 」伴学笔记创作活动的第 22 天
API
Vue项目由多个单文件组件组成,单文件组件将这个组件的JavaScript(script标签中)、HTML(template标签中)、CSS(style标签中)封装到一个后缀为.vue的文件中。组件有以下两种书写风格:
选项式API
使用包含多个选项的对象来组成逻辑,选项所定义的属性都会暴露在指向当前组件的this上。
组合式API
使用导入(import)的API函数来描述组件逻辑。
基础
应用
创建应用
每个应用都通过Vue的createApp函数创建,应用可以保存在变量中。
传入createApp函数的是一个组件,这个组件作为根组件,其它组件可以作为子组件。
组件可以从单文件组件直接导入。
import App from './App.vue'
const app = createApp(App)
应用实例会暴露多个方法和对象。
挂载应用
应用被创建之后可以只有在调用了.mount()方法挂载到一个容器( DOM元素或者CSS选择器的字符串)上之后才可以被渲染。注意
<div id="app"></div>
app.mount('#app')
注意把js脚本文件放在html的最后,因为需要挂载到前面的元素上。
可以创建多个应用让其分别挂载到页面的不同位置,每个应用都有自己的用于配置和全局资源的作用域。
模板语法
文本插值
Vue可以使双大括号替换为相应组件中msg 属性的值。
<span>{{ msg }}</span>
msg还可以是JavaScript的表达式,但这个表达式必须是可以求值的(即把return加在前面也合法),相当于表达式返回一个值赋给msg。
attribute的值并不支持双大括号语法(Mustache语法)。
指令
指令是带有v-前缀的特殊attribute。
某些指令可能需要一个参数(attribute),在指令名后通过:隔开。指令参数可以是JavaScript表达式,在一对[]中,尽量不去使用大写。
指令还可以具有修饰符(.开头的特殊后缀),表明指令需要以特殊的方式被绑定。
值可以是JavaScript的表达式,也可以是组件中暴露的函数。
指令的任务是在状态改变时响应式的更新DOM。
v-html
如果msg的值为HTML,就不能使用{{}}这种方法,双大括号会将数据解释为纯文本。
插入HTML需要使用v-html指令。
<script>
export default {
data() {
return {
msg: '<span style="color: red">Red msg'
}
}
}
</script>
<template>
<p><span v-html="msg"></span></p>
</template>
v-bind
名字:参数.修饰符=值
v-bind指令用于响应式的绑定一个attribute。此时的属性值会随着vid进行改变。
<div v-bind:id="vid"><div/>
或者使用简写语法。
<div :id="vid"><div/>
可以通过不带参数的v-bind,将一个包含多个attribute的对象绑定到一个元素上。
data() {
return {
atts: {
id: "aid",
class: "aclass"
}
}
}
<div v-bind="atts"><div/>
当绑定的值为null或者undefined,这个attribute将会被移除。感觉可以用来搭配属性选择器。
响应式基础
DOM的更新并不是同步的,无论状态发生了多少次改变,每个组件直到下一次时机都只更新一次。
组合式
可以通过reactive()函数(接受一个对象作为参数)或者ref()方法创建响应式的对象(其实是Proxy对象即对象的代理)或者数组。
reactive()
必须用通过setup()函数将定义的响应式对象返回,才能使其被暴露到模板中。定义操作也是在这个函数中完成的。
还可以在setup()函数中定义并返回响应式的函数。
import { reactive } from 'vue'
export default {
setup() {
const state = reactive( { x: 0} )
function fc() {
//...
}
return {
x,
fc
}
}
}
默认导出/导出必须位于模块或文件的顶层。
还可以借助<script setup>,只需在里面进行定义即可,也不需要export default。
但是reactive不支持原生类型,而且替换响应式对象会导致初始化的响应式链接丢失。
ref()
ref()会将传入的参数转换为带.value属性的对象并返回,使用value属性对值进行访问。
当ref被作为顶层属性使会自动进行解包,就不需要.value属性了。但是集合类型的元素不会被解包。
选项式
选项式API用data(值为返回一个对象的函数)选项声明组件的响应式状态,之后用this进行访问。
export default {
data {
return {
state: 0
}
}
}
计算属性
可以使用计算属性来描述依赖响应式状态的复杂逻辑。 相比与方法计算属性值会基于响应式状态进行缓存,因为方法会在重新渲染时执行函数,而计算属性只要响应式状态不发生改变就不会执行getter。
组合式
计算属性的创建需要借助于computed()方法,接受一个getter函数,返回一个计算属性ref。
如果想要改变属性的值,可以在创建计算属性时同时传入一个setter函数。
<script>
import { ref } from 'vue'
const fname = ref("qg")
const lname = ref("xx")
const name = computed({
get() {
return fname.value + ' ' + lname.value
},
set(n) {
[fname.value, lname.value] = n.split(' ')
}
})
</script>
想使用普通属性一样使用name:使用值name.value,重新赋值name.value = jq yy。因为是响应式的,fname和lname属性也会随之改变。
选项式
通过computed选项,可以只添加具有get功能的函数,也可以添加同时具有getter和setter的对象。
<script>
export default {
data() {
return {
fname: "qg",
lname: "xx"
}
},
computed: {
name: {
get() {
return this.fname + ' ' + this.lname
},
set(n) {
[this.fname, this.lname] = n.split(' ')
}
}
}
}
</script>
class与style绑定
这需要使用v-bind指令对其进行绑定,指令可以和原有的属性共存。
class
可以和动态字符串、对象、数组进行绑定。
表达式:
<div :class="isActive ? CActive : ''"></div>
对象:
<div class="1" :class="{ active: isActive, 'text-danger': hasError }"></div>
<script setup>
const classObject = reactive({
active: true,
'text-danger': false
})
</script>
<template>
<div :class="classObject"></div>
</template>
数组:
<script setup>
const CActive = ref('active')
const CError = ref('text-danger')
</script>
<div :class="[CActive, CError]"></div>
表达式也和对象也可以作为数组的元素。
在使用组件时,class会和组件模板的class合并。
style
可以直接和对象或数组进行绑定。
<script setup>
const styleObject = reactive({
color: 'red',
display: 'block'
})
</script>
<template>
<div :style="styleObject"></div>
</template>
<script setup>
const colorVal = ref('red')
const fontSize = ref(20)
</script>
<template>
<div :style="{ color: colorVal, fontSize: fontSize + 'px' }"></div>
</template>
绑定的样式属性可以具有多个值,会选择浏览器支持的最后一个值。
<div :style="{ :style: ['-webkit-box', 'flex']}"></div>
:style支持自动前缀,使用了浏览器特殊前缀的属性时,会自动加上。
渲染
条件渲染
v-if、v-else-if、v-else
用类似于if-else的条件语句来进行条件渲染,当表达式为真值时才会被渲染。
<div v-if="type === 1"></div>
<div v-else-if="type === 2"></div>
<div v-else></div>
如果需要同时切换多个元素,可以把v-if指令放在<template>上。
v-show
v-show指令会在DOM渲染中保留该元素,仅会切换display属性。
列表渲染
在对列表进行渲染时可以使用v-for指令基于数组或对象来渲染。
v-for指令类似于for-in语句。
<script setup>
const items = ref([{msg: '1'}, {msg: '2'}])
</script>
<li v-for="(item, index) in items" :key="item.id">
{{ index}} {{item.msg}}
</li>
通过绑定key来管理状态。
<script>
const items = reactive({
title: "",
arguments: "",
auther: ""
})
</script>
<ul>
<li v-for="(value, key, index) in items" :key="item.id">
{{ index }}. {{ key }}: {{ value }}
</li>
</ul>
在使用组件时必须通过绑定才能使用数据。
<Component
v-for="(item, index) in items"
:item="item" :index="index" :key="item.id"
/>
事件处理
通过使用v-on指令来监听DOM实践。
v-on:事件="事件处理器"或@事件="事件处理器"
事件处理器可以是JavaScript语句或者方法。
使用方法时会自动传递一个原生事件(在方法定义时要准备名为event的参数,使用时不需要传入),也可以自定义传入的参数来代替默认的事件。
<script setup>
function greet(event) {
if (event) {
alert(event.target.tagName)
}
</script>
<template>
<button @click="greet">Greet</button>
</template>
在处理器中访问DOM事件时需要传入$event变量。
<script setup>
function greet(msg, event) {
if (event) {
event.preventDefault()
}
alert(msg)
</script>
<template>
<button @click="greet('greet', $event)">Greet</button>
</template>
修饰符
通过给v-on指令增加修饰符可以规定事件的触发。
条件修饰符
.once时间只触发一次。
.prevent组织事件默认行为。
……
修饰符可以使用链式书写。
按键修饰符
.enter、.tap ……
系统按键修饰符:.ctrl、.alt、.shift、.meta可以和其它按键修饰符组合触发事件
.exact规定触发事件所需的确定组合的修饰符。
表单输入绑定
在把表单得到的value同步给JavaScript的变量时可以使用v-model指令。
v-model的值是要进行更新的响应式变量。
使用v-bind响应式绑定+v-on事件处理:
<script setup>
import { ref } from 'vue'
const message = ref('')
</script>
<template>
<p>Message is: {{ message }}</p>
<input :value="message" @input="event => message = event.target.value" placeholder="edit me" />
</template>
使用v-model指令:
<script setup>
import { ref } from 'vue'
const message = ref('')
</script>
<template>
<p>Message is: {{ message }}</p>
<input v-model="message" placeholder="edit me" />
</template>
值绑定
文本、单选按钮、选择器默认传递的都是value属性的值,复选框传递的是true/false。
文本、单选按钮、选择器可以通过v-bind绑定value传递响应式的值,复选款可以绑定true-value、false-value在为true/false时传递绑定的值。
v-model指令也可以添加修饰符。
.trim:去除两端空格.number转换为数字.lazy每次change事件后更新数据
声明周期
通过注册声明周期钩子,可以在特定阶段运行代码。
侦听器
使用watch函数可以创建数据源响应式状态发生改变时调用回调函数的侦听器。侦听器的创建必须用同步语句。侦听器创建时会返回一个函数,这个函数可以用于停止侦听器。
第一个参数被称作数据源,可以时响应式对象、ref、getter(用来代替响应式对象的属性值)、数组。
添加{deep: true} 可以创建深层的侦听器,嵌套发生变换就会触发回调。
添加{immediate: true} ,可以让回调在创建时立即执行。
使用watchEffec函数,为其传入一个回调函数作为参数,不需要明确指定源,也不需要额外添加 { immediate: true} ,回调会立即执行。但要和使用watch一样创建响应式状态,watchEffect会自动跟踪一切可以访问的响应式属性作为源,并在源发生改变时执行回调。
添加{flush: post},可以让回调访问更新之后的DOM,因为默认会先执行侦听器回调。也可以使用
watchPostEffect函数。
模板引用
在<script>定义一个空的ref,并在元素中为其增加ref属性,值与定义的ref同名,在被挂载之后,就能得到这个模板的引用。
<script setup>
import { ref } from 'vue'
const input = ref(null)
</script>
<template>
<input ref="input" />
</template>