Vue3学习笔记

Vue 3

1. setup 配置项

beforeCreate 之前执行 即:setup 中 this 不存在

1. setup 是所有Composition API "表演的舞台"
2. 组件中所用到的所有 data,methods…都要配置到 setup 中
3. setup 函数的返回值:

  • 返回一个对象,则对象的属性方法在模板中可以直接使用
  • 返回一个渲染函数

1.1 setup 配置项中的三个注意点

  • props
  • emit
  • slots

App.vue

<template>
  <Demo name="tom" :age="18" school="atguigu" @showMsg="showMsg">
    <!-- 只能用 v-slot log 中才能打印出来 -->
    <template v-slot:test1>
      <span>这里是父标签给子组件的标签体</span>
    </template>
  </Demo>
</template>

<script>

import Demo from './components/Demo.vue'
export default {
  name: 'App',
  components:{Demo},
  setup(){
    function showMsg(value){
      alert(`我是App我收到的数据是:${value}`)
    }
    return{
      showMsg,
    }
  }
}
</script>

<style>
</style>

在这里插入图片描述

Demo.vue

<template>
    <h3>这里是Demo组件</h3>
    <h3>{{name}}</h3>
    <h3>{{school}}</h3>
    <h3>{{age}}</h3>
    <slot name="test1"></slot><br>
    <button @click="showAgeType">显示年龄的类型</button><br>
    <button @click="showMsg">点击触发App传来的方法</button>
</template>

<script>
export default {
    name:'Demo',
    //接收父组件传的数据
    props:['name','school','age'],
    //接受父组件的函数
    emits:['showMsg'],
    //setup 能接受的两个参数 setup 没有 this
    setup(props,context){
        console.log('Demo 中的 setup 配置项执行了...')
        console.log(props,context)
        console.log('emit是:',context.emit);
        console.log('slots是:',context.slots);
        function showAgeType(){
            console.log(typeof(props.age))
        }
        function showMsg(){
            context.emit('showMsg',666)
        }
        return{
            showAgeType,
            showMsg,
        }
    },
    mounted() {
        console.log(this)
        console.log('Demo 组件挂载了...')
    },
}
</script>

<style>

</style>

子组件需要申明接受 父组件传来的全部参数和自定义方法 props 和 emits,不接受收 log 会 warning

computed 计算属性

不同于vue2 计算属性变成了 一个函数 简写形式只触发 get 方法 完整形式可以使用 set 方法

<template>
    姓:<input type="text" v-model="person.firstName"><br>
    名:<input type="text" v-model="person.lastName"><br>
    <span>全名:{{person.fullName}}</span><br>
    <input type="text" v-model="person.fullName">
</template>

<script>
import { computed, reactive } from '@vue/reactivity'
export default {
    name:'Demo',
    setup(){
        //使用 reactive 实现对象响应式
        let person = reactive({
            firstName:'张',
            lastName:'三'
        })
        //reactive 属性追加的属性也是响应式的

        //完整写法
        // person.fullName = computed({
        //     get(){
        //         return person.firstName + '-' + person.lastName
        //     },
        //     set(value){
        //         const nameArr = value.split('-')
        //         person.firstName = nameArr[0]
        //         person.lastName = nameArr[1]
        //     }
        // })

        //简写形式
        person.fullName = computed(()=>{
            return person.firstName + '-' + person.lastName
        })

        return{
            person,
        }
    },
}
</script>

<style>

</style>

1.2 watch监视数据变化【注意deep的使用】

监视的是 refImpl 包裹的对象

但是使用 ref 定义对象时,_value 是 Proxy 对象

即:refImpl 对象中的对象 无法进行监视

对象.value 是 Proxy 对象, 可进行监视

也可以对 ref 定义的对象使用 deep 监视

watch(监视对象,回调函数,开启immediate或者开启深度监视等)

