vue3小野森森-03-toRaw,markRaw,生命周期钩子,选项式provide及inject,组合式provide及inject,给provide及inject增加响应式,$refs

1、toRaw

返回一个reactive或readonly包裹的proxy对象
其实就是将一个proxy对象转化成普通对象

<template>
  <div>

  </div>
</template>

<script>

import {ref,reactive,toRaw,readonly,shallowReactive,shallowReadonly,toRefs} from 'vue'

export default {
  name: 'App',
  setup (props,context) {
    //这是一个普通对象
    const obj={
      a:1,
      b:2
    }

    const proxyObj=reactive(obj)//转换成代理对象
    console.log(proxyObj)//打印成一个proxy对象
    const newObj=toRaw(proxyObj)//转换成普通对象
    console.log(newObj)//打印成一个普通对象
    //包装前和转换后其实是相等的
    console.log(newObj===obj)//true

    return {

    }
  }
}
</script>

<style>

</style>

2、markRaw(有点摄影里面那个raw的意思,原始的意思)

返回包裹对象的本身,和原对象是相等的
这种包含是浅度(shallow)的不是深度(deep)的

<template>
  <div>

  </div>
</template>

<script>

import {ref,reactive,toRaw,markRaw,readonly,shallowReactive,shallowReadonly,toRefs} from 'vue'

export default {
  name: 'App',
  setup (props,context) {
    //这是一个普通对象
    const obj={
      a:1,
      b:2
    }

    const rawObj=markRaw(obj)//包裹成普通对象
    console.log(obj)//打印一个普通对象
    console.log(rawObj)//依然打印一个普通对象
    console.log(obj===rawObj)//true

    const proxyObj=reactive(rawObj)//包装成proxy对象
    console.log(proxyObj)//但打印的依然还是普通对象

    return {

    }
  }
}
</script>

<style>

</style>

3、生命周期钩子

钩子参看前篇,略

4、选项式provide,inject

父组件作为数据的提供方:provider

vue3小野森森-03-toRaw,markRaw,生命周期钩子,选项式provide及inject,组合式provide及inject,给provide及inject增加响应式,$refs
Son.vue

<template>
  <h1>{{sonName}} i am son component</h1>
  <h1>{{directsonname}} directly provider name</h1>

</template>

<script>
  export default {
    name: 'Son',
    inject:['sonName','directsonname'],
    setup(){
      return {

      }
    },
  }
</script>

<style scoped>

</style>

Father.vue

<template>
  <h1>{{fathername}}  i am fahter component</h1>
  <hr/>
  <Son></Son>
</template>

<script>
  import Son from './Son.vue'
  export default {
    name: 'Father',

    setup(){
      const sonName='sonname'

      return {
        sonName
      }
    },
    provide:{
      sonName: 'sonName'
    },
    inject:['fathername'],
    components:{
      Son
    }
  }
</script>

<style scoped>

</style>

App.vue

<template>
  <div>
    <Father ></Father>
  </div>
</template>

<script>

import {ref,reactive} from 'vue'
import Father from './components/Father.vue'

export default {
  name: 'App',
  setup (props,context) {
    const myname=ref('Fathername')

    return {
      myname
    }
  },
  provide:{
    fathername:'Fathername',
    directsonname:'directSonName'
  },
  components:{
    Father,

  }
}
</script>

<style>

</style>

5、组合式Provide,inject

  • 需要在setup内调用
  • provide以函数的形式来使用,两个参数,第一个参数是属性名,第二个参数是属性值
  • 子组件inject和选项式provide和inject一样使用,也可以通过函数形式来使用
  • inject函数也有两个参数,一个是属性值,一个是默认值

Fther.vue

<template>
  <h1>{{name}}</h1>
  <hr/>
  <h1>{{age}}</h1>
  <hr/>
  <h1>{{hobby}}</h1>
  <hr/>
  <h1>{{career}}</h1>
  <hr/>
  <Son></Son>
</template>

<script>
  import Son from './Son.vue'
  export default {
    name: 'Father',
    inject:['name','age','hobby','career'],

    setup(){
      return {
      }
    },
    components:{
      Son
    }
  }
</script>

<style scoped>

</style>

App.vue

<template>
  <div>
    <Father ></Father>
  </div>
</template>

<script>

import {ref,reactive,provide} from 'vue'
import Father from './components/Father.vue'

