vue3小野森森-01-关于setup,reactive,ref,unref,toRef,toRefs,isRef,customRef,shallowRef,triggerRef,computed

1、关于setup的一些概念
  • vue3里面自定义事件依然需要先定义后使用
  • vue3不再使用this.emit来发射自定义事件,而是使用context.semit来发射自定义事件,this已经是昨日黄花
  • 和vue2一样,emit里面有两个参数,一个是自定义事件名,一个是要发射过去的数据,数据可以是多个或者是数组
  • 在setup里面定义的变量和函数一定要通过return返回出去
  • vue3把钩子都作为函数放在‘vue’里需要从‘vue’中解构出来
  • 在setup里面使用的变量要用ref或者reactive包裹一下,ref包裹基本数据类型,reactive包裹对象数据类型。包裹后就称为响应式的对象。
  • 被包裹的基本数据类型是只读(readonly)的,不能直接修改要通过数据.value的形式进行修改
  • 函数的使用通过赋值的形式使用
  • 以上均在下例中进行了注释

子组件Test.vue

<template>
  <h3>here is test component</h3>
  <h1>{{count}}</h1>
  <button @click="emitAddEvent">add</button>
</template>

<script>
  import {watchEffect,watch,toRefs} from 'vue'
  export default {
    name: 'Test',
    props: {
      count:Number
    },
    //自定义事件注册在setup外面
    emits:['add'],
    //连个参数,一个props,一个context
    setup(props,context){
      //3和2在定义函数是不一样的,通过回调函数,将自定义事件发射出去
      const emitAddEvent=()=>{
        //发射事件不再使用thies.emit,而是用context,this在3里面不用了,
        //emit函数和2里面一致,先注册后使用
        context.emit('add',100)

      }

      return {
        //用到那个变量或者函数一定要return出去
        emitAddEvent
      }
    }
  }
</script>

<style scoped>

</style>

父组件app.vue

<template>
  <div>
    <!--这里add是自定事件,addcount是自定义事件的回调函数    -->
    <Test :count="mycount" @add="addcount"></Test>
  </div>
</template>

<script>
import Test from './components/Test.vue'
//从vue中解构导出所需要的函数,包括钩子都是以函数的形式解构出来使用
import {reactive,ref,toRefs} from 'vue'

export default {
  name: 'App',
  setup(props,context){
    //使用到的变量要ref包裹一下
    const mycount=ref(1000)
    //发射过来的emit事件是带参的,回调函数要用个形参来接收一下
    const addcount=(plusdata)=>{
      //被ref包裹的数据,由于响应式的问题,是只读的(readonly)不能修改,需要拆一下把value拆出来修改
      mycount.value+=plusdata
    }

    return {
      //变脸及回调函数都要return出去
      mycount,
      addcount
    }
  },

  components: {
    Test
  }
}
</script>

<style>

</style>

2、reatvie
  • 对应用类型数据进行包裹,使其称为响应式的数据,vue不建议使用原对象(应用类型数据),而直接使用包裹后的数据,因为包裹后就称为响应式数据。如果强行拆开,使用原对象,则丧失了响应式。
  • reactive事项了原对象的拷贝,但他是深拷贝
<template>
  <div>
  spp

  </div>
</template>

<script>

import {reactive,ref,toRefs} from 'vue'

export default {
  name: 'App',
  setup(props,context){
    const proxyObj=reactive({
      a:1,
      b:2,
      c:[
        {d:3,e:4},{f:3,g:5}

      ]
    })

    console.log(proxyObj)
    return {

    }
  },

  components: {
  }
}
</script>

<style>

</style>

  • reactive的对象可以直接修改对象
  • //使用reactive包裹的对象会自动展开,state.myref等效于state.value.myref
    console.log(state.myref)
  • //也可以直接修改数据,因为实际是自动展开了
    state.myref=200
    console.log(state.myref)
3、ref
  • 包裹基本数据类型,返回响应式的ref对象
  • 修改的话需要使用数据.value来使用
  • 如果包裹一个应用类型,但实际返回的是reactive类型,并支持deep拷贝
  • return出去的被ref包裹的数据,会合并到render函数(h函数)里去。并自动的将里面的value展开,如{{count}},而不用{{count.value}}
  • 如果一个ref包裹了一个已经ref包裹的数据,新的ref会覆盖老的ref的值
<template>
  <div>
  spp

  </div>
</template>

<script>

import {reactive,ref,toRefs} from 'vue'

