Title

一、setup文件的认识

   特点1:script 中间的内容就是一个对象

  特点2:script 在第一层 定义的方法 或者 变量 => 就是这个对象 属性  => 顶层的绑定回被暴露给模板(模板可以直接使用这个变量)

  特点3:setup 默认执行生命周期beforeCreate created
  注意:这个对象 => 就是当前这个组件实例

二、什么是响应式api

  处理 数据 => 我们把页面写的数据,需要动态改变的数据 => 叫做  响应式数据 => 数据改变视图中使用了这个数据,这个数据回对应的       响应式数据底层实现 => vue3 => Proxy

  可以把数据变成响应式api 的方法叫做响应式 api
  什么是响应式数据:就是数据改变 视图对应更新
 

三、在vue3 中有哪些常用的响应式API?

响应式核心:

1、ref()

  作用:将一个基本数据类型的数据变为响应式

  语法:let 变量=ref(处理的数据)

<template>
  <div>
    <h2>响应式api</h2>
    <h2>{{age}}</h2>
    <button @click="addAge">change</button>
  </div>
</template>

<script setup>
  import {ref} from 'vue';
  // ref 处理的数据 
  // 1 基本数据类型 => 通过vue2 响应式原理来实现Object.defineProperty()
  // 2 处理的复杂的数据类型 => reactive()这个响应式api

  let age=ref(29);  // 通过ref 处理的数据 => 变成响应式
  let data=ref({ages:50});
  console.log(data,"data")
  
  const addAge=()=>{
    age.value+=1;
    console.log(age);
  }
</script> <style> </style>

 

2、reactive()

  作用:将复杂的数据类型变成响应式数据
  语法:let data=reactive({处理的数据})
  特点:1. 就是proxy代理可以将对象中第一层的属性变成响应式,不用递归,提供性能优化。2. 就是 proxy 代理的数据时对象,这个对象中有深层次,它会实现懒代理(就是用户只有在使用了这个数据,才会将这个数据变为响应式数据)
<template>
  <div>
    <h2>响应式api</h2>
    
   <h2>{{objP.name}}的年龄{{objP.age}}</h2>
   
    <button @click="changeName">changeName</button>
    <button @click="changeLike">changeLike</button>
  </div>
  
</template>

<script setup>
  import {reactive} from 'vue';
  
  // 作用将复杂的数据类型变成响应式数据
  let objP=reactive({
    name:"小明",
    age:8,
    like:{eat:'🍎',play:['⚽']}
  })

    // reactive()代理数据类型 对象 特点
      //  1 就是 proxy 代理可以将对象中第一层的属性变成响应式,不用递归,提供性能优化
      //  2 就是 proxy 代理 数据是对象,这个对象中属性有深层次,他会实现懒代理
      // 就是用户只有在使用了这个数据,才会将这个数据变为 响应式数据
      console.log(objP);

      const changeName=()=>{
        objP.name="lisa"
        objP.age+=1;
      }

      const changeLike=()=>{
        objP.like.play=['🌏'];
        console.log(objP.like); // 使用后深层次数据也变为响应式数据
      }

      
</script>

<style>

</style>

 3、readonly()

  作用:处理的数据,只能读取不能修改,父组件给子组件数据

  语法:let 数据 =readonly(默认数据)

<template>
  <div>
    <h2>readonly</h2>
<!-- 作用:处理的数据,只能读取不能修改,父组件给子组件数据 
      语法:  let 数据  =readonly(默认数据)
-->
    <h2>{{ obj.name }}</h2>
    <button @click="change">修改数据</button>
  </div>
  
</template>

<script setup>
  import {readonly} from 'vue';
  
  let obj=readonly({name:'lisa'});  // 通过proxy代理

  console.log(obj)

  const change=()=>{
    obj.name="cici";    // 只读的,无法修改
  }
      
</script>

<style>

</style>

4、watchEffect()

  作用: 页面更新 就会触发watchEffect 处理函数

  语法:watchEffect(( )=>{ })

  特点:1 第一次默认执行 处理函数; 2 watchEffect 监听的数据,需要我们写到他的处理函数中,并且 可以监听多个; 3 watchEffect 监听的数据的改变,处理函数就会触发=》获取到最新的数据=》没有旧 的数据

