Vue3的一些特性(当个小笔记)

133 阅读3分钟

Vue3里面的生命周期钩子函数

  • setup()利用setup来代替beforecreate和created
  • onBeforeMount()//dom渲染前
  • onMounted()//dom渲染后
  • onBeforeUpdated() //更新前
  • onUpdated()//更新后
  • onBeforeUnmount()//销毁前
  • onUnmounted//销毁后

Vue3的ref,reactive,toref

1.ref

Vue3是属于比较严格的,所以不会像vue2一样加个model就能够及时的在页面上改变数据了。如果我们想要做成响应式数据的话,我们需要用到[ref],同时ref也会把我们写的属性变成对象。

<template>
 <div class="home">
     <h1>姓名:{{name}}</h1>
     <h2>姓名:{{age}}</h2>
     <h2>职业:{{person.occupation}}</h2>
     <button @click="say">修改</button>
  </div>
</template>
import {ref,defineComponent} from 'vue' //如果不用ref引用的话会报错
export default  defineComponent({
    name:'Home',
    setup(){
      let name=ref("zyy")
      let age=ref(19)
      let person=ref({
        occupation:'厨师'
        salary:'10k'
      })
      console.log(name) 
      console.log(age)
      //写个方法
      function say(){
         name.value='aaa'
         age.value=20
         person.value.occupation='程序员'
      }
      return {
        name,
        age,
        person,
        say
      }
      }
})

由此我们可以看出,通过ref可以把数据变成响应式数据。

2.reactive

reactive是ref的深层响应式,也可以进行数据的响应,而且如果对内部数据做出改变的话就不需要.value了。为什么ref要.value才可以修改呢。因为ref会提供一个内部值访问属性value

<template>
 <div class="home">
     <h1>姓名:{{name}}</h1>
     <h2>姓名:{{age}}</h2>
     <h2>职业:{{person.occupation}}</h2>
     <button @click="say">修改</button>
  </div>
</template>
import {ref,reactive,defineComponent} from 'vue' 
export default  defineComponent({
    name:'Home',
    setup(){
      let name=ref("zyy")
      let age=ref(19)
      let person=reactive({
      occupation:'厨师'
      salary:'10k'
      })
      }
      console.log(name) 
      console.log(age)
      //写个方法
      function say(){
         name='aaa'
         age=20
         person.occupation='程序员'
      }
      return {
        name,
        age,
        person,
        say
      }
      }
})

也可以把所以要动态响应的数据放进一个对象里通过reactive修改,这样就不用每次都ref啦。

<template>
 <div class="home">
     <h1>姓名:{{name}}</h1>
     <h2>姓名:{{age}}</h2>
     <h2>职业:{{person.occupation}}</h2>
     <button @click="say">修改</button>
  </div>
</template>
import {ref,reactive,defineComponent} from 'vue' 
export default  defineComponent({
    name:'Home',
    setup(){
      let data=reactive({
      name:'zyy',
      age:18, 
      job:{ occupation:'厨师',salary:'10k' },
      })
      //写个方法
      function say(){
         data.name='aaa'
         data.age=20
         data.person.occupation='程序员'
      }
      return {
        data,
        say
      }
      }
})

3.toRef

 setup() {
    console.log(this);
    const msg={
      name:'ls',
      age:19
    }
    let name=toRef(msg,'name')
    const say=()=>{
     name.value='zz'
     console.log(msg.name);
    }
    return{
      say,
      name
    }
  },

toRef和ref本质区别就是toRef会改变原始数据msg的name,而且改变的数据不会响应到页面上。而ref属于copy,不会改变原始msg的数据 如果我们想批量修改做成响应式数据并且不在页面渲染我们可以使用toRefs批量修改

4.toRefs

 setup() {
    console.log(this);
    const msg={
      name:'ls',
      age:19
    }
    let name=toRefs(msg)
    const say=()=>{
     name.name.value='zz'
     name.age.value='40'
     console.log(name);
     console.log(msg);
    }
    return{
      say,
      name
    }
  },
