- Vite工具和Vue都可以創(chuàng)建Vu3項(xiàng)目,Vite運(yùn)行編譯更快蹬挤,幾乎瞬間可以完成介陶。
- Vue3.0的.vue文件可以不用根標(biāo)簽包裹慨蓝。
ref數(shù)據(jù)響應(yīng)式和Ref對象
- ref響應(yīng)需要用到.value賦值膳叨,不可直接賦值
<script setup lang="ts">
import { ref,Ref } from "vue";
let msg: Ref<string> = ref('小松')
const changeMsg = () => {
msg.value = '小虎'
console.log(msg);
}
</script>
<template>
<button @click="changeMsg">change</button>
<div>{{ msg }}</div>
</template>
isRef用于判斷是否為Ref對象
<script setup lang="ts">
import { ref,Ref,isRef } from "vue";
let msg: Ref<string> = ref('小松')
let notRef: number = 1
const changeMsg = () => {
msg.value = '小虎'
console.log(isRef(msg)); //true
console.log(isRef(notRef)); //false
}
</script>
<template>
<button @click="changeMsg">change</button>
<div>{{ msg }}</div>
</template>
shallowRef包裝對象,節(jié)省性能茸俭,對應(yīng)對象的屬性
<script setup lang="ts">
import { shallowRef } from "vue";
let msg = shallowRef({
name: '小松'
})
const changeMsg = () => {
msg.value = {
name: '大松'
}
}
</script>
<template>
<button @click="changeMsg">change</button>
<div>{{ msg }}</div>
</template>
triggerRef強(qiáng)制更新dom
<script setup lang="ts">
import { shallowRef,triggerRef } from "vue";
let msg = shallowRef({
name: '小松'
})
const changeMsg = () => {
// msg.value = {
// name: '大松'
// }
msg.value.name = '大送'
triggerRef(msg)
}
</script>
自定義customRef
<script setup lang="ts">
import { customRef } from "vue";
function MyRef<T>(value:T) { //T是泛型
return customRef((trank,trigger) => {
return {
get () {
trank()
return value
},
set(newVal: T) {
console.log('SET');
value = newVal
trigger()
}
}
})
}
let msg = MyRef<string>('小曼')
const changeMsg = () => {
msg.value = '大滿'
}
</script>
<template>
<button @click="changeMsg">change</button>
<div>{{ msg }}</div>
</template>
shallowRef和triggerRef結(jié)合使用
<script setup lang="ts">
import { shallowRef,triggerRef } from "vue";
const msg = shallowRef({
foo:'小送',
bar:'小西'
})
const changeMsg = () => {
msg.value.foo = 'xiaoman'
console.log(msg);
}
</script>
<template>
<button @click="changeMsg">change</button>
<div>{{ msg }}</div>
</template>
想要讓視圖同步更新粘都,需要用到triggerRef強(qiáng)制更新數(shù)據(jù)
<script setup lang="ts">
import { shallowRef,triggerRef } from "vue";
const msg = shallowRef({
foo:'小送',
bar:'小西'
})
const changeMsg = () => {
msg.value.foo = 'xiaoman'
triggerRef(msg)
console.log(msg);
}
</script>
<template>
<button @click="changeMsg">change</button>
<div>{{ msg }}</div>
</template>
reactive響應(yīng)式對象
- 傳基礎(chǔ)數(shù)據(jù)類型會報(bào)錯不跟,字符串等,基礎(chǔ)數(shù)據(jù)類型使用ref
- 可傳復(fù)雜數(shù)據(jù)類型励堡,數(shù)組和對象等谷丸,復(fù)雜數(shù)據(jù)類型使用reactive
- reactive響應(yīng)對象時(shí)不需要用.value賦值,可直接賦值
<script setup lang="ts">
import { reactive } from "vue";
let msg = reactive([])
let obj = reactive({
name: '小西'
})
obj.name = '大西'
</script>
<template>
{{msg}}
{{obj}}
</template>
- 異步賦值數(shù)組(請求接口的時(shí)候)
<script setup lang="ts">
import { reactive } from "vue";
let msg = reactive<number[]>([])
setTimeout(() => {
let arr = [1,2,3,4]
// msg = arr 直接賦值不會響應(yīng)
msg.push(...arr) //解構(gòu)會響應(yīng)
},1000)
</script>
<template>
{{msg}}
</template>
另外一種數(shù)組賦值方式
<script setup lang="ts">
import { reactive } from "vue";
type O = {
list:number[]
}
let msg = reactive<O>({
list:[]
})
setTimeout(() => {
msg.list = [1,2,3,4]
},1000)
</script>
<template>
{{msg}}
</template>
readonly會將proxy對象進(jìn)行拷貝一份应结,設(shè)置只讀模式刨疼,不可以操作數(shù)據(jù)
<script setup lang="ts">
import { reactive,readonly } from "vue";
let person = reactive({
count:1
})
person.count++
let copy = readonly(person)
copy.count++
</script>
shallowReactive只對淺層數(shù)據(jù)發(fā)生響應(yīng),對于深層數(shù)據(jù)只會改變值鹅龄,但不會更新視圖
- 淺層揩慕,數(shù)據(jù)可響應(yīng),視圖同步更新
- 深層扮休,數(shù)據(jù)可響應(yīng)迎卤,但視圖不更新
<script setup lang="ts">
import { shallowReactive } from "vue";
let msg = shallowReactive({
test: '小滿', //淺層,數(shù)據(jù)可響應(yīng)玷坠,視圖同步更新
nav:{ //深層蜗搔,數(shù)據(jù)可響應(yīng),但視圖不更新
bar:{
name: '大滿'
}
}
})
const change1 = () => {
msg.test = '小西'
}
const change2 = () => {
msg.nav.bar.name = '大西'
}
</script>
<template>
{{msg}}
<button @click="change1">change1</button>
<button @click="change2">change2</button>
</template>
toRef是引用八堡,修改響應(yīng)式數(shù)據(jù)會影響以前的數(shù)據(jù),數(shù)據(jù)發(fā)生變化樟凄,界面就會自動更新.
ref、toRef兄渺、toRefs 都可以將某個(gè)對象中的屬性變成響應(yīng)式數(shù)據(jù)
ref的本質(zhì)是拷貝缝龄,修改響應(yīng)式數(shù)據(jù),不會影響到原始數(shù)據(jù)挂谍,視圖會更新
toRef叔壤、toRefs的本質(zhì)是引用,修改響應(yīng)式數(shù)據(jù)凳兵,會影響到原始數(shù)據(jù)百新,視圖不會更新
toRef 一次僅能設(shè)置一個(gè)數(shù)據(jù)企软,接收兩個(gè)參數(shù)庐扫,第一個(gè)參數(shù)是哪個(gè)對象,第二個(gè)參數(shù)是對象的哪個(gè)屬性
toRefs接收一個(gè)對象作為參數(shù),它會遍歷對象身上的所有屬性形庭,然后挨個(gè)調(diào)用toRef執(zhí)行
<script setup lang="ts">
import { reactive, toRef } from "vue";
const obj = reactive({
foo: 1,
bar: 1
})
const state = toRef(obj,'bar')
const change = () => {
state.value++
console.log('原始對象>>>',obj);
console.log('引用對象>>>',state);
}
</script>
<template>
<div>{{state}}</div>
<div><button @click="change">change</button></div>
</template>
toRefs接收一個(gè)對象铅辞,toRef 一次僅能設(shè)置一個(gè)數(shù)據(jù)
<script setup lang="ts">
import { reactive, toRefs } from "vue";
const obj = reactive({
foo: 1,
bar: 1
})
let { foo, bar } = toRefs(obj)
console.log(foo, bar);
const change = () => {
foo.value++
bar.value++
}
</script>
<template>
<div> >>>{{foo}}</div>
<div> >>>{{bar}}</div>
<div><button @click="change">change</button></div>
</template>
toRaw將響應(yīng)式代理對象變?yōu)槠胀▽ο?/h4>
<script setup lang="ts">
import { reactive, toRaw } from "vue";
const obj = reactive({
foo: 1,
bar: 1
})
const raw = toRaw(obj)
console.log('響應(yīng)式對象',obj);
console.log('普通對象',raw);
</script>
計(jì)算屬性 computed的使用
<script setup lang="ts">
import { computed, ref } from "vue";
let firstName = ref('')
let lastName = ref('')
</script>
<template>
<div>
<input v-model="firstName" type="text">
<input v-model="lastName" type="text">
<div>
{{ firstName }} - {{ lastName }}
</div>
</div>
</template>
另外一種書寫方式
<script setup lang="ts">
import { computed, ref } from "vue";
let firstName = ref('')
let lastName = ref('')
const name = computed(() => {
return firstName.value + '----' + lastName.value
})
</script>
<template>
<div>
<input v-model="firstName" type="text">
<input v-model="lastName" type="text">
<div>
{{ name }}
</div>
</div>
</template>
另外一種處理方式
<script setup lang="ts">
import { computed, ref } from "vue";
let firstName = ref('')
let lastName = ref('')
const name = computed({
get (){
return firstName.value + '----' + lastName.value
},
set(){
firstName.value + '----' + lastName.value
}
})
</script>
<template>
<div>
<input v-model="firstName" type="text">
<input v-model="lastName" type="text">
<div>
{{ name }}
</div>
</div>
</template>
購物車案例
<script setup lang="ts">
import { reactive,ref } from "vue"
type Shop = {
name: string,
num: number,
price: number
}
const data = reactive<Shop[]>([
{
name:'褲子',
num:1,
price:100
},
{
name:'上衣',
num:1,
price:200
},
{
name:'外套',
num:1,
price:300
}
])
let $total = ref(0)
const addAndSub = (item: Shop,type: boolean):void =>{
if(item.num > 1 && !type){
item.num--
total()
}
if(item.num < 99 && type){
item.num++
total()
}
}
const del = (index: number) => {
data.slice(index,1)
}
/*
reduce 計(jì)算總價(jià),
*/
const total = () => {
$total.value = data.reduce((prev, next) => {
return prev + (next.num * next.price)
},0)
}
total()
</script>
<template>
<div>
<table border width="800px">
<thead>
<tr>
<th>名稱</th>
<th>數(shù)量</th>
<th>單價(jià)</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr :key="index" v-for="(item, index) in data">
<td align="center">{{ item.name }}</td>
<td align="center">
<button @click="addAndSub(item,false)"> - </button>
{{ item.num }}
<button @click="addAndSub(item,true)"> + </button>
</td>
<td align="center">{{ item.price }}</td>
<td align="center">
<button @click="del(index)">刪除</button>
</td>
</tr>
</tbody>
<tfoot>
<td></td>
<td></td>
<td></td>
<td align="center">總價(jià): {{$total}}¥</td>
</tfoot>
</table>
</div>
</template>
用computed計(jì)算屬性
<script setup lang="ts">
import { computed, reactive,ref } from "vue"
type Shop = {
name: string,
num: number,
price: number
}
const data = reactive<Shop[]>([
{
name:'褲子',
num:1,
price:100
},
{
name:'上衣',
num:1,
price:200
},
{
name:'外套',
num:1,
price:300
}
])
let $total = ref(0)
const addAndSub = (item: Shop,type: boolean):void =>{
if(item.num > 1 && !type){
item.num--
}
if(item.num < 99 && type){
item.num++
}
}
const del = (index: number) => {
data.slice(index,1)
}
/*
reduce 計(jì)算總價(jià)萨醒,
*/
$total = computed<number>(() => {
return data.reduce((prev, next) => {
return prev + (next.num * next.price)
},0)
})
</script>
<template>
<div>
<table border width="800px">
<thead>
<tr>
<th>名稱</th>
<th>數(shù)量</th>
<th>單價(jià)</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr :key="index" v-for="(item, index) in data">
<td align="center">{{ item.name }}</td>
<td align="center">
<button @click="addAndSub(item,false)"> - </button>
{{ item.num }}
<button @click="addAndSub(item,true)"> + </button>
</td>
<td align="center">{{ item.price }}</td>
<td align="center">
<button @click="del(index)">刪除</button>
</td>
</tr>
</tbody>
<tfoot>
<td></td>
<td></td>
<td></td>
<td align="center">總價(jià): {{$total}}¥</td>
</tfoot>
</table>
</div>
</template>
watch偵聽器斟珊,可偵聽數(shù)據(jù)變化,以及偵聽多個(gè)數(shù)據(jù)源
<script setup lang="ts">
import { ref, watch } from 'vue'
let msg1 = ref<string>('')
let msg2 = ref<string>('')
/*
watch:偵聽數(shù)據(jù)變化
參數(shù)1:偵聽數(shù)據(jù)源
參數(shù)2:回調(diào)callback簡稱cb
cb回調(diào):
參數(shù)1:新值
參數(shù)2:舊值
*/
watch([msg1,msg2],(newVal, oldVal) => {
console.log('新值',newVal);
console.log('舊值',oldVal);
})
</script>
<template>
<input type="text" v-model="msg1">
<input type="text" v-model="msg2">
</template>
如果需要監(jiān)聽深層對象富纸,則需要開啟第三個(gè)參數(shù) deep:true
<script setup lang="ts">
import { ref, watch } from 'vue'
let msg = ref({
nav:{
bar:{
name:"東南"
}
}
})
watch(msg,(newVal, oldVal) => {
console.log('新值',newVal);
console.log('舊值',oldVal);
},{deep:true})
</script>
<template>
<input type="text" v-model="msg.nav.bar.name">
</template>
bug:監(jiān)聽到的新值和舊值一樣
頁面刷新囤踩,偵聽默認(rèn)不會執(zhí)行,只有當(dāng)變化的時(shí)候才會去偵聽
但我們可以讓頁面刷新的時(shí)候立馬去監(jiān)聽晓褪,配置immediate:true屬性堵漱,立即觸發(fā)偵聽器
<script setup lang="ts">
import { ref, watch } from 'vue'
let msg = ref({
nav:{
bar:{
name:"東南"
}
}
})
watch(msg,(newVal, oldVal) => {
console.log('新值',newVal);
console.log('舊值',oldVal);
},{
deep:true,
immediate:true
})
</script>
- 對于reacative對象使用偵聽器涣仿,深層對象可以不用配置 deep:true, immediate:true
<script setup lang="ts">
import { reactive, ref, watch } from 'vue'
let msg = reactive({
nav:{
bar:{
name:"東南"
}
}
})
watch(msg,(newVal, oldVal) => {
console.log('新值',newVal);
console.log('舊值',oldVal);
})
</script>
<template>
<input type="text" v-model="msg.nav.bar.name">
</template>
監(jiān)聽reactive對象的多個(gè)屬性
<script setup lang="ts">
import { reactive, ref, watch } from 'vue'
let msg = reactive({
name:"東南",
name2:"南北"
})
watch(msg,(newVal, oldVal) => {
console.log('新值',newVal);
console.log('舊值',oldVal);
})
</script>
<template>
<input type="text" v-model="msg.name">
<input type="text" v-model="msg.name2">
</template>
單一監(jiān)聽reactive對象的某個(gè)屬性勤庐,采用函數(shù)返回的形式
<script setup lang="ts">
import { reactive, ref, watch } from 'vue'
let msg = reactive({
name:"東南",
name2:"南北"
})
watch(() => msg.name,(newVal, oldVal) => {
console.log('新值',newVal);
console.log('舊值',oldVal);
})
</script>
<template>
<input type="text" v-model="msg.name">
<input type="text" v-model="msg.name2">
</template>
認(rèn)識watchEffect高級監(jiān)聽器
watch是只有數(shù)據(jù)發(fā)生改變的時(shí)候才去監(jiān)聽,而且需要立即觸發(fā)監(jiān)聽的話好港,需要額外配置immediate愉镰,watchEffect則不需要配置immediate則可實(shí)現(xiàn)立即監(jiān)聽的效果。
對于watch監(jiān)聽多個(gè)屬性時(shí)钧汹,則需要作為參數(shù)傳進(jìn)去丈探,watchEffect是高效的,不需要傳參拔莱。
<script setup lang="ts">
import { watchEffect, ref } from 'vue'
let msg1 = ref<string>('桌子')
let msg2 = ref<string>('板凳')
watchEffect(() => {
console.log('msg1=====>',msg1.value);
console.log('msg2=====>',msg2.value);
})
</script>
<template>
<input type="text" v-model="msg1">
<input type="text" v-model="msg2">
</template>
- watchEffect可接收一個(gè)callback作為回調(diào)类嗤,它可以在偵聽之前操作一些東西(比如在偵聽之前做一些防抖和節(jié)流的操作)
<script setup lang="ts">
import { watchEffect, ref } from 'vue'
let msg1 = ref<string>('桌子')
let msg2 = ref<string>('板凳')
watchEffect((oninvalidate) => {
console.log('msg1=====>',msg1.value);
console.log('msg2=====>',msg2.value);
oninvalidate(() => {
console.log('before');
})
})
</script>
<template>
<input type="text" v-model="msg1">
<input type="text" v-model="msg2">
</template>
- 停止監(jiān)聽,watchEffect可實(shí)現(xiàn)停止監(jiān)聽辨宠,當(dāng)停止監(jiān)聽后遗锣,數(shù)據(jù)發(fā)生改變,將不會對其進(jìn)行監(jiān)聽
<script setup lang="ts">
import { watchEffect, ref } from 'vue'
let msg1 = ref<string>('桌子')
let msg2 = ref<string>('板凳')
const stop = watchEffect((oninvalidate) => {
console.log('msg1=====>',msg1.value);
console.log('msg2=====>',msg2.value);
oninvalidate(() => {
console.log('before');
})
})
const stopWatchEffect = () => stop()
</script>
<template>
<input type="text" v-model="msg1">
<input type="text" v-model="msg2">
<button @click="stopWatchEffect">停止監(jiān)聽</button>
</template>
組件使用
對比vue2組件的使用,在vue3中,組件的使用省略了在options中配置components該選項(xiàng)
<script setup lang="ts">
import HelloWorld from './components/HelloWorld.vue'
</script>
<template>
<HelloWorld></HelloWorld>
</template>
組件的生命周期
- setup最新被執(zhí)行
- onBeforeMount 在該生命周期內(nèi)嗤形,不能獲取dom相關(guān)操作
- onMounted 在該生命周期內(nèi)精偿,組件已經(jīng)創(chuàng)建完成,可進(jìn)行獲取dom操作
- onBeforeUpdate 和 onUpdated 數(shù)據(jù)更新前后使用
- onBeforeUnmount 和 onUnmounted 是組件卸載前后調(diào)用
Com.vue子組件
<script setup lang="ts">
import { ref,onBeforeMount,onMounted,onBeforeUpdate,onUpdated,onBeforeUnmount,onUnmounted } from 'vue';
const count = ref(0)
console.log('setup');
onBeforeMount(() => { //獲取不到dom
let div = document.querySelector('#msg')
console.log('創(chuàng)建之前===> onBeforeMount',div);
})
onMounted(() => { //可進(jìn)行dom獲取
let div = document.querySelector('#msg')
console.log('創(chuàng)建完成===> onBeforeMount',div);
})
onBeforeUpdate(() => { //數(shù)據(jù)更新之前
let div = document.querySelector('#msg')
console.log('數(shù)據(jù)更新之前===> onBeforeUpdate');
})
onUpdated(() => { //數(shù)據(jù)更新完成
console.log('數(shù)據(jù)更新完成===> onUpdated');
})
onBeforeUnmount(() => { //組件卸載之前
console.log('組件卸載之前===> onBeforeUnmount');
})
onUnmounted(() => { //數(shù)據(jù)更新完成
console.log('組件卸載完成===> onUnmounted');
})
</script>
<template>
<div id="msg">Hello!</div>
<div>{{count}}</div>
<button @click="count++">改變count</button>
</template>
app.vue根組件
<script setup lang="ts">
import { ref } from 'vue';
import Com from './components/Com.vue'
let flag = ref(true)
</script>
<template>
<Com v-if="flag"></Com>
<button @click="flag = !flag">改變組件的狀態(tài)</button>
</template>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
scoped組件間的樣式隔離
-
實(shí)現(xiàn)Layout布局的拼裝
-
目錄層次規(guī)范
App.vue
<script setup lang="ts">
import Layout from './views/Layout/index.vue'
</script>
<template>
<Layout></Layout>
</template>
<style lang="less">
html,body,#app {
height: 100%;
overflow: hidden;
}
*{
margin:0;
padding: 0;
}
</style>
/views/Layout/index.vue
<script setup lang="ts">
import Menu from '../Layout/Menu/index.vue'
import Header from '../Layout/Header/index.vue'
import Content from '../Layout/Content/index.vue'
</script>
<template>
<div id="layout">
<Menu></Menu>
<div id="layout-right">
<Header></Header>
<Content></Content>
</div>
</div>
</template>
<style lang="less" scoped>
#layout{
display: flex;
height: 100%;
overflow: hidden;
&-right{
flex: 1;
display: flex;
flex-direction: column;
}
}
</style>
/views/Layout/Content/index.vue
<script setup lang="ts">
</script>
<template>
<div id="content">
<div id="content-item" :key="item" v-for="item in 100">
{{item}}
</div>
</div>
</template>
<style lang="less" scoped>
#content{
flex: 1;
margin: 20px;
border: 1px solid #ccc;
overflow: auto;
&-item{
padding:20px;
border:1px solid #ccc;
}
}
</style>
/views/Layout/Menu/index.vue
<script setup lang="ts">
</script>
<template>
<div id="menu">菜單區(qū)域</div>
</template>
<style lang="less" scoped>
#menu{
width:200px;
border-right: 1px solid #ccc;
}
</style>
<script setup lang="ts">
</script>
<template>
<div id="menu">菜單區(qū)域</div>
</template>
<style lang="less" scoped>
#menu{
width:200px;
border-right: 1px solid #ccc;
}
</style>
/views/Layout/Header/index.vue
<script setup lang="ts">
</script>
<template>
<div id="header">頭部區(qū)域</div>
</template>
<style lang="less" scoped>
#header{
height: 60px;
border-bottom: 1px solid #ccc;
}
</style>
頁面展示
父子組件傳參
子接用defineProps 赋兵,子發(fā)用defineEmits
子組件直接使用defineProps()接收笔咽,不需引入,前提是搭配setup和TS語法糖使用
<script setup lang="ts">
</script>
父組件傳字符串霹期,非復(fù)雜數(shù)據(jù)類型不需要v-bind指令進(jìn)行綁定
子組件接收
父組件傳數(shù)組(復(fù)雜數(shù)據(jù)類型)
<script setup lang="ts">
import Menu from '../Layout/Menu/index.vue'
import Header from '../Layout/Header/index.vue'
import Content from '../Layout/Content/index.vue'
import { reactive } from 'vue';
const list = reactive<number[]>([1,2,3])
</script>
<template>
<div id="layout">
<Menu :data="list" title="春日宴"></Menu>
<div id="layout-right">
<Header></Header>
<Content></Content>
</div>
</div>
</template>
子組件接收
<script setup lang="ts">
type Props = {
title:string,
data:number[]
}
defineProps<Props>();
</script>
<template>
<div id="menu">
菜單區(qū)域
<div>{{title}}</div>
<div>{{data}}</div>
</div>
</template>
效果:
子組件給父組件傳值:defineEmits
子組件派發(fā)
<script setup lang="ts">
import { reactive } from "vue";
type Props = {
title:string,
data:number[]
}
defineProps<Props>();
//子組件派發(fā)
const numList = reactive<number[]>([6,7,8])
const emit = defineEmits(['on-click'])
const Tap = () => {
emit('on-click',numList)
}
</script>
<template>
<div id="menu">
菜單區(qū)域
<div>{{title}}</div>
<div>{{data}}</div>
<div><button @click="Tap">發(fā)送</button></div>
</div>
</template>
父組件
<script setup lang="ts">
import Menu from '../Layout/Menu/index.vue'
import Header from '../Layout/Header/index.vue'
import Content from '../Layout/Content/index.vue'
import { reactive } from 'vue';
const list = reactive<number[]>([1,2,3])
//父子接收
const getList = (numList:number[]) => {
console.log(numList,'來自子組件的numList');
}
</script>
<template>
<div id="layout">
<Menu @on-click="getList" :data="list" title="春日宴"></Menu>
<div id="layout-right">
<Header></Header>
<Content></Content>
</div>
</div>
</template>
子組件派發(fā)的時(shí)候可以攜帶多個(gè)值給父組件
父組件接收
子組件定義多個(gè)派發(fā)事件
父子組件獲取實(shí)例叶组,子組件需要defineExpose暴露給父組件
在vue3中父組件通過ref獲取子組件的實(shí)例是無法獲取的
子組件必須同通過defineExpose暴露給父組件
父子組件通訊,子組件設(shè)置默認(rèn)值 withDefaults
父組件
子組件設(shè)置默認(rèn)值
<script setup lang="ts">
type Props = {
title?:string,
data?:number[]
}
withDefaults(defineProps<Props>(),{
title: '標(biāo)題', //父組件傳過來就用父組件的值历造,沒有傳過來就用默認(rèn)值
data:() => [1,2,3]
})
</script>
<template>
<div id="menu">
菜單區(qū)域
<div>{{title}}</div>
<div>{{data}}</div>
</div>
</template>