reactive 定义的数据 在监视时无法获得 oldValue 无需开启深度监视且没法关闭

如果要监视对象的某一个属性需要使用函数

  • 情况1
<template>
   <h3>{{sum}}</h3><button @click="sum++">点击按钮改变其值</button>
   <h3>{{msg}}</h3><button @click="msg += '!'">点击按钮改变其值</button>
</template>

<script>
import { reactive,ref,watch } from 'vue'
export default {
    name:'Demo',
    setup(){
        let sum = ref(0)
        let msg = ref('你好啊')
        let person = reactive({
            name:'张三',
            age : 20,
            job:{
                salary:20
            }
        })
        // 情况一:watch监视 ref 定义的一个响应式数据
        watch(sum,(newValue,oldValue)=>{
            console.log('sum值变了',newValue,oldValue);
        },{immediate:true})

        return{
            sum,
            msg
        }
    },
}
</script>

<style>

</style>
  • 情况2
<template>
   <h3>{{sum}}</h3><button @click="sum++">点击按钮改变其值</button>
   <h3>{{msg}}</h3><button @click="msg += '!'">点击按钮改变其值</button>
</template>

<script>
import { reactive,ref,watch } from 'vue'
export default {
    name:'Demo',
    setup(){
        let sum = ref(0)
        let msg = ref('你好啊')
        let person = reactive({
            name:'张三',
            age : 20,
            job:{
                salary:20
            }
        })
        // 情况二:watch监视 ref 定义的多个响应式数据
        watch([sum,msg],(newValue,oldValue)=>{
            console.log('sum值或者msg变了',newValue,oldValue);
        },{immediate:true})

        return{
            sum,
            msg
        }
    },
}
</script>

<style>

</style>
  • 情况三

默认开启深度监视,且无法关闭

无法获取 oldValue 值 与 newValue 的值相同

<template>
   <h3>{{sum}}</h3><button @click="sum++">点击按钮改变其值</button>
   <h3>{{msg}}</h3><button @click="msg += '!'">点击按钮改变其值</button>
   <hr>
   <h3>{{person.name}}</h3><button @click="person.name += '~'">点击按钮改变其值</button>
   <h3>工资:{{person.job.salary}}</h3><button @click="person.job.salary++">点击按钮改变其值</button>
   
</template>

<script>
import { reactive,ref,watch } from 'vue'
export default {
    name:'Demo',
    setup(){
        let sum = ref(0)
        let msg = ref('你好啊')
        let person = reactive({
            name:'张三',
            age : 20,
            job:{
                salary:20
            }
        })
        // 情况三:watch监视 reactive 定义的一个响应式对象的全部属性
        watch(person,(newValue,oldValue)=>{
            console.log('person值变了',newValue,oldValue);
        },{immediate:true})

        return{
            sum,
            msg,
            person
        }
    },
}
</script>

<style>

</style>
  • 情况四

需要使用函数的返回值作为监视的对象

用不到 deep 监视

<template>
   <h3>{{sum}}</h3><button @click="sum++">点击按钮改变其值</button>
   <h3>{{msg}}</h3><button @click="msg += '!'">点击按钮改变其值</button>
   <hr>
   <h3>{{person.name}}</h3><button @click="person.name += '~'">点击按钮改变其值</button>
   <h3>{{person.age}}</h3><button @click="person.age++">点击按钮改变其值</button>
   <h3>工资:{{person.job.salary}}</h3><button @click="person.job.salary++">点击按钮改变其值</button>
   
</template>

<script>
import { reactive,ref,watch } from 'vue'
export default {
    name:'Demo',
    setup(){
        let sum = ref(0)
        let msg = ref('你好啊')
        let person = reactive({
            name:'张三',
            age : 20,
            job:{
                salary:20
            }
        })
        // 情况四:watch监视 reactive 定义的一个响应式对象的 某个属性
        // 需要使用函数 返回谁就是监视谁
        watch(()=>person.age,(newValue,oldValue)=>{
            console.log('person的age值变了',newValue,oldValue);
        },{immediat:true,deep:false})

        return{
            sum,
            msg,
            person
        }
    },
}
</script>

