vue3 的8种通信 方式

时间:2022-12-26 21:55:40

目录

1.defineProps  defineEmits  defineExpose/ref

ts写法

defineEmit

defineExpose

2.v-model   组件标签可同时写多个v-model 不再支持  .sync

3.provide inject

4.attrs  会包含父组件的props 属性的集合  一旦用props接收,attrs

就接收不到了

5.插槽


基于vue 3.2

1.defineProps  defineEmits  defineExpose/ref

<template>
  <div>
    <button @click="changeSonValue">changeNum</button>
    <h1>{{ n }}</h1>
    <h1 v-for="(item, index) in obj">{{ item }}</h1>
  </div>
</template>
<script setup>
import { ref, watch } from "vue";
// let props = defineProps(["num", "obj","changeNum"]);  //简单
let props = defineProps({num:{type:Number},obj:{type:Object}}) //限制类型
let n = ref(props.num);  //props 获取所有props的对象
// console.log(n);
const changeSonValue = () => {
  n.value++;
};

   let changeNumFromFather = ()=>{
      props.changeNum()
  }


watch(n,(n,o)=>{  
   console.log(n);
},{immediate:true,deep:true});

watch(props.obj,(n,o)=>{
   console.log(n);
},{deep:true,immediate:true})

watch([n,props.obj],()=>{}) //多个监视用数组

</script>
<style scoped></style>

defineEmits

//father
<!--
 * new page
 * @author: keepCoding-gyk
 * @since: 2022-12-04
 * father.vue
-->
<template>
  <div>
    <h1>
        {{num}}
        <son  @changeNum="getNum"></son>
    </h1>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import son from './son.vue'
   let num = ref(666);
  
   let getNum = (v)=>{
       num.value+=v
   }
  
</script>

<style lang="scss" scoped>
</style>

//son
<!--
 * new page
 * @author: keepCoding-gyk
 * @since: 2022-12-04
 * son.vue
-->
<template>
  <div>
    <button @click="changeNumFromFather">changeNumFromFather</button>
  </div>
</template>

<script setup>
    let emits = defineEmits(['changeNum']);
    let  changeNumFromFather =()=>{
        emits('changeNum',1)
    }
</script>

<style lang="scss" scoped></style>

defineExpose  父组件需要借助ref

<!--
 * new page
 * @author: keepCoding-gyk
 * @since: 2022-12-04
 * father.vue
-->
<template>
  <div >
    <son ref="son1"></son>
    <button @click="test">test</button>
  </div>
</template>

<script setup >
import son from './son.vue';
import { ref } from 'vue';
const son1 = ref(null)
console.log(son1);
let test = ()=>{
     console.log(son1.value.num);
     son1.value.changeNum()
}
</script>

<style lang="scss" scoped>
</style>

<!--
 * new page
 * @author: keepCoding-gyk
 * @since: 2022-12-04
 * son.vue
-->
<template>
  <div>
   <h1>{{num}}</h1>
  </div>
</template>

<script setup>
import { ref } from 'vue';

let num = ref(666);

let changeNum = ()=>{
   num.value ++
}
 defineExpose ({num,changeNum});
   
</script>

<style lang="scss" scoped>
</style>

ts写法

defineProps 三种写法

 let props= defineProps(['str'])
 console.log(props);

  let props = defineProps({
    str:String,
    arr:{
        type:Object,
        default:()=>[1,2]
    }
  })

let props = defineProps<{
    str:string,
    arr:number[]
}>()


withDefaults(defineProps<{  //设置默认值
    str:string,
    arr:number[]
}>(),{
    arr:()=>[666]
})

defineEmit

let emit = defineEmits(['ca'])

let emit = defineEmits<{  // 可以对每一个参数进行限制
    (e:'ca',a:string,b:number,c:string):void
}>()

let changeArr = ()=>{
  emit('ca','999',88,'jjj')
}

defineExpose

defineExpose<{n:string,s:Function}>({
    n:'999',
    s:()=>console.log('999'),
})

let wf = ref<InstanceType<typeof sVue>>();
onMounted(()=>{
    wf.value?.s();
    console.log(wf.value?.n);
})

