VUE(3)

一 组件通信

1 .props

(1)父传子

 <Person :ftoy="ftoy"/> //父组件代码
 defineProps(['ftoy'])  //子组件用这个函数接受

(2)子传父,父要通过函数传递给子,子在修改父的数据,函数接收数据变化后,父亲那里的数据也发生变化

function getsontoy(value:string){
  stoy.value=value
}             //父亲拿到的函数的value就是子传递过来的数据
<button @click="sendtoy(toy)">点击给父发送子玩具</button> 这个函数传递参数就可以发送子组建的数据了,在父的value里面

2 自定义事件

@后面接自定义的事件,子元素接受后想要使用,需要emit(‘事件名字’,可填传入的值,在定义事件的地方可以接收)

 <Person @send-toy="sendtoy"/> //名称自定,=后面跟的是函数,可以接收参数
const emit=defineEmits(['send-toy'])
 <button @click="emit('send-toy',toy)">点击给父发送子玩具</button>

3 mitt

第一步安装mitt 终端输入 npm i mitt

第二步 创建mitt 的ts 文件方便引用

import mitt from 'mitt'
const emitter = mitt()
export default emitter

第三 mitt使用首先要导入,发送事件

 <button @click="emitter.emit('send-toy',toy)">子传父的玩具用mitt形式:</button> //emitter.emit()相当于触发或者发射事件,同样可以传递value值

import emitter from '../utils/emitter';

第四 组件接收,同样先要导入,后绑定事件接受,这里需要注意是绑定完,需要在卸载的时候,把事件解绑,防止内存泄漏

emitter.on('send-toy',(value:any)=>{
    mstoy.value=value
})

onUnmounted(()=>{
  emitter.off('send-toy')
})   //解绑事件

4 $attrs通信

attrs是父组件传递的所有数据,传递的对象可以选择接收或者不接收,但是attrs会保留所有传递的数据。通过这个我们就可以实现,父传孙。传递的写法和之前相同,就在子组件里面写下


  <GrandChild v-bind="$attrs">

就可以传递给孙组件所有的数,当然使用的时候需要接受,如果父亲传递一个函数,可以接受数据,数据传递给孙组件,孙组件使用函数给值可以做到给父组件传递值,更新数据

defineProps(['ftoy','a','b','updata'])

5 $refs $parent 通信

$refs用于 父传子而 $parent用于子传父,他们都可以得到所有的父对象和子对象,通过这总形式通信传递,想要在父里面修改子组件数据,或者反过来都需要在被修改数据的组件里面暴露出数据用defineExpose()

<button @click="changeAllBook($refs)">修改子组件的书籍数量</button> //父亲通过refs拿到所有子组件对象

function changeAllBook(refs:any){ //遍历所有子组件对象,给子组件修改数据

console.log(refs)

for (let key in refs){

refs[key].book += 1

}

}

$parent写法也是同理的,但是只能用于,子对父

6 provide和inject

可以实现跨层级组件(祖孙)间通信,不用借助子组件。

provide('state', state) //父传递数据
const state = inject('state') //孙接收数据

7 默认插槽

使用默认插槽的要写成双标签,标签里面可以写样式,数据,数据使用的是父组件定义的数据,但是写完内容后,需要在子组件里面写<slot>(这里可以定义默认内容没传入东西就会显示)</slot>

  <Person @send-toy="sendtoy" title="游戏推荐">
    <ul>
      <li v-for="g in games" :key="g.id">
        {{ g.game }}
      </li>
    </ul>
    </Person>   //父组件写的内容
 <div class="cont">
    <h2>{{ title }}</h2>
    <slot>默认内容</slot>    //子组件写的内容,如果父组件没有写样式,就会默认呈现slot标签里面写的内容

8 具名插槽

可以设置不同的插槽,随意放置位置,但是需要起名字,用v-slot:来命名,可以用#来简写,子组件用name来表示是那个插槽

  <Person @send-toy="sendtoy" title="游戏推荐">
   <template #s2>
    <ul>
      <li v-for="g in games" :key="g.id">
        {{ g.game }}
      </li>
    </ul>
   </template>
   <template #s1>
    <h2>游戏推荐</h2>
   </template>
    </Person>         //父组件
 <div class="cont">
    <slot name="s1">默认内容1</slot>
    <slot name="s2">默认内容2</slot>
  </div>                   //子组件

