8.7 KiB
Vue 3
1.环境搭建
vue3项目创建
node版本要在15.0或更高版本
npm install vue@latest
这个指令将会安装并执行create-vue
,它是Vue官方的项目脚手架工具。
创建时名称不要有大写
开发环境
VScode
+ volar
插件
2.Vue API 风格
vue的组件可以按两种不同的风格书写:选项式API(vue2) 和 组合式API(vue3) 大部分的核心概念在两种风格之间都是通用的。
选项式API(Options API)
使用选项式API,我们可以用包含多个选项的对象来描述组件的逻辑,例如data
、methods
、created
、mounted
、computed
。选项所定义的属性都会暴露在函数内部的this
上,它会指向当前的组件实例。
3.组合式API
3.1 setup函数
-
setup函数的执行时机:beforeCreate钩子之前 自动执行
-
setup写代码的特点是:定义数据 + 函数 然后以对象方式return 后才可以在模板中使用
-
<script setup>
语法糖解决以对象的形式返回繁琐写法 -
setup中的this无法找到组件实例,此时this是一个undefined
3.2 响应式数据
- reactive(): 声明对象类型的值,如数组
<script setup>
import { reactive } from 'vue'
// reactive()的作用是接受对象类型数据的参数并返回一个响应式的对象
const obj = reactive({
name: '',
age: 90
})
</script>
- ref()函数:声明基础数据类型的值,
<script setup>
import { ref } from 'vue'
const count = ref(0);
const setCount = ()=>{
// 在脚本区域修改ref产生的响应式对象数据,必须通过.value属性
count.value++
}
</script>
3.3 计算属性
computed
计算属性函数,基本思想和vue2的完全一致,组合式API下的计算属性只是修改了写法:
<script setup>
import { computed } from 'vue'
const count = ref(0);
const computedCountFlag =computed( ()=>{
// 返回基于响应式数据做计算后的值
return count.value > 10
})
</script>
注意:
- 计算属性中不应该有“副作用”,比如异步请求或是修改dom
- 计算属性应该是只读的,避免直接修改计算属性的值
3.4 watch
作用:侦听一个或者多个数据 的变化,数据(响应式的数据)变化时执行回调函数,额外参数:
immediate
:立即执行deep
:深度侦听
deep 默认机制:通过watch监听的ref对象默认是千层监听的,直接修改嵌套的对象属性不会触发回调执行,需要开启deep选项
精确监听
<script setup>
import { ref ,watch } from 'vue'
const person = ref({
name:'',
age:100
});
// 只有当age变化时在执行
watch(()=>person.value.age,(newAge,oldAge)=>{
console.log('age变化了')
})
</script>
3.5 生命周期函数
Vue3中生命周期API(选项式 VS 组合式)
选项式API | 组合式API |
---|---|
beforeCreate/created | setup |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeUnmount | onBeforeUnmount |
unmounted | onUnmounted |
可多次执行函数
<script setup>
import { onMounted } from 'vue'
onMounted(()=>{
console.log('组件挂载完毕1')
})
onMounted(()=>{
console.log('组件挂载完毕3')
})
onMounted(()=>{
console.log('组件挂载完毕2')
})
// log结果1/3/2
</script>
3.6 组件通信
父传子
基本操作:
- 父组件中给子组件绑定属性
- 子组件内部通过props选项接收
<script setup>
//引入子组件,setup语法糖下局部组件无需注册直接可以使用
import sonCom from './sonCom'
let msg = 'this is app message'
</script>
<template>
<!-- 绑定属性 message-->
<sonCom :message="msg"></sonCom>
</template>
<script setup>
// 通过 deineProps “编译器宏函数” 接收父组件传递的数据
const props = defineProps({
message:{
type: String,
default: ''
},
info:String
})
// ts泛型的写法
const props = defineProps<{
title:string
}>()
// ts泛型带上默认值
withDefaults(defineProps<{
message:string,
arr: string[]
}>(), {
arr:() => ['A', 'B']
})
console.log('父组件传入的值:',props.message)
</script>
<template>
{{message}}
</template>
如果父组件传入的是响应式数据,则数据变化,子组件接受的数据也会变化
扩展:利用ts的泛型限定传参类型,message参数为必传,arr为可选。
<script setup>
// 通过 deineProps “编译器宏函数” 接收父组件传递的数据
const props = defineProps<{
message:String,
arr?:string[]
}>()
console.log('父组件传入的值:',props.message)
</script>
<template>
{{message}}
</template>
子传父
基本操作:
- 父组件中给子组件标签通过
@
绑定事件 - 子组件内部通过
$emit
方法触发事件
<script setup>
//引入子组件,setup语法糖下局部组件无需注册直接可以使用
import sonCom from './sonCom'
const getMessage = (msg)=>{
console.log(msg)
}
</script>
<template>
<!-- 绑定属性 message-->
<sonCom @get-message="getMessage"></sonCom>
</template>
<script setup>
// 通过 deineEmits “编译器宏函数” 生成 emit 方法
const emit = deineEmits(['get-message'])
const sendMsg = ()=>{
emit('get-message','发送给父组件的数据')
}
</script>
<template>
<button @click="sendMsg">发送</button>
</template>
3.7 模版引用
通过ref标识
获取真实的dom对象或者组件实例对象。
示例:
<script setup>
import {ref} from 'vue'
import TestCom from './test-com.vue'
// 1.调用ref函数得到ref对象,相当于生成了一个容器一样用于存放dom对象
const h1Ref = ref(null)
const testRef = ref(null)
// 组件挂载完毕之后才能获取
onMounted(()=>{
console.log(h1Ref.value)//<h1>H1标签</h1>
console.log(testRef.value)//组件的代理对象
})
</script>
<template>
<!-- 2.通过ref标识绑定ref对象-->
<h1 ref='h1Ref'>H1标签</h1>
<TestCom ref='testRef'></TestCom>
</template>
defineExpose()
默认情况下在<script setup>
语法糖下组件内部的属性和方法是不开放给父组件访问的,可以通过defineExpose编译宏指定哪些属性和方法允许访问。
<script setup>
import {ref} from 'vue'
const name = ref('test name')
const setName = (name='new name')=>{
name.value = name
}
// 为了防止组件内部的属性和方法被修改,默认是不暴露的,如果明确要提供给外部需要用defineExpose编译宏显示声明
defineExpose({
name,
setName
})
</script>
3.8 provide和inject
作用和场景:顶层组件向任意的底层组件传递数据和方法,实现跨层组件通信。
基本操作:
-
顶层组件通过
provide
函数提供数据// 传递的过程中保持响应式,传入ref对象 provide('key',顶层组件中的数据)
-
底层组件通过
inject
函数获取数据const message = inject('key')
跨层传递方法
场景:在底层组件需要修改顶层组件的数据,但单向数据流的原则,不建议直接修改传过来的数据。可以通过在顶层组件中提供一个修改数据的方法,传递给底层组件让其调用来修改数据。(谁的数据就由谁修改)
顶层组件:
const setCount = ()=>{
count.value++
}
provide('setCount-key',setCount)
底层组件:
const setCount = inject('setCount-key')
3.9 获取组件实例
getCurrentInstance
的返回值是一个组件实例对象.
- 可以通过
.ctx
来访问该实例的上下文对象; - 者通过
.proxy
来访问该实例的代理对象。
两者的区别在于,通过.ctx
访问的是真实的组件实例,而通过 .proxy
访问的是一个代理对象,该代理对象可以在模板中直接使用。
getCurrentInstance 只能在 setup 或生命周期钩子中使用
import { getCurrentInstance, onMounted} from 'vue'
export default {
setup() {
onMounted(() => {
const instance = getCurrentInstance()
console.log('实例', instance)
})
return {}
}
}