export default {
  name: 'App',
  setup (props,context) {
    provide('name','zhangsan')
    provide('age',30)
    provide('hobby','sing')
    provide('career','programmer')

    return {
    }
  },


  components:{
    Father,

  }
}
</script>

<style>

</style>

推荐用法(inject也携程组合式的):
Father.vue

<template>
  <h1>{{name}}</h1>
  <hr/>
  <h1>{{age}}</h1>
  <hr/>
  <h1>{{hobby}}</h1>
  <hr/>
  <h1>{{career}}</h1>
  <hr/>
  <Son></Son>
</template>

<script>
  import Son from './Son.vue'
  import {inject } from 'vue'
  export default {
    name: 'Father',
    // inject:['name','age','hobby','career'],
    setup(){
      const name=inject('name','国泰民安')
      const age=inject('age','100')
      const hobby=inject('hobby','daqiu')
      const career=inject('career','dadouduo')

      return {
        name,
        age,
        hobby,
        career
      }
    },
    components:{
      Son
    }
  }
</script>

<style scoped>

</style>

app.vue

<template>
  <div>
    <Father ></Father>
  </div>
</template>

<script>

import {ref,reactive,provide} from 'vue'
import Father from './components/Father.vue'

export default {
  name: 'App',
  setup (props,context) {
    provide('name','zhangsan')
    provide('age',30)
    provide('hobby','sing')
    provide('career','programmer')

    return {
    }
  },


  components:{
    Father,

  }
}
</script>

<style>

</style>

6、给Provide,inject增加响应式

使用ref或reactive包裹
Father.vue

<template>
  <h1>{{name}}</h1>
  <hr/>
  <h1>{{age}}</h1>
  <hr/>
  <h1>{{hobby}}</h1>
  <hr/>
  <h1>{{career}}</h1>
  <hr/>
  <Son></Son>
</template>

<script>
  import Son from './Son.vue'
  import {inject } from 'vue'
  export default {
    name: 'Father',
    // inject:['name','age','hobby','career'],
    setup(){
      const name=inject('name','国泰民安')
      const age=inject('age','100')
      const hobby=inject('hobby','daqiu')
      const career=inject('career','dadouduo')

      return {
        name,
        age,
        hobby,
        career
      }
    },
    components:{
      Son
    }
  }
</script>

<style scoped>

</style>

App.vue

<template>
  <div>
    <Father ></Father>
    <button @click="changeNumber">改变</button>
  </div>
</template>

<script>

import {ref,reactive,provide} from 'vue'
import Father from './components/Father.vue'

export default {
  name: 'App',
  setup (props,context) {
    const myname=ref('张小三')
    provide('name',myname)
    provide('age',30)
    provide('hobby','sing')
    provide('career','programmer')

    setTimeout(()=>{
      myname.value='王大拿'
    },2000)

    const changeNumber=()=>{
      myname.value='郭晶晶'
    }

    return {
      changeNumber
    }
  },


  components:{
    Father,

  }
}
</script>

<style>

</style>

  • provide不仅可以提供变量,还可以提供函数
  • inject可以注入(接受)到provide提供的这个函数,从而不用再子组件中编写这个函数(方法),因为数据是由父组件提供的,所以也建议在父组件中提供方法修改这个数据,子组件只是接收和使用父组件传过来的数据
  • 父组件在提供方法的时候最好使用readonly包裹一下
    Father.vue
<template>
  <h1>{{name}}</h1>
  <hr/>
  <h1>{{age}}</h1>
  <hr/>
  <h1>{{hobby}}</h1>
  <hr/>
  <h1>{{career}}</h1>
  <hr/>
  <button @click="changeName">改变姓名</button>
  <Son></Son>
</template>

<script>
  import Son from './Son.vue'
  import {inject } from 'vue'
  export default {
    name: 'Father',
    // inject:['name','age','hobby','career'],
    setup(){
      const name=inject('name','国泰民安')
      const age=inject('age','100')
      const hobby=inject('hobby','daqiu')
      const career=inject('career','dadouduo')

      const changeName=inject('changeName')

      return {
        name,
        age,
        hobby,
        career,
        changeName
      }
    },
    components:{
      Son
    }
  }
</script>

<style scoped>

</style>

App.vue

<template>
  <div>
    <Father ></Father>
  </div>
</template>

<script>

import {ref,reactive,provide,readonly} from 'vue'
import Father from './components/Father.vue'

