1、ref函数标注类型:
如果是简单值,该类型可以省略,利用类型推导就可以。
如果是复杂类型,指定泛型
<template>
ref,{{ money }}
<ul>
<li v-for="item in list" :key="item.id">{{ item.name }}</li>
</ul>
</template>
<script setup lang="ts">
import {ref} from 'vue'
const money = ref<number>(10)
// 复杂数据,通过泛型指定数据的类型
const list = ref<{id:number, name:string}[]>()
</script>
2、reactive函数类型
通过泛型参数的形式增加类型
<template>
<p>{{ list.id }}</p>
<p>{{ list.name }}</p>
<p>{{ list.price }}</p>
</template>
<script setup lang="ts">
import {reactive} from 'vue'
type TodoList = {
id?:string,
name?:string,
price?:number
}
const list = reactive<TodoList>({})
</script>
3、defineProps组件
父组件传值
<template>
<MySon :msg="msg" :num="num"></MySon>
</template>
<script setup lang="ts">
import MySon from './MySon.vue'
import { ref } from 'vue';
const msg = ref('hello')
const num = ref(123)
</script>
子组件接收(在defineProps后面使用泛型)
<template>
Myson {{ msg }} {{ num }}
</template>
<script lang="ts" setup>
//const { msg, num = 100 } 给默认值
const { msg, num = 100 } = defineProps<{ msg: String, num: Number }>()
</script>
如果提供的默认值需要在模板中渲染,需要额外添加配置
在vite.config.js文件中
// vite.config.js
export default {
plugins: [
vue({
reactivityTransform: true
})
]
}
详情见文档
4、defineEmits(子传父)
子组件
<template>
Myson {{ msg }} {{ num }}
<button @click="updateMsg">点击修改msg</button>
</template>
<script lang="ts" setup>
const { msg, num = 100 } = defineProps<{ msg: String, num: Number }>()
// const emit = defineEmits(['update-msg'])
const emit = defineEmits < {
(e: 'update-msg', newMsg: String) :void //e:是事件类型,newMsg:参数 (固定格式)
}> ()
const updateMsg = () => {
emit('update-msg','你好')
}
</script>
父组件
<template>
<MySon @update-msg="hupdateMsg" :msg="msg" :num="num"></MySon>
</template>
<script setup lang="ts">
import MySon from './MySon.vue'
import { ref } from 'vue';
const msg = ref('hello')
const num = ref(123)
const hupdateMsg = (newMsg:string) => {
msg.value = newMsg
}
</script>
5、事件处理
例子: mousemove事件
<template>
<button @mousemove="hmousemove">鼠标move事件</button>
</template>
<script setup lang="ts">
const hmousemove = (e:MouseEvent) => {
console.log(e.x,e.y)
}
</script>
6、模板引用Ref
<template>
<div ref="RefDiv">这里是内容</div>
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue';
// 指定类型
const RefDiv = ref<HTMLElement | null>(null)
onMounted(() => {
console.log('RefDiv',RefDiv.value)
// RefDiv.value?.innerHTML = 'abc' 可选链操作符 这里会报错 会自动加上?号,
RefDiv.value!.innerHTML = 'abc'
})
</script>
技巧:如何查看一个DOM对象的类型:通过控制台进行查看
document.createElement('img').__proto__
7、ref操作组件
子组件
<template>
<div>子组件{{num}}</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const num = ref(10)
const setNum = (newNum:number) => {
num.value = newNum
}
// 暴露参数,方法
defineExpose({num,setNum})
</script>
父组件
<template>
<MySon ref="refCom"></MySon>
</template>
<script setup lang="ts">
import MySon from './MySon.vue'
import { ref, onMounted } from 'vue';
// typeof MySon 获取组件类型
// InstanceType <构造器>
const refCom = ref<InstanceType<typeof MySon> | null>(null)
onMounted(() => {
console.log(refCom.value)
refCom.value!.setNum(101)
})
</script>
8、可选链运算符
可选链运算符(?.
)允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。?.
运算符的功能类似于 .
链式运算符,不同之处在于,在引用为空 (nullish ) (null 或者 undefined) 的情况下不会引起错误,该表达式短路返回值是 undefined
。与函数调用一起使用时,如果给定的函数不存在,则返回 undefined
。
当尝试访问可能不存在的对象属性时,可选链运算符将会使表达式更短、更简明。在探索一个对象的内容时,如果不能确定哪些属性必定存在,可选链运算符也是很有帮助的。
const nestedProp = obj.first?.second
// 等价于
let temp = obj.first
let nestedProp = temp === null || temp === undefined ? undefined : temp.second
9、非空断言
如果我们明确的知道对象的属性一定不会为空,那么可以使用非空断言 !
。
// 告诉 TS, 明确的指定 obj 不可能为空
const nestedProp = obj!.second
// 表示 document.querySelector('div') 不可能为空
console.log(document.querySelector('div')!.innerHTML)