Vue3入门 ----- script setup、computed、watch、组件通讯、ref
前言:因为公司的一个后台新项目决定用Vue3, 然而同事包括自己使用Vue3时, 除了一些语法例setup, defineComponent等与Vue2有区别外, 并没有其他特别的地方, 反而增添了开发的工作量. 觉得Vue3和Vue2最大的不同不该是语法上的不同, 故决定系统性地开展Vue3的学习.初使用和Vue2使用的optionsAPI(例如: 数据放 data 中, 方法放 methods
·
初使用
和Vue2使用的optionsAPI(例如: 数据放 data 中, 方法放 methods中)不同的是, Vue3是用了composition API, 提升了代码的可读性和可维护性, 同时也保留了Vue2的optionsAPI.
<template>
<div>当前点击次数:{{ count }}</div>
<button @click="add">点击</button>
</template>
<script lang="ts">
import { defineComponent, reactive, ref } from 'vue'
export default defineComponent({
setup() {
const count = ref(0)
const add = () => {
count.value++
}
return {
count,
add,
}
},
})
</script>
- composition api的使用, 需要配置一个setup 函数
- setup 函数是一个新的组件选项, 作为组件中 compositionAPI 的起点
- 从生命周期角度来看, setup 会在beforeCreate 钩子函数之前执行
- setup 中不能使用 this, this 指向 undefined 在模版中需要使用的数据和函数,需要在
setup
返回。
- ref 和 reactive 的最佳使用方式:
- 明确的对象,明确的属性,用 reactive,其他用 ref
- 从vue3.2之后,官方更推荐使用 ref
script setup
但是defineComponent和setup这种写法有点累赘, 所以现在官方推荐使用setup模板。 script setup是在单文件组件 (SFC) 中使用组合式 API 的编译时语法糖。相比于普通的 script 语法更加简洁
<template>
<div>当前点击次数:{{ count }}</div>
<button @click="add">点击</button>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const count = ref(0)
const add = () => {
count.value++
}
</script>
script setup 优势:
- 使用
ts
项目不需要再defineComponent
包裹了。 - 无需再
return
了,template
可直接使用,顶层的绑定会自动暴露给模板。
计算属性computed函数
在Vue3中 computed为函数, 写法有两种, 且可以使用多次
<template>
<div>原本的值 <input type="text" v-model.number="num" /></div>
<div>改变后的值 {{ nextNum }}</div>
<div>相互影响的值 <input type="text" v-model.number="revNum" /></div>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue'
const num= ref(10)
// 不带set的计算属性
const nextNum = computed(() => {
return num.value + 1
})
// 带set的计算属性
const revNum= computed({
get() {
return num.value + 2
},
set(val: number) {
num.value = val - 2
},
})
</script>
侦听器watch函数
watch 侦听器, 接收三个参数
- 参数1: 监视的数据源, 可传入多个监听值, 以数组格式传入
- 参数2: 回调函数
- 参数3: 额外的配置
// 监听单个ref
const num = ref(100)
watch(num, (value, oldValue) => {
console.log(value)
})
// 监听多个ref
const num1 = ref(100)
const num2 = ref(0)
watch([num1, num2], (value) => {
console.log(value)
})
// 监听ref复杂数据
const user = ref({
name: 'name',
age: 18,
})
watch(
user,
(value) => {
console.log('user变化了', value)
},
{
// 深度监听,当ref的值是一个复杂数据类型,需要深度监听
// 但是如果是以reactive创建的复杂类型数据,则不需要
deep: true,
immediate: true
}
)
组件通讯
父传子 (script setup中子组件引入后可以使用)
父组件中给子组件传值与Vue2相同故省略, 主要不同在子组件获取父组件的值, 不再使用props, 而需要使用defineProps
// 父组件给子组件传入两个值
<script setup lang="ts">
import { computed } from 'vue'
// 规定传递数据的类型
interface Props {
age: number
name: string
}
// defineProps: 接收父组件传递的数据
const props = defineProps<Props>()
// 使用
const addAge = computed(() => {
return props.age ++
})
</script>
<template>
<h3>子组件---{{ addAge }} --- {{ name }}</h3>
</template>
子传父
- 子组件通过
defineEmits
获取emit对象(因为没有this) - 子组件通过emit触发事件,并且传递数据
- 父组件提供方法
- 父组件通过自定义事件的方式给子组件注册事件,与Vue2相同,定义一个方法函数去接收值
// 子组件
const rValue = ref('give back')
// 定义回传的方法 defineEmits
const emit = defineEmits(['giveBack'])
const giveBack = () => {
emit('giveBack', rValue)
}
跨层级通讯-依赖注入 - provide 和 inject
- 父组件利用 provide 提供数据(数值与方法函数都可提供)
//父组件
import { provide, ref } from 'vue'
const num = ref(100)
// provide提供给子组件 key和value不需要相同
provide('num', num)
- 子组件利用inject来接收
<script setup lang="ts">
import { inject, Ref } from 'vue'
// inject来插入来自父组件的值
const getNum = inject<Ref<number>>('num')
const changeNum = (m: number) => {
getNum && getNum.value ++
}
</script>
<template>
<h5>子组件--{{ getNum }}</h5>
<button @click="changeNum">修改</button>
</template>
- 注意: 如果用defineProps来通讯, 子组件必须用defineEmit来父组件接收来改变父组件的值,因为prop的值是readonly。而通过provide/inject的值,子组件可以直接修改,但也可以通过provide一个方法给子组件修改。
模板中 ref 的使用
在标签中使用 ref="xxx"
来记录取的哪个元素
在script中,通过赋值来取得值,但是赋值的命名必须与标签中的命名一致
<div ref="divRef">通过Ref拿我</div>
<button @click="changeRefHTML>点我改变</button>
//script
const divRef = ref<HTMLDivElement | null>(null)
const changeRefHTML = () => {
if (divRef.value) {
divRef.value.innerHTML = '变了'
}
}
通过ref获取子组件的值/方法
//父组件中使用子组件
<Form ref="formRef" />
<button @click="changeSon">点我改变</button>
// 获取子组件
import Form from "./components/Form.vue"
// typeof获取类型 Instancetype 泛型类型
const formRef = ref<InstanceType<typeof Form> | null>(null)
const changeSon = () => {
if (refForm.value) {
// 子组件里面的方法/取值方法类似
refForm.value.refMethod()
}
}
更多推荐
已为社区贡献4条内容
所有评论(0)