Vite+TS+Vue3.0 筆記一

  • 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>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末甩十,一起剝皮案震驚了整個(gè)濱河市船庇,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌侣监,老刑警劉巖鸭轮,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異橄霉,居然都是意外死亡窃爷,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進(jìn)店門姓蜂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來按厘,“玉大人,你說我怎么就攤上這事钱慢】贪” “怎么了?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵滩字,是天一觀的道長造虏。 經(jīng)常有香客問我,道長麦箍,這世上最難降的妖魔是什么漓藕? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮挟裂,結(jié)果婚禮上享钞,老公的妹妹穿的比我還像新娘。我一直安慰自己诀蓉,他們只是感情好栗竖,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著渠啤,像睡著了一般狐肢。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上沥曹,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天份名,我揣著相機(jī)與錄音,去河邊找鬼妓美。 笑死僵腺,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的壶栋。 我是一名探鬼主播辰如,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼贵试!你這毒婦竟也來了琉兜?” 一聲冷哼從身側(cè)響起凯正,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎呕童,沒想到半個(gè)月后漆际,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體淆珊,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡夺饲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了施符。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片往声。...
    茶點(diǎn)故事閱讀 40,144評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖戳吝,靈堂內(nèi)的尸體忽然破棺而出浩销,到底是詐尸還是另有隱情,我是刑警寧澤听哭,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布慢洋,位于F島的核電站,受9級特大地震影響陆盘,放射性物質(zhì)發(fā)生泄漏普筹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一隘马、第九天 我趴在偏房一處隱蔽的房頂上張望太防。 院中可真熱鬧,春花似錦酸员、人聲如沸蜒车。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽酿愧。三九已至,卻和暖如春邀泉,著一層夾襖步出監(jiān)牢的瞬間寓娩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工呼渣, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留棘伴,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓屁置,卻偏偏與公主長得像焊夸,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子蓝角,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評論 2 355

推薦閱讀更多精彩內(nèi)容