export default {
  name: 'App',
  setup(props,context){
    const myref=ref(100)
    const proxyObj=ref({
      a:1,
      b:2,
    })
    console.log(myref.value)
    console.log(proxyObj.value.a)

    const state=reactive({ myref })
    //使用reactive包裹的对象会自动展开,state.myref等效于state.value.myref
    console.log(state.myref)
    //也可以直接修改数据
    state.myref=200
    console.log(state.myref)
    return {
      myref,
      state
    }
  },

  components: {
  }
}
</script>

<style>

</style>

4、ref/unref
  • ref是深度响应的。深度以为这嵌套的对象,深度响应表示嵌套的对象按照路径找下去是可以修改的
<template>
  <div>
    <h1>{{name}}</h1>
    <h1>{{person.homeland.city}}</h1>

  </div>
</template>

<script>

import {reactive,ref,toRefs} from 'vue'

export default {
  name: 'App',
  setup(props,context){
    const name=ref('')
    name.value='zhangsan'
    setTimeout(()=>{
      name.value='lisi'
      console.log(name.value)
    },2000)

    const person=ref({
      name:'wanger',
      age:12,
      homeland:{
        province:'hebei',
        city:'shijiazhuang'
      }
    })

    setTimeout(()=>{
      //非深度响应
      person.value.name='mazouri'
      //深度响应
      person.value.homeland.city='baoding'
    },3000)

    console.log(person.value.name)
    console.log(person.value.homeland.city)
    return {
      name,
      person,

    }
  },

  components: {
  }
}
</script>

<style>

</style>

  • unref如果参数数据是ref包裹,就返回inner value,如果不是ref包裹的数据,就返回数据本身
  • isRef函数判断
<template>
  <div>


  </div>
</template>

<script>

import {reactive,ref,toRefs,isRef,unref} from 'vue'

export default {
  name: 'App',
  setup(props,context){
    const myobj={
      name:'zhangsan',
      age:22,
      address:'heibei'
    }

    const obj1=isRef(myobj) ? myobj.name : myobj
    console.log(obj1)

    const obj2=ref(myobj)
    const obj3=isRef(obj2) ? myobj.name : myobj
    console.log(obj3)
    //unref实际就等于上面的obj3
    const obj4=unref(obj2)
    console.log(obj4)
    const obj5=unref(myobj)
    console.log(obj5)
    return {
      myobj

    }
  },

  components: {
  }
}
</script>

<style>

</style>

5、toRef/toRefs/isRef

1、toRef:建立reactive和ref的一种转换

可以把对象中的某个属性单独拿出来转成ref

<template>
  <div>
    {{myref}}
  </div>
</template>

<script>

import {reactive,ref,toRef,isRef,unref} from 'vue'

export default {
  name: 'App',
  setup(props,context){
    const state=reactive({
      name:'zhangsan',
      age:23
    })

    //指定转换的属性,这里将state的reactive包装对象的name属性传给myref
    const myref=toRef(state,'name')
    //修改转换后的值
    myref.value='lisi'
    console.log('11111',state.name)
    //修改state.name和修改myref.value都会影响到对方
    state.name='wanger'
    console.log('22222',myref.value)

    return {
      myref,
    }
  },

  components: {
  }
}
</script>

<style>

</style>

2、toRefs:建立reactive包装对象和ref的一种转换

  • 将一个reactive包装好的对象,整个转换成一个ref包装成的对象
  • 这样对象的所有属性都转换过去,而不是像toRef那样值转换其中的一个属性,因此,只需要一个转换对象形参就可以
<template>
  <div>
    urname:{{name}}<br/>
    urage:{{age}}
  </div>
</template>

<script>

import {reactive,ref,toRef,toRefs,isRef,unref} from 'vue'

export default {
  name: 'App',
  setup(props,context){
    const state=reactive({
      name:'zhangsan',
      age:23
    })

    //指定转换的属性,这里将state的reactive包装对象的name属性传给myref
    //这里转成了一个普通对象
    const myrefs=toRefs(state)
    console.log(myrefs)
    console.log({
      ...myrefs
    })
    console.log('11111',myrefs.name.value)//zhangsan
    console.log('11111',myrefs.age.value)//23
    //修改转换后的值
    myrefs.name.value='lisi'
    myrefs.age.value=33
    //修改转换后的值会影响到原则,因为实际本质上还是引用的
    console.log(state.name)//lisi
    console.log(state.age)//33
    //修改state.name和修改myref.value都会影响到对方
    state.name='wanger'
    state.age=44
    console.log('22222',myrefs.name.value)
    console.log('22222',myrefs.age.value)
    return {
      //直接展开转化后的myrefs,这样在template里面可以直接拿到展开后的name和age
      ...myrefs,
      state
    }
  },

  components: {
  }
}
</script>