<template>
    <div>
        <h2>watchEffect 副作用</h2>
        <!-- 
            作用: =》 页面更新 就会触发watchEffect 处理函数

            语法:watchEffect(()=>{

            })
         -->
         <h2>{{ name }}</h2>
         <h2>{{ age }}</h2>
         <button @click="addAge">年龄+1</button>
         <button @click="changeName">修改name</button>
    </div>
</template>

<script setup>
    
    import {ref,watchEffect} from 'vue';

    let age=ref(20);
    let name=ref("lisa");

    // watchEffect 特点
    // 1 第一次执行 处理函数
    // 2 watchEffect 监听的数据, 需要我们写到它的处理函数中,并且可以监听多个
    // 3 watchEffect 监听数据的改变,获取到新的数据,没有旧数据

    // watchEffect(()=>{
    //     console.log("页面更新了");
    //     console.log(age.value);// 监听 age 值,只要这个值发生改变,这个watchEffect 他的处理函数就是重新执行,获取到的最新的数据
    //     console.log(name.value);
    // })


    // 在watchEffect中做数据处理
    watchEffect(()=>{
        console.log('页面更新');
      if(age.value>30){
        console.log('200');
      }
    })
    const addAge = ()=>{
        age.value =   age.value +1
     }
     const changeName =()=>{
        name.value='小明'
     }
</script>