9 作用域插槽

可以给指定的插槽传输数据,用的是v-slot:的形式,传过来的数据是一个对象的形式,使用作用域插槽也可以定义名字的

  <div class="cont">
    <slot name="s1">默认内容1</slot>
    <slot name="s2" :games="games">默认内容2</slot>
  </div>      //子组件传给父组件数据,games 
   <template v-slot:s2="{games}">
    <ul>
      <li v-for="g in games" :key="g.id">    //如果这里不解构的话,v-for 里面 写的是 g in games.games
        {{ g.game }}
      </li>
    </ul>
   </template>
   <template v-slot:s1>
    <h2>游戏推荐</h2>
   </template>

二 其他api

1 shallowRef

只能改变浅层次的值,一般用来看是否发生整体的数据修改。比如说

let person = shallowRef([

name:'张三

age:18

])

function changeSum (){fsum.value += 1}

function changeName (){(person.value.name =李四 } //这个地方就不能修改,他是 person.value.name 这里有层次超过一个就不可以

function changeAge (){person.value.age += 1}

function changePerson (){person.value = (name: 'tony ' , age:100]} //这里可以修改

2 shallowReative

它其实和shallowRef一样的,使用他们可以增强性能。

3 readonly

定义了readonly只能读取数据,不可以修改数据,可以对数据进行保护,比如说

let sum1=ref(0)

let sum2=readonly(sum1) 这里的sum2 只读取了sum1 的值,sum1的值变化,sum2 也变化,但是无法改变sum2的值

4 shallowReadly

它和readonly差不多,但是它只限制第一次层次的只读,比如说你修改它第二层次的数据是可以修改的,

5 toRaw

作用:用于获取一个响应式对象的原始对象,toRaw 返回的对象不再是响应式的,不会触发视图更新

官网描述:这是一个可以用于临时读取而不引起代理访问/跟踪开销,或是写入而不触发更改的特殊方法。不建议保存对原始对象的持久引用,请谨慎使用。

外部系统时何时使用?--在需要将响应式对象传递给非 Vue 的库可到的是普通对象使用 toRaw 可以确保它们收到的是普通对象

6 markRaf

标记永远不会变为响应式对象

7 customRef

自定义ref,get是数据被调用的时候执行这个函数,set是当数据被修改的时候执行这个函数

export default function (initValue: string, dalay: number) {
    let timer: any
    let msg = customRef((track, trigger) => {
        return {
            get() {
                track()  //告诉vue,你要对msg数据持续关注,一旦msg变化就要去更新
                return initValue
            },
            set(value) {
                clearTimeout(timer)
                timer = setTimeout(() => {
                    initValue = value
                    trigger()  //通知vue数据更新完毕了
                }, dalay)

            }
        }
    })
    return { msg }
}

8 Teleport

一种能够将我们组件html结构移动到指定位置的技术

<teleport to='body’ > // 这里的to就可以定义这个盒子传送,以那个盒子为基点,比如说这里写的body它定位是以body来定位,会脱离父盒子的限制

<div class="modal” V-show="isShow"><h2>我是一个弹窗</h2>

<p>我是弹窗中的一些内容</p>

<button @click="isShow = false">关闭弹窗</button>

</div>

</teleport>

9 Suspense

如果子组件是包含异步任务的,父组件要用Suspense去包裹一个template标签,定义插槽为默认插槽就可以获得子组件了

 import { Suspense } from 'vue';
<Suspense>
    <template v-slot:default>
    <Chlid/>
    </template>   //这个插槽异步任务完成才出现
    <template v-slot:fallback>
      正在加载中......
    </template>        //这个插槽异步任务没完成的时候出现
  </Suspense>    


VUE(3)
http://localhost:8090//archives/vue-3
作者
骆伟林
发布于
2024年11月11日
许可协议