<style>

</style>
  • 情况五
<template>
   <h3>{{sum}}</h3><button @click="sum++">点击按钮改变其值</button>
   <h3>{{msg}}</h3><button @click="msg += '!'">点击按钮改变其值</button>
   <hr>
   <h3>{{person.name}}</h3><button @click="person.name += '~'">点击按钮改变其值</button>
   <h3>{{person.age}}</h3><button @click="person.age++">点击按钮改变其值</button>
   <h3>工资:{{person.job.salary}}</h3><button @click="person.job.salary++">点击按钮改变其值</button>
   
</template>

<script>
import { reactive,ref,watch } from 'vue'
export default {
    name:'Demo',
    setup(){
        let sum = ref(0)
        let msg = ref('你好啊')
        let person = reactive({
            name:'张三',
            age : 20,
            job:{
                salary:20
            }
        })
        // 情况五:watch监视 reactive 定义的一个响应式对象的 某些属性
        // 需要使用函数 返回谁就是监视谁
        watch([()=>person.age,()=>person.name],(newValue,oldValue)=>{
            console.log('person的age值或者name值变了',newValue,oldValue);
        },{immediat:true,deep:false})

        return{
            sum,
            msg,
            person
        }
    },
}
</script>

<style>

</style>
  • 情况6

需要使用深度监测

开启后也无法能获取 oldValue 值

<template>
   <h3>{{sum}}</h3><button @click="sum++">点击按钮改变其值</button>
   <h3>{{msg}}</h3><button @click="msg += '!'">点击按钮改变其值</button>
   <hr>
   <h3>{{person.name}}</h3><button @click="person.name += '~'">点击按钮改变其值</button>
   <h3>{{person.age}}</h3><button @click="person.age++">点击按钮改变其值</button>
   <h3>工资:{{person.job.salary}}</h3><button @click="person.job.salary++">点击按钮改变其值</button>
   
</template>

<script>
import { reactive,ref,watch } from 'vue'
export default {
    name:'Demo',
    setup(){
        let sum = ref(0)
        let msg = ref('你好啊')
        let person = reactive({
            name:'张三',
            age : 20,
            job:{
                salary:20
            }
        })
        // 特殊情况:watch监视 reactive 定义的一个响应式对象的 某个深度属性
        watch(()=>person.job,(newValue,oldValue)=>{
            console.log('person的job值变了',newValue,oldValue);
        },{immediat:true,deep:true})

        return{
            sum,
            msg,
            person
        }
    },
}
</script>

<style>

</style>

在这里插入图片描述

  • 情况7

对第六种监视使用 person.job 的形式 能强制开启对下一层整个对象的深度监视

也无法获取 oldValue 值

在这里插入图片描述
在这里插入图片描述

1.3 watchEffect

回调函数中用谁就会监视谁

<template>
   <h3>{{sum}}</h3><button @click="sum++">点击按钮改变其值</button>
   <h3>{{msg}}</h3><button @click="msg += '!'">点击按钮改变其值</button>
   <hr>
   <h3>{{person.name}}</h3><button @click="person.name += '~'">点击按钮改变其值</button>
   <h3>{{person.age}}</h3><button @click="person.age++">点击按钮改变其值</button>
   <h3>工资:{{person.job.salary}}</h3><button @click="person.job.salary++">点击按钮改变其值</button>
   
</template>