<style>
</style>

 5、watch()

  作用:侦听一个或多个响应式数据源,并在数据源变化时调用所给的回调函数。

  语法:watch(数据源,回调函数,配置项)  

    数据源:监听的数据源、

    回调函数:(newVal,oldVal)=>{console.log(newVal,oldVal); // 数据改变会触发次函数的执行 }、

    配置项:immediate:true; // 第一次默认监听数据、deep:true; // 监听深度数据

  总结watch():1. 首次加载默认不监听,2. 可以监听多个数据源 ,3. 可以处理异步问题

  watch() 和 watchEffect() 的区别:

  相同点:1. 都是侦听一个或多个响应式数据源,2. 可以处理异步问题

  不同点:watchEffect 默认立即监听数据,只能获取到新的数据;而watch 第一次默认不见听数据,可以获取到新旧数据

<template>
  <div>
    <h2>watch</h2>
    <!-- <h2>{{ name }}</h2> -->
    <h2>{{ age }}</h2>
    <button @click="changeAge">年龄+1</button>
    <!-- <button @click="changeName">修改name</button> -->

    <h2>{{ state.name }}</h2>
    <button @click="changeState">修改 reactive 数据类型</button>
  </div>
</template>

<script setup>

import { ref, watch, reactive } from 'vue';
// watch 作用 => 时刻监听数据的改变(响应式数据)
// 语法:watch(数据源,处理函数,配置项)
// 配置项:immediate:true; 首次加载默认监听
// deep:true;监听深度的数据


// // 案例一: 监听数据 ref 类型
// let age=ref(20);
// let name=ref("lisa");

// watch(age,(newVal,oldVal)=>{
//   console.log(newVal,oldVal); // 数据改变会触发次函数的执行
// })
// const changeAge = ()=>{
//     age.value =age.value +1;
//  }
//  const changeName =()=>{
//     name.value='小明'
//  }


//  案例2:通过watch 监听某个数据 首次监听到
//添加配置项  immediate:true =》首次监听到
// 监听的深度的数据 =》 deep:true
//       let state = reactive({
//         name:'张三',
//         age:100,
//         like:{eat:'吃'}
//      })
//    watch( ()=>state.like,(newVal,oldVal)=>{
//         console.log(newVal,oldVal);
//       },{
//         immediate:true,
//         deep:true
//       })
//      const changeState = ()=>{
//          state.like.eat='小红'
//      }
//      const changeAge = ()=>{
//         age.value +=1
//      }


// 案例3:watch =>监听多个数据

let age = ref(29)

let state = reactive({
  name: '张三',
  age: 100
})

watch([age, () => state.name], ([newA, newN], [oldA, oldN]) => {
  console.log(newA, oldA);
  console.log(newN, oldN);
})
const changeState = () => {
  state.name = '小红'
}
const changeAge = () => {
  age.value += 1
}

//总结 watch


//作用监听 响应式数据


// 特点
// 1默认 第一次不执行,如果需要理解执行添配置项
// 2监听多个数据源
// 3 处理异步问题

//watchEffect 和watch 相同的点和不同点

// 相同点
// 都可以时时刻刻监听某个数据改变,处理异步问题,都可以监听多个数据


//不同点
// watchEffect 默认立即执行 ,watchEffect 只能获取到最新的数据
// watch 默认不立即执行,watch 获取 到新旧数据

</script>

<style>

</style>

 6、computed() 计算属性

  作用:后端给的数据不是自己想要的,通过计算属性,把自己数据处理成自己想要的

  写法:1. 默认:只用get方法,语法:let 想要的数据=computed({return 计算后的数据 });

     2. get 和set 方式:let 想要的数据=computed({get:()=>{return}, set:(value)=>{}})

  特点:1. 可以时时刻刻监听数据,根据这个数据,得到我们需要的数据;2. 只能写同步方法

<template>
  <div>
    <h2>计算属性computed</h2>
    <!-- 
      作用:计算属性
      1 什么时候使用这个计算属性
          后端给的数据,不是自己想要的,通过计算属性,把这个数据处理成自己想要的
      2 语法: let 需要的数据=computed(()=>{})
     -->
     <h2>计算出实际薪资{{total}}</h2>
  </div>
</template>

<script setup>
  import {ref,computed} from 'vue';

  // 后端给的一个数据
  let salary=ref(0);
  const getData=()=>{
    setTimeout(()=>{
      // 后端给的数据 没有实际的数据
      salary.value=2000;
    },500);
  }
  getData();

  // // 计算属性的用法: 1 get 属性
  // let total=computed(()=>{
  //   // 处理逻辑 +200
  //   return salary.value+200;
  // })


  // 用法2: 具有set 和 get 属性

  // 1 什么时候触发get 方法 => 获取这个计算属性的放回置的时候 触发 get方法
  // 2 什么时候触发set 方法 => 修改值得时候触发set方法
  let total=computed({
    get:()=>{
      console.log("获取的时候触发");
      return salary.value+1000;
    },
    set:(value)=>{// 第一个参数:设置的值
      console.log("设置值的时候触发",value);  // 设置total的时候触发这个方法
      // 1 通过计算属性get方法 计算出我们需要的数据
      // 2 当这个值为 某个值的时候,有需要进行逻辑处理,得到一个新的计算属性的值
      setTimeout(()=>{
        if(value>=3200){
          salary.value=salary.value-200
        }
      },1000)
    }
  })

  console.log(total);
    total.value=6000; 
    // 计算属性的特点:
    // 1 计算属性不能处理异步数据
    // 2 时时刻刻观察 我们需要处理的动态数据
</script>

<style>

</style>

 

 

响应式:工具

1、toRefs()

  本质:就是将reactive代理对象数据中的属性,属性值 变为 ref处理的数据

  语法:toRefs(reactive响应式数据)

<template>
  <div>
    <h2>{{name}}</h2>
    <h2>{{age}}</h2>
  
    <button @click="addAge">addAge</button>
  </div>
  
</template>

<script setup>
  import {reactive,toRefs} from 'vue';
  
//   let {age,name}=reactive({
//     name:"小明",
//     age:8,
//     like:{eat:'🍎',play:['⚽']}
//   })
// // 直接结构 reactive 响应式数据 => 他的数据不再是响应式数据
//    const addAge=()=>{
//       age=age+1;    // 无法修改
//   }

let objP=reactive({
    name:"小明",
    age:8,
    like:{eat:'🍎',play:['⚽']}
  })
//   我想在视图中直接使用 name,age 和ref 一样
// 本质就是将reactive 代理,对象数据中的属性,值变成ref处理的数据
// 使用vue3中的响应式api => toRefs

// 语法: toRefs(reactive响应式数据)
let {age,name}=toRefs(objP);

const addAge=()=>{
      age.value+=1;    // 无法修改
  }
</script>

<style>

</style>

2、toRef()

  作用:将reactive代理的数据(这个数据必须是一个对象)中的某个属性变为ref代理

  语法:let ref值=toRef(目标对象,属性)

  toRefs() 和 toRef() 的区别:toRefs()是把对像中的所有的属性,变成ref进行代理;   toRef()是把reactive中的某个属性,变成ref 进行代理

<template>
    <div>
        <h2>toRef</h2>
        <!-- 
            作用:就是将reactive代理的数据,这个数据必须是一个对象,中的某个属性变成ref 代理
            语法:let ref值=toRef(目标对象,属性)
         -->
         <h2>{{stateAge}}</h2>
    </div>
</template>

<script setup>
    
    import {toRef,reactive} from 'vue'
    let state=reactive({
        age:20,
        name:"lisa",
    })

    let stateAge=toRef(state,'age');
    console.log(stateAge);
</script>

<style>

</style>

 

 3、isRef()、isReactive()、isReadonly()、isProxy()

  作用:判断这个变量是不是被这个isxxx这个方法处理了,返回值为布尔值,是就为true,不是就为false

<template>
    <div>
         <!--   响应式api工具
            isRef => 
            isReactive
            isReadonly
            isxxx => 判断 这个变量是不是被这个isxxx这个方法处理了,是true,不是false
            
          -->
    </div>
</template>

<script setup>
    
    import {ref,isRef,isReadonly} from 'vue'

    let money = ref(1000)   // ref 代理了

    let obj={name:"lisa"}
    console.log(isRef(money));    // 判断这个变量是不是ref代理的    // false
    console.log(isReadonly(obj));   // false
</script>

<style>

</style>

 

响应式:进阶

1、shollowRef()、shallowReactive()、shallowReadonly()

  作用:第一层有这个方法的 功能,只作用于第一层

  shollowRef() 第一层的数据是响应式、shallowReactive()第一层的数据是响应式、shallowReadonly() 第一层的数据是只读

<template>
    <div>
        <h2>shallowReactive</h2>
        <!-- 
            shallowReactive => 第一层的数据是响应式
            shallowRef => 第一层的数据是响应式
            shallowReadonly => 第一层的数据是只读的
            作用:浅的,只作用于数据的第一层
         -->
         <h2>{{state.name}}</h2>
         <h2>{{state.like.eat}}</h2>
         <button @click="change">改变state
        第一层中的数据</button>
        <button @click="changeTwo">改变state
        第二层中的数据</button>
        <button @click="changeAll">同时改变state
        第一层和第二层中的数据</button>

        <h3>{{ objs.name }}</h3>
        <h3>{{  objs.like.eat }}</h3>
        <button @click="changeR">改变state
        第二层中的数据</button>
    </div>
</template>

<script setup>
    
    import {shallowReactive,reactive,toRefs,shallowReadonly} from 'vue';

    let state=shallowReactive({
        age:20,
        name:"lisa",
        like:{eat:"🍎"}
    })

    const change=()=>{
        state.name="andy";
        
    }
    const changeTwo=()=>{
        state.like.eat= "🍍";   // 单独是无法修改的,因为它不是第一层数据,不是响应式的数据
    }
    const changeAll=()=>{
        state.name="andy";
        state.like.eat= "🍍";   // 添加第一层数据,同时改变,第二层也变成了响应式的数据
    }

       //readonly
       let objs = shallowReadonly({
           name:'小明',
           like:{eat:'🍉'}
       })

       const changeR =()=>{
        // objs.name="cici";//无法修改,因为这里的第一层是只读的
        objs.like.eat='🍇'; // 这里是可以改变的,因为shallowReadonly只作用于第一层,但是它不是响应式的,无法同步视图更新
        console.log(objs.like.eat); //  🍇
       }


       // shallowRef() 同理
  
</script>

<style>

</style>

 

posted on 2023-01-07 01:21  chccee  阅读(208)  评论(0编辑  收藏  举报