<style>

</style>

3、isRef判断是否为ref
参看前几例

6、cutomRef自定义ref

用于数据防抖
customRef需要有一个工厂函数做参数,track(追踪),trigger(触发),分别对应getter和setter

<template>
  <div>
    <span>{{text}}</span>
    <input type="text" v-model="text">
  </div>
</template>

<script>

import {reactive,customRef} from 'vue'

function useDebounce(value,delay=200){
  let time=null
  return customRef((track,trigger)=>{
    return {
      get(){
        //跟踪旧值,返回旧值前要跟踪旧值,防止其发生变化
        track()
        return value
      },
      set(newvalue){
        clearTimeout(time)
        time=setTimeout(()=>{
          value=newvalue
          //更新数值和要去触发trigger
          trigger()
        },delay)
      }
    }
  })
}

export default {
  name: 'App',
  setup(props,context){
    const text=useDebounce('',500)
    return {
      text
    }
  },

  components: {
  }
}
</script>

<style>

</style>

7、shallowRef

浅ref,由于使用ref包装之后,数据就具有了响应式,如果使用shallowRef包装,转化后成为一个proxy对象(普通对象)

<template>
  <div>
    <span>{{myobj1}}</span>
    <hr/>
    <span>{{myobj2}}</span>
  </div>
</template>

<script>

import {ref,reactive,customRef,shallowRef} from 'vue'

export default {
  name: 'App',
  setup () {
    const myobj1=ref({
      name:'zhangsan',
      age:12
    })
    console.log(myobj1)//RefImpl
    myobj1.value={
      name:'lisi',
      age:33
    }
    console.log(myobj1.value)//Proxy
    const myobj2=shallowRef({
      name:'zhangsan',
      age:12
    })
    console.log(myobj2)//RefImpl
    myobj2.value={
      name:'wanger',
      age:55
    }
    console.log(myobj2)//RefImpl


    return {
      myobj1,
      myobj2
    }
  }
}
</script>

<style>

</style>

8、triggerRef

手动触发响应式操作

<template>
  <div>
    <span>{{myobj1}}</span>
    <hr/>
    <span>{{myobj2}}</span>
  </div>
</template>

<script>

import {ref,reactive,customRef,shallowRef,watchEffect,triggerRef} from 'vue'

export default {
  name: 'App',
  setup () {
    const myobj1=ref({
      name:'zhangsan',
      age:12
    })
    console.log(myobj1)//RefImpl
    myobj1.value={
      name:'lisi',
      age:33
    }
    console.log(myobj1.value)//Proxy
    const myobj2=shallowRef({
      name:'zhangsan',
      age:12
    })
    console.log(myobj2)//RefImpl
    myobj2.value={
      name:'wanger',
      age:55
    }
    console.log(myobj2)//RefImpl

    let name=''

    watchEffect(()=>{
      name=myobj2.value.name
      console.log(name)
    })
    myobj2.value.name='zhaoqiusun'

    triggerRef(myobj2)


    return {
      myobj1,
      myobj2
    }
  }
}
</script>

<style>

</style>

9、computed

返回一个不可变的值
返回值也是一个ref

<template>
  <div>
    <span>{{superSentence}}</span>

  </div>
</template>

<script>

import {ref,computed} from 'vue'

export default {
  name: 'App',
  setup (props,context) {
    const textRef=ref('欢迎来到我的小屋')

    const superSentence=computed(()=>{
      return '小明'+textRef.value
    })

    console.log(superSentence.value)


    return {
      superSentence
    }
  }
}
</script>

<style>

</style>

实际机制其实也是一个get和set

<template>
  <div>
    <span>{{superSentence}}</span>

  </div>
</template>

<script>

import {ref,computed} from 'vue'

export default {
  name: 'App',
  setup (props,context) {
    const textRef=ref('欢迎来到我的小屋')

    const superSentence=computed(
      {
        get(){
          return '小明'+textRef.value
        },
        set(value){
          console.log('我通过计算属性修改了值')
          console.log(value)

        }
      }
    )

    console.log(superSentence.value)
    superSentence.value='我一旦修改,就要触发set语句'


    return {
      superSentence
    }
  }
}
</script>

<style>

</style>

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值