<script>
import { reactive,ref,watchEffect} from 'vue'
export default {
    name:'Demo',
    setup(){
        let sum = ref(0)
        let msg = ref('你好啊')
        let person = reactive({
            name:'张三',
            age : 20,
            job:{
                salary:20
            }
        })
        //会点函数中用到了谁 就监视谁 和 vue2中的computed属性类似,只是不注重返回
        watchEffect(()=>{
            const s1 = sum.value
            const s2 = person.job.salary
            console.log('watchEffect 中的属性:sum 或 salary 发生了改变')
        })
        return{
            sum,
            msg,
            person
        }
    },
}
</script>

<style>

</style>

1.4 toRef 和 toRefs

为了简化模板中的代码【去除对象】并保持响应式
toRef(对象,对象属性)
toRefs(对象) 解析第一层的全部属性

<template>
    <h3>用于对比是否修改了到了person:{{person}}</h3>
    <h3>{{name}}</h3><button @click="name += '~'">点击修改姓名</button>
    <h3>{{age}}</h3><button @click="age++">点击修改年龄</button>
    <h3>person.job.salary.yearsSalary:{{person.job.salary.yearsSalary}}</h3><button @click="person.job.salary.yearsSalary++">点击修改年薪</button>
    <h3>yearsSalary:{{yearsSalary}}</h3><button @click="yearsSalary++">点击修改年薪</button>
</template>

<script>
import { reactive, toRef, toRefs } from '@vue/reactivity'

export default {
    name:'Demo',
    setup(){
       let person = reactive({
           name:'张三',
           age:22,
           job:{
               salary:{
                   yearsSalary:20
               }
           },
       })
       return{
           //return对象本身
           person,
           //toRef 指定对象的某个个属性
           yearsSalary:toRef(person.job.salary,'yearsSalary'),
           //对象的全部属性,这里不包含对象本省,所以想要在外面使用person对象还需要 return对象本身
           ...toRefs(person)
       }
    },
}
</script>

<style>

</style>

2. ref 函数

创建一个包含响应式的引用对象

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Sz3t6siv-1638867938077)(index_files/f4256e84-eccc-419c-a6aa-ed8a852f59e5.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kl3AFM57-1638867938081)(index_files/8b74bbcd-261b-48fd-9873-9b8487dd8059.png)]

3. customRef

自定义 ref
track() 追终变化
trigger() 触发从新解析模板

4. provide 和 inject

祖组件给后代组件传递消息的方式
祖组件 provide
后代组件 inject

在这里插入图片描述在这里插入图片描述

5. 不常用方法

shallowReactive

第一层数据响应式

shallowRef

第一层响应式 【不求人 reactive】

readonly

数据不允许修改 且 log 警告

【注意】是否与reactive响应式自相矛盾呢?

答案是否定的,不用响应式 不用 readonly 数据可以被修改,只是不是响应式,即:页面不改变,但是如果使用readonly 数据是不允许修改的

shallowReadonly

第一层数据不允许修改

toRaw

将一个 reactive 生成的对象转为普通对象 【ref 生成的不行】
与响应式相反 即:让你响应式的数据变成不是响应式

markRow

将对象标记为普通对象不是响应式

vue3生命周期

自定义 hook 函数

import { reactive,onMounted,onBeforeUnmount } from "vue"

//自定义打点 hook
export default function(){
    //打点相关的数据
    let point = reactive({
        x:0,
        y:0
    })

    //打点相关的方法
    function savePoint(event){
        point.x =  event.pageX
        point.y =  event.pageY
    }

    //打点相关的生命周期钩子
    onMounted(() => {
        window.addEventListener('click',savePoint)
    }),
    onBeforeUnmount(() => {
        window.removeEventListener('click',savePoint)
    })
    return point
}

3. reactive 函数

定义一个对象类型的响应式数据 基本类型处理不了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Yr2dhAR6-1638867938082)(index_files/77d65898-30b5-4796-a0f0-34697adcc6da.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TlNbDdWa-1638867938083)(index_files/30ce8b66-3e42-4ae3-9933-a2a0e4992692.png)]

2. Vue3 响应式原理

使用 Proxy 代理和 Reflect 反射

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值