中直接使用
中直接使用<template>
{{ msg }}
<Home />
template>
<script setup>
// 直接引入一个组件
import Home from './Home/index.vue'
// 直接在模板中使用
const msg = "你好世界"
// 直接定义函数
const fn = () => {
console.log(msg)
}
script>
defineProps
代替props
,接收父组件传递的数据(父组件向子组件传参)
<template>
<div>父组件div>
<Child :title="msg" />
template>
<script setup>
import {ref} from 'vue'
import Child from './child.vue'
const msg = ref('父的值')
script>
<template>
<div>子组件div>
<div>父组件传递的值:{{ title }}div>
template>
<script setup>
//import {defineProps} from 'vue' // 不需要引入 defineProps
// 写法1 使用defineProps替代props
const props = defineProps({
title: {
type: String
}
})
// 写法2 withDefaults为props提供默认值 (推荐与TS使用)
const props = withDefaults(
defineProps<{
title: string
name: string
}>(),
{
title: '你好世界',
name: 'hello world'
}
)
//script-setup 需要通过props.xx获取父组件传递过来的props
console.log(props.title) //父的值
script>
defineEmit
代替emit
,子组件向父组件传递数据(子组件向外暴露数据)<template>
<div>子组件div>
<button @click="toEmits">子组件向外暴露数据button>
template>
<script setup>
import {ref} from 'vue'
const name = ref('我是子组件') // 携带的数据
//3 暴露内部自定义方法
const emits = defineEmits(['childFn']);
// 1 子组件中绑定一个事件 toEmits
const toEmits = () => {
//2 暴露给父组件的childFn方法并携带数据
emits('childFn', name)
}
script>
<template>
<div>父组件div>
<Child @childFn='childFn' />
<p>接收子组件传递的数据{{ childData }} p>
template>
<script setup>
import {ref} from 'vue'
import Child from './child.vue'
const childData = ref(null)
// 2 在父组件中定义一个方法,获取传递的参数
const childFn=(e)=>{
consloe.log('子组件触发了父组件childFn,并传递了参数e')
// 3 将子组件的数据赋值给父组件的变量
childData.value = e
}
script>
defineExpose
获取组件实例属性defineExpose
ref
绑定变量ref='childRef'
,使用变量childRef.value.xx
<script setup>
import { ref } from 'vue'
// 1 定义子组件需要暴露的属性
const a = 1
const b = ref(2)
// 2 子组件 主动暴露属性
defineExpose({
a,
b
})
script>
<template>
<div>父组件div>
<Child ref='childRef' />
<button @click='getChildData'>通过ref获取子组件的属性 button>
template>
<script setup>
import {ref} from 'vue'
import Child from './child.vue'
// 2 注册子组件的响应数据
const childRef= ref()
// 3 定义一个方法 接收打印子组件暴露的值
const getChildData =()=>{
console.log(childRef.value.a) // 1
console.log(childRef.value.b) // 2 响应式数据
}
script>
route
和router
setup
里不能访问this
,不能再直接访问 this.$router
或 this.$route
。getCurrentInstance
替代this
,但不推荐useRoute
和useRouter
替代this.$route
和 this.$router
<script setup>
import { useRouter, useRoute } from 'vue-router'
const route = useRoute()
const router = useRouter()
function pushWithQuery(query) {
router.push({
name: 'search',
query: {
...route.query,
},
})
}
<script/>
import router from './router'
router.beforeEach((to,from,next)=>{
// ....
})
组合式api
的导航守卫onBeforeRouteLeave
、onBeforeRouteUpdate
<script setup>
import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'
// 与 beforeRouteLeave 相同,无法访问 `this`
onBeforeRouteLeave((to, from) => {
const answer = window.confirm(
'Do you really want to leave? you have unsaved changes!'
)
// 取消导航并停留在同一页面上
if (!answer) return false
})
const userData = ref()
// 与 beforeRouteUpdate 相同,无法访问 `this`
onBeforeRouteUpdate(async (to, from) => {
//仅当 id 更改时才获取用户,例如仅 query 或 hash 值已更改
if (to.params.id !== from.params.id) {
userData.value = await fetchUser(to.params.id)
}
})
<script/>
script
标签MyComponent.vue
<script lang="ts">
export default { name: 'MyComponent' };
</script>
<script setup lang="ts">
// 组件内容
</script>
ref / reactive / computed
<script setup lang="ts">
import { computed, reactive, ref } from '@vue/runtime-core';
type User = { name: string; password: string };
// ref
const msg = ref(''); // 会默认约束成 string 类型
const msg2 = ref<string>(''); // 可以通过范型约束类型
const user = ref({} as User); // 自定义类型强制转化 通过 user.value. 访问
// reactive
const obj = reactive({});
const user2 = reactive<User>({name: '', password: ''});
const user3 = reactive({} as User); // 自定义类型强制转化
// computed
const str3 = computed(() => ''); // 会默认约束成 string 类型
const user5 = computed<User>(() => {
return { name: '', password: '' };
});
</script>
keepAlive
缓存// 1 在路由规则中,需要缓存的组件中新增 meta: { keepAlive: true }
const routes = [{
name: 'OrderList',
meta: {
title: '订单列表',
keepAlive: true, // 新增后,该组件会被缓存
}
}]
// 2 入口文件的路由出口修改如下
<router-view v-slot="{ Component }">
<keep-alive>
<component :is="Component" v-if="$route.meta.keepAlive" :key="$route.name" />
</keep-alive>
<component :is="Component" v-if="!$route.meta.keepAlive" :key="$route.name" />
</router-view>
【参考资料】
Vue3拒绝写return,用setup语法糖,让写Vue3更畅快
defineProps() 和 defineEmits()
针对 TypeScript 的功能
Vue3必学技巧-自定义Hooks-让写Vue3更畅快
搭配 TypeScript 使用 Vue
router-view的新写法