1 createApp
通过createApp可以创建一个vue实例,传入值为组件
应用实例必须在调用了.mount()
方法后才会渲染出来,接收参数为实际DOM元素
或css选择器
.mount()方法应该在整个应用配置和资源注册完成后调用,返回值为根组件实例
1.1 应用配置config
应用实例会暴露一个.config
对象允许物品们配置一些应用级选项
例如:定义一个错误处理器
app.config.errorHandler=(err)=>{}
1.2 注册可用资源
例如:注册组件,在全局可用
app.component('button',button)
2 模板语法
2.1 动态参数
动态参数中表达式的值应当是一个字符串或者null
<a :[attributeName]="url" />
<a @[eventName]="url" />
2.2 修饰符
比如:.prevent修饰符告诉v-on触发事件调用event.preventDefault()
<div @click.prevent="btnClick"/>
2.3 响应式
reactive
返回的是一个原始对象的Proxy
,他和原始对象是不相等的
reactive的限制:
(1)仅对对象类型有效,对string、boolean、number无效
(2)将响应式变量赋值或解构至本地变量时,或将该属性传入一个函数时,会丢失响应性
const state = reactive({count:0})
let n=state.count
n++ // n=1 state.count=0
fn(state.count) //只接受了一个数组,并无法跟踪count的变化
ref可以传递给函数并不丢失响应式,变量解构也不会丢失响应式
注意:只有当ref是顶层属性时,在template中使用不用带value,可以通过将foo改成顶层属性解决这个问题
//{{ object.foo + 1 }}不会像预期那样工作,返回[object Object]
let obj={
foo:ref(1)
}
const {foo}=obj
//{{ object.foo }} 这样可以
2.4 计算属性
computed方法期望接收一个getter函数,返回值为一个计算属性ref,计算属性值会基于其响应式依赖被缓存
可写计算属性
const n1=ref('bob')
const n2=ref('john')
const fullname=computed({
get(){
return n1+''+n2
}
set(val){
[n1.value,n2.value]=val.split('')
}
})
注意:不要在计算属性中做异步请求或者更改DOM
2.5 class和style
如果组件有多个根元素,可以使用$attrs指定哪个根元素来接收这个class
2.6 v-if和v-show
在template上可以使用v-if但不能使用v-show
使用v-if条件区块内的事件监听器和子组件都会被销毁和重建,v-show元素始终会被渲染,只是css的display属性变为none
v-if和v-for同时存在于一个元素上时,v-if会首先被执行
3 事件处理
事件修饰符:
- .stop:禁止冒泡
- .prevent:禁止默认事件
- .self:仅当event.target为元素本身时
- .capture
- .once
- .passive:默认行为立即发生
4 v-model
(1)正常情况下,v-model会在每次input
事件后更新数据,添加lazy
修饰符改为在每次change
事件后更新数据
(2)如果想用户输入自动转化为数字,可以在v-model后添加.number
修饰符
(3)如果默认自动取出用户输入内容的两端空格,可以在v-model后添加.trim
修饰符
5 侦听器
watch不能直接监听reactive对象的值,而需要使用一个返回该属性的getter函数
watchEffect
不需要传递监听的内容,会自动感知代码依赖,只需要传递一个回调参数即可
默认情况下,创建的侦听器会在vue组件更新之前被调用,如果期望能访问更新后的DOM,需要指明flush:‘post’
或使用watchPostEffect()
6 模板引用
使用v-for时对应的ref值为一个数组
注意:ref还可以进行动态绑定
<input :ref="input">
const input=(el)=>{}
使用ref绑定在子组件上,获得的是组件实例
7 组件基础
在多个组件间进行切换,传入给is的值可以是被注册的组件名,导入的组件对象
<component :is=""/>
某些元素仅在放置于特定元素中才会显示,这导致使用带有此类限制元素的组件时出现问题:
<table>
<blog></blog>
</table>
此时blog组件会被忽略,可以使用is属性解决这个问题,在使用在原生html元素上时,is的值必须加上vue前缀
<table>
<tr :is="vue:blog"></tr>
</table>
8 透传Attributes
传递给组件却没有被声明为props、emit的属性或v-on事件监听器,最常见的就是class、id、style
如何禁用透传?
//新建一个script
<script>
export default{
inhertiAttrs: false
}
</script>
禁用透传attributes的使用场景:将attributes用于根节点以外的元素
9 markRaw
将响应式数据变为非响应式数据
应用于以下场景:
1、有些值不应该是响应式的,例如第三方类实例或vue组件对象
2、呈现不可变数据源的大型列表时,跳过代理可以提高性能
10 作用域插槽
特殊情况下,插槽内容想要同时使用父组件和子组件内的数据,那么可以对slot使用props传递子组件内的数据
<Bar v-slot="slotProps">{{slotProps.text}}</Bar>
<Bar v-slot="{text,count}"></Bar>
<Bar>
<template #header="headerProps"></template>
</Bar>
11 异步组件
在大型项目中,可能需要拆分应用为更小的块,并仅在需要时再从服务器加载相关组件
import {defineAsyncComponent} from 'vue'
const AsyncComp = defineAsyncComponent(()=>{
return new Promise((resolve,reject)=>{
resolve()
})
})
const AsyncComp = defineAsyncComponent(()=>import('')
})
加载与错误状态
const AsyncComp=defineAsyncComponent({
loader:()=>import('')
//加载异步组件时使用的组件
loadingComponent:LoadingComponent,
//加载组件前的延迟时间
delay:200,
//加载失败后的组件
errorComponent:ErrorComponent,
//超时显示失败组件
timeout:3000,
})
12 自定义指令
只有当所需功能只能通过直接的DOM操作来实现时,才应该使用自定义指令
<script setup>
const vFocus = {
mounted :(el)=>el.focus()
}
</script>
const app = createApp({})
app.directive('focus',{})
13 插件
编写一个可以在全局调用翻译的函数
<p>{{$translate('sdad.hello')}}</p>
export default{
install:(app,options)=>{
app.config.globalProperties.$translate=(key)=>{
return key.split('.').reduce((prev,next)=>{
if(prev)return prev[next]
},options)
}
//提供翻译字典对象
app.provide('i18n',options)
}
}
14 transition组件
仅支持单个元素或组件作为其插槽内容,进入和离开由以下条件触发:
- v-if
- v-show
- <component>
css过渡class:
- v-enter-from:进入动画的起始状态,在元素插入之前添加,在元素插入完成后下一帧移除
- v-enter-active:进入动画的生效状态
- v-enter-to:进入动画的结束状态
- v-leave-active:离开动画的生效状态
- v-leave-to
- v-leave-from
15 Teleport
它可以将一个组件内部的一部分模板传送到该组件的DOM结构外层的位置去
应用场景:全屏的模态框,通过点击按钮实现开关