2.v-model   组件标签可同时写多个v-model 不再支持  .sync

<!--
 * new page
 * @author: keepCoding-gyk
 * @since: 2022-12-04
 * father.vue
-->
<template>
  <div >
    <h1>father {{num1}}</h1>
    <sonVue v-model:value1="num1" v-model:value2="num2" ></sonVue>
  </div>
</template>

<script setup >
import { ref } from 'vue';
import sonVue from './son.vue';
let num1 = ref(666);
let num2 = ref(888)
</script>

<style lang="scss" scoped>
</style>

<!--
 * new page
 * @author: keepCoding-gyk
 * @since: 2022-12-04
 * son.vue
-->
    
<template>
  <div>
    <input type="text"  v-model="num"  @change="changeFatherValue1">
    <button @click="changeFatherValue1">46546546</button>
  </div>
</template>

<script setup>
import { ref } from 'vue';

 
   let props = defineProps({value1:{},value2:{}})   //{value:{}}
   let emits = defineEmits(['value1'])
   let num = ref(props.value1)
   let changeFatherValue1 = ()=>{
      emits('update:value1',num.value)
   }
</script>

<style lang="scss" scoped>
</style>

3.provide inject

<!--
 * new page
 * @author: keepCoding-gyk
 * @since: 2022-12-05
 * grand.vue
-->
<template>
  <div >
    <h1>grand</h1>
    <father></father>
  </div>
</template>

<script setup >
import { getCurrentInstance, provide, ref } from 'vue';
import father from './father.vue'
let num = ref(10);
provide('num',num.value);
provide('test',99999999)

</script>

<style lang="scss" scoped>
</style>

<!--
 * new page
 * @author: keepCoding-gyk
 * @since: 2022-12-05
 * father.vue
-->
<template>
  <div >
    <son></son>
  </div>
</template>

<script setup >
import son from './son.vue'

</script>

<style lang="scss" scoped>
</style>

<!--
 * new page
 * @author: keepCoding-gyk
 * @since: 2022-12-05
 * son.vue
-->
<template>
  <div >
  </div>
</template>

<script setup >
import { inject } from 'vue';
let num = inject('num');
console.log(num);
let test = inject('test');
console.log(test);

 
</script>

<style lang="scss" scoped>
</style>

4.attrs  会包含父组件的props 属性的集合  一旦用props接收,attrs

就接收不到了

<!--
 * new page
 * @author: keepCoding-gyk
 * @since: 2022-12-05
 * father.vue
-->
<template>
  <div >
    <son :m1="m1" :m2="m2"></son>
  </div>
</template>

<script setup >
import { ref } from 'vue';
import son from './son.vue'


let m1 = ref(10);
let m2 = ref(100);

</script>

<style lang="scss" scoped>
</style>


<!--
 * new page
 * @author: keepCoding-gyk
 * @since: 2022-12-05
 * son.vue
-->
<template>
  <div >
  </div>
</template>

<script setup >
 import { useAttrs } from 'vue'; 
 let props = defineProps(['m1']);
 let attrs = useAttrs();
 console.log(attrs); 
</script>

<style lang="scss" scoped>
</style>


5.插槽

vue2
匿名插槽 <slot/>
具名 <slot name="xxx"/> 模版标签 v-slot:xxx 或 #xxx
作用域 <slot :name="xxx"/>  模版  slot-scope="{name}"
vue3  匿名 具名不变
作用域

<slot :name="xxx"/>  模版  v-slot="{name}" 或者  #default="{name}" 或者

 v-slot:default="slotProps"

动态插槽  

 <template #[dyniamic]>
    <h1>{{ dyniamic }}</h1>
 </template>

import { ref } from 'vue';
let dyniamic = ref('dyniamic')
let dyniamicChange = ()=>{
  dyniamic.value = 'test'
}

<slot name="dyniamic"></slot>
<slot name="test"></slot>

具名插槽也可以 当作用域 用

<template v-slot:app="scope">
  {{ scope }}
</template>

 <slot name="app" :msg="arr"></slot>