一个小案例:记录一下鼠标滑动的坐标点
<template>
  <div class="container">
    <div>坐标{{x}}</div>
    <div>坐标{{y}}</div>
  </div>
</template>
<script>
import { onMounted, reactive,toRefs} from 'vue'
export default({
  setup() {
    //1.记录鼠标坐标
    //1.1申明一个响应式数据,他是一个对象包含x,y
    const mouse=reactive({
      x:0,
      y:0
    })
    //1.3修改响应式数据
    const move=(e)=>{
      mouse.x=e.pageX
      mouse.y=e.pageY 
    }
    //1.2等dom渲染完毕,去监听事件
    onMounted(()=>{
      document.addEventListener('mousemove',move)
    })
    //组件销毁时,删除事件
    onUnmountrf(()=>{
       document.removeEventListener('mousemove',move)
    })
    return{...toRefs(mouse)}
    
  },
})
</script>

Vue的计算属性

要注意的是,计算属性是不可以修改的

import {computed, ref} from 'vue'
export default({
  setup() {
    const age=ref(16)
    const newAge=computed(()=>{
      return age.value+2
    })

    return{
      newAge,
      age
    }
  },
})

如果我们想对值做计算属性 我们可以通过set方法

import {computed, ref} from 'vue'
export default({
  setup() {
    const age=ref(16)
    const newAge=computed({
      //get函数,获取计算属性的值
      get(){
        return age.value+2
      },
      set(value){
        age.value=value-2
        console.log(value);
      }
    })

    return{
      newAge,
      age
    }
  },
})

vue3的wacth监听器