export default {
  name: 'App',
  setup (props,context) {
    const myname=ref('张小三')
    provide('name',readonly(myname))
    provide('age',30)
    provide('hobby','sing')
    provide('career','programmer')

    const changeName=()=>{
      myname.value='郭小晶'
    }

    provide('changeName',changeName)



    return {

    }
  },


  components:{
    Father,

  }
}
</script>

<style>

</style>

7、$refs模板引用(vue2)

  • 实现了类似jquery的dom操作
  • 也就是通过ref=‘子组件名’的形式给子组件命名,在通过$refs.子组件名.方法或者属性来操作子组件上的属性或方法
  • $refs只能作用直接子组件
    以下例子是使用vue2选项式API

Father.vue

<template>
  <h1>{{name}}</h1>
  <Son></Son>
</template>

<script>
  import Son from './Son.vue'
  import {ref,inject } from 'vue'
  export default {
    name: 'Father',
    data(){
      return{
        name:'zhangan'
      }
    },
    methods:{
      changeName(){
        this.name='lisi'
      }
    },

    // inject:['name','age','hobby','career'],
    setup(){

      return {

      }
    },
    components:{
      Son
    }
  }
</script>

<style scoped>

</style>

App.vue

<template>
  <div>
    <Father ref="father"></Father>
    <hr/>
    <button @click="changename">改变名称</button>
  </div>
</template>

<script>

import {ref,reactive,provide,readonly} from 'vue'
import Father from './components/Father.vue'

export default {
  name: 'App',
  setup (props,context) {

    return {
    }
  },

  methods:{
    changename(){
      this.$refs.father.changeName()
    }
  },
  components:{
    Father,

  }
}
</script>

<style>

</style>

8、refs(vue3)

  • 使用组合式api的时候reactive,ref和templates是统一的
  • 在setup上声明ref
  • 在组件上使用的ref的属性名,必须在setup上定义一个和他名字一致的变量
  • 这个变量用来接收一个被ref包裹的null值(默认要求)
  • 在方法中使用这个ref(通过这个ref拿到这个dom节点,并进行操作)

Father.vue

<template>
  <h1>{{name}}</h1>
  <!--  这里的ref的名字要和setup里面的名字一致-->
  <h1 ref="mychild">张三</h1>
  <button @click="changeMyName">改变名字</button>
  <Son></Son>
</template>

<script>
  import Son from './Son.vue'
  import {ref,inject } from 'vue'
  export default {
    name: 'Father',
    setup(){
      //默认必须要ref一个null值,注意这里的child要和组件上的ref的名字一致
      const mychild=ref(null)
      const changeMyName=()=>{
        //通过mychild拿到子组件节点,并进行dom操作
        mychild.value.innerText='lisi'
      }
      return {
        mychild,
        changeMyName
      }
    },
    components:{
      Son
    }
  }
</script>

<style scoped>

</style>

App.vue

<template>
  <div>
    <Father ref="father"></Father>

  </div>
</template>

<script>

import {ref,reactive,provide,readonly} from 'vue'
import Father from './components/Father.vue'

export default {
  name: 'App',
  setup (props,context) {

    return {
    }
  },

  methods:{

  },
  components:{
    Father,

  }
}
</script>

<style>

</style>

另外一例
Father.vue

<template>
    <!--  这里的ref的名字要和setup里面的名字一致-->
  <h1 >{{name}}</h1>
  <button @click="changeMyName">改变名字</button>
  <Son></Son>
</template>

<script>
  import Son from './Son.vue'
  import {ref,inject } from 'vue'
  export default {
    name: 'Father',
    setup(){
      const name=ref('zhangsan')
      const changeMyName=()=>{
        name.value='lilaosi'
      }
      return {
        name,
        changeMyName
      }
    },
    components:{
      Son
    }
  }
</script>

<style scoped>

</style>

App.vue

<template>
  <div>
    <Father ref="father"></Father>
    <button @click="setname">设置名字</button>

  </div>
</template>

<script>

import {ref,reactive,provide,readonly} from 'vue'
import Father from './components/Father.vue'

export default {
  name: 'App',
  setup (props,context) {
    const father=ref(null)

    const setname=()=>{
      father.value.changeMyName()
    }
    return {
      father,
      setname
    }
  },

  methods:{

  },
  components:{
    Father,

  }
}
</script>

<style>

</style>

上一篇:【provide和inject传值】


下一篇:VUE3中实现刷新