import {watch, reactive} from 'vue'
export default({
  setup() {
    
    const obj=reactive({
      name:'ls',
      age:10
    })
    const updateName=()=>{
      obj.name='zyy'
    }
    watch(()=>obj.name,()=>{//这是监听对象中的某一项
        console.log('监听obj.name改变了');
    })
    /*这是正常的监听
     watch(obj,(newVal,oldVal)=>{
        console.log(newVal.name,oldVal.name);
    })
    /*
    return{
      obj,
      updateName
    }
  },
})

Ref属性

需要了解的是可以批量操作元素,但必须是动态绑定

<template>
  <div class="container">
  <div ref='dom'>我是box</div>
  <ul>
    <li v-for="i in 4"  :key="i" :ref="setDom">{{i}}</li>
  </ul>
  </div>
</template>
<script>
import {onMounted, ref} from 'vue'
export default({
  setup() {
    const dom=ref(null)
    onMounted(()=>{
      console.log(dom.value);
    })
    const domList=[]
    const setDom=(el)=>{
      domList.push(el)
    }
    console.log(domList);
    return{
      dom,
      setDom
    }
  },
})
</script>

组件通信 父-----子

父组件传值给子组件

App.vue
<template>
  <div>父组件
   <Son :money="money"></Son> 
  </div>
</template>
<script>
import Son from './components/son.vue'
import {ref} from 'vue'
export default({
  components:{
    Son
  },
  setup(){
    //父组件传给子组件
    const money=ref(100)
    return{ money }
  }
})
</script>
son.vue
<template>
<div>子组件
<p>{{money}}</p>    
</div>
</template>
<script>
export default ({
    //子组件接受一下父组件的值
    props:{
        money:{
            type:Number,
            default:0
        }
    }
})
</script>

子-----父

子组件传值给父组件,通过emit,如上个例子所示,在他的基础上把money变更为50传给父组件

son.vue
<template>
<div>子组件
    <p>{{money}}</p>
<button @click="changeMoney">花50元</button>
</div>
</template>
<script>
export default ({
    props:{
        money:{
            type:Number,
            default:0
        }
    },
    //emit出发自定义事件的函数
setup(props,{emit}){
const changeMoney=()=>{
    console.log(props.money);
    //消费50元
    //通知父组件,money需变成50
    emit('change-money',50)
}
return{
    changeMoney
}
}
})
</script>
app.vue

<template>
  <div>父组件
   {{money}} 
    <hr>
   <Son :money="money" @change-money='updatemoney'></Son> 
  </div>
</template>
<script>
import Son from './components/son.vue'
import {ref} from 'vue'
export default({
  components:{
    Son
  },
  setup(){
    //父组件传给子组件
    const money=ref(100)
    const updatemoney=(newMoney)=>{
      console.log(newMoney);
      money.value=newMoney
    }
    return{ money,updatemoney }
  }
})
</script>

依赖注入

目的:共享父组件

app.vue
<template>
<div>父组件{{money}}
  <hr>
<Son></Son>
</div>
</template>
<script>
import {provide,ref} from 'vue'
import Son from './components/son.vue'
export default ({
    components:{
        Son
    },
    setup(){
        const money=ref(100)
        const changeMoney=(saleMoney)=>{
          console.log('changemoney',saleMoney);//需要注意的是saleMoney就是在grandson里设定的值
          money.value=money.value-saleMoney
        }
        //将数据提供给后代组件的provide
        provide('money',money)
        //将函数提供给后代组件provide
        provide('changeMoney',changeMoney)
        return{
    money
}
    }   
})
</script>
son.vue
<template>
    <div>
       子组件{{money}}
       <hr>
       <GrandSon></GrandSon>
    </div>
</template>
<script>
import{inject} from 'vue'
import GrandSon from './GrandSon.vue'
export default({
    components:{
        GrandSon
    },
    setup() {
        //接受外层组件提供的组件
    const money=inject("money")
    return{
        money
    }
    },
})
</script>
grandson.vue
<template>
    <div>孙组件{{money}}
     <button @click='fn'>消费50</button>   
    </div>
    
</template>
<script>
import{inject} from 'vue'
export default ({
    setup() {
        //孙组件消费50通知父组件进行修改,不能自己修改数据,谁定义谁修改
        const  money=inject('money')
        const changemoney=inject('changeMoney')
        const fn=()=>{
            changemoney(50)
        }
        return{money,fn}
    },
})
</script>

v-model的xxx=$event,类似于一个语法糖

app.vue
<template>
<div>
  <!-- 参考代码 -->
 <h1 @click="$event.target.style.color='red'">父组件{{count}}</h1> 
  <hr>
  <!-- 如果你想获取原生事件|自定义事件的传参, -->
  //通过count=$event,把在子组件操作的事件应用到count上
<Son :modeValue='count' @update:modeValue='count=$event'></Son>

</div>
</template>
<script>
import {ref} from'vue'
import Son from './components/son.vue'
export default ({
    components:{
        Son
    },
    setup(){
       const count=ref(0)
       return{
         count
       }
        } 
})
</script>

子组件还是一切如旧

<template>
    <div>
       子组件{{modeValue}}
       <button @click="fn">改变数据</button>
    </div>
</template>
<script>
export default({
    props:{
        modeValue:{
            type:Number,
            default:0
        }
    },
    setup(props,{emit}) {
        const fn=()=>{
           emit('update:modeValue',100) 
        }
        return{
            fn
        }
    },
})
</script>

mixins语法(混入)

全局混入

main.js

 const app=createApp(App)
 app.mixin({
     mounted(){
         console.log(this.$el,'dom准备好');
     }
 })
 app.mount('#app')

例子:做一个同步关注

<template>
<div>
   <h1>作者:周杰伦 <a href="javascript:;" @click="followFn">{{loading?'正在请求,,,':'关注'}}</a></h1>
   <hr>
  <Son/>
</div>
</template>
<script>
import Son from './components/Son.vue'
import {followMixin} from './mixins.js'
export default {
  name: 'App',
  components: {
    Son
  },
  mixins:[followMixin]
}
</script>
<template>
  <div class="container">
    <h1>作者:周杰伦 <a href="javascript:;" @click="followFn">{{loading?'正在请求,,,':'关注'}}</a></h1>
  </div>
</template>
<script>
import {followMixin} from './mixins.js'
export default ({
  mixins:[followMixin]
})
</script>