Vue3.3指北(三)

Vue3.3指北

  • 1、Vue2和Vue3
    • 1.1、 Vue2 选项式 API vs Vue3 组合式API
    • 1.2、Vue3的优势
  • 2、组合式API - setup
    • 2.1、setup选项
    • 2.2、setup中写代码的特点
    • 2.3、`
      • 执行时机

      在beforeCreate钩子之前执行

      Vue3.3指北(三)_第1张图片

      2.2、setup中写代码的特点

      • setup函数中写的数据和方法需要在末尾以对象的方式return,才能给模版template使用
      
      

      2.3、

      示例:我们在模板里面应用 setup() 函数里面的东西

      <script>
          // 1.创建Vue的实例对象
          const app = Vue.createApp({
      
              setup(props,context) {
                  const message = 'this is message';
                  const logMessage = ()=>{
                      console.log(message);
                  };
                  return {
                      message,
                      logMessage
                  }
              },
      
              // 我们在模板里面应用 setup() 函数里面的东西
              template: `
              

      {{message}}

      `
      }); app.mount('#app'); </script>

      2.4、props和context

      • setup 里接收的参数是 propscontext
      // 声明时props和setup同级,可以通过以下方式对父组件传递的参数在props中声明
      props:{
          msg:String,
          name:String
      },
      
      • context 上下文包括 attrsemitslots
        • attrs :接收在父组件传递过来的,并且没有在props中声明的参数
        • emit :子组件对父组件发送事件
        • slots :插槽

      在vue2中,子对父发送事件采用this.$emit对父组件发送事件,在vue3中子组件对父组件发送事件采用context.emit发送事件

      import { ref } from 'vue';
       
      export default {
        props: {
          message: String
        },
        setup(props, context) {
          const count = ref(0);
       
          // 使用props
          console.log(props.message);
       
          // 使用context
          console.log(context.attrs);
          console.log(context.slots);
          console.log(context.emit);
       
          return {
            count
          };
        }
      };
      

      在上面的示例中,我们使用了propscontext参数来获取组件的属性、插槽和触发事件的方法。

      需要注意的是,setup()函数在组件初始化期间只会执行一次,并且在datacomputed等选项之前执行。

      3、组合式API - reactive和ref函数

      3.1、reactive

      • 接受对象类型数据的参数传入并返回一个响应式的对象
      <script setup>
       // 导入
       import { reactive } from 'vue'
       // 接收对象类型
       const state = reactive({
         msg:'this is msg'
       })
       const setSate = ()=>{
         // 修改数据更新视图
         state.msg = 'this is new msg'
       }
      script>
      
      <template>
        {{ state.msg }}
        <button @click="setState">change msgbutton>
      template>
      

      3.2、ref

      • 接收简单类型或者对象类型的数据传入并返回一个响应式的对象
        • 让基础类型的数据具备响应式(有点像v-model双向绑定数据的感觉)
      <script setup>
       // 导入
       import { ref } from 'vue'
       // 执行函数 传入参数 变量接收
       const count = ref(0)
       const setCount = ()=>{
         // 修改数据更新视图必须加上.value
         count.value++
       }
      script>
      
      <template>
        <button @click="setCount">点击增加button>
      template>
      

      Tips:

      • 需要注意的是使用ref参数类型修改数据必须加上 .value

      3.3、reactive 对比 ref

      相同点:

      • 都是用来生成响应式数据

      不同点

      1. reactive不能处理简单类型的数据
      2. ref参数类型支持更好,但是必须通过.value做访问修改
      3. ref函数内部的实现依赖于reactive函数

      在实际工作中的推荐

      • 推荐使用ref函数,减少记忆负担

      4、组合式API - computed

      计算属性基本思想和Vue2保持一致,组合式API下的计算属性只是修改了API写法

      • computed()方法返回值是个计算属性ref对象,在模板中使用也是会自动解包的
      • 它的参数是一个回调函数,也就是箭头函数
      <script setup>
      // 导入
      import {ref, computed } from 'vue'
      // 原始数据
      const count = ref(0)
      // 计算属性
      const doubleCount = computed(()=>count.value * 2)
      
      // 原始数据
      const list = ref([1,2,3,4,5,6,7,8])
      // 计算属性list
      const filterList = computed(item=>item > 2)
      script>
      

      5、组合式API - watch

      • 侦听一个或者多个数据的变化,数据变化时执行回调函数
      • 三个参数
        • 第一个参数是:选择要监听的属性选择要监听的属性
        • 第二个参数是:设置的回调函数。即监听到变化时应该执行的函数
        • 第三个参数是配置项
          • immediate 控制立刻执行
          • deep开启深度侦听

      5.1、侦听单个数据

      <script setup>
        // 1. 导入watch
        import { ref, watch } from 'vue'
        const count = ref(0)
        // 2. 调用watch 侦听变化
        watch(count, (newValue, oldValue)=>{
          console.log(`count发生了变化,老值为${oldValue},新值为${newValue}`)
        })
      script>
      

      5.2、侦听多个数据

      • 侦听多个数据,第一个参数可以改写成数组的写法
      <script setup>
        // 1. 导入watch
        import { ref, watch } from 'vue'
        const count = ref(0)
        const name = ref('cp')
        // 2. 调用watch 侦听变化
        watch([count, name], ([newCount, newName],[oldCount,oldName])=>{
          console.log(`count或者name变化了,[newCount, newName],[oldCount,oldName])
        })
      script>
      

      5.3、immediate

      在侦听器创建时立即出发回调,响应式数据变化之后继续执行回调

      <script setup>
        // 1. 导入watch
        import { ref, watch } from 'vue'
        const count = ref(0)
        // 2. 调用watch 侦听变化
        watch(count, (newValue, oldValue)=>{
          console.log(`count发生了变化,老值为${oldValue},新值为${newValue}`)
        },{
          immediate: true
        })
      script>
      

      5.4、deep

      • 通过watch监听的ref对象默认是浅层侦听的,直接修改嵌套的对象属性不会触发回调执行,需要开启deep
      <script setup>
        // 1. 导入watch
        import { ref, watch } from 'vue'
        const state = ref({ count: 0 })
        // 2. 监听对象state
        watch(state, ()=>{
          console.log('数据变化了')
        })
        const changeStateByCount = ()=>{
          // 直接修改不会引发回调执行
          state.value.count++
        }
      script>
      
      <script setup>
        // 1. 导入watch
        import { ref, watch } from 'vue'
        const state = ref({ count: 0 })
        // 2. 监听对象state 并开启deep
        watch(state, ()=>{
          console.log('数据变化了')
        },{deep:true})
        const changeStateByCount = ()=>{
          // 此时修改可以触发回调
          state.value.count++
        }
      script>
      

      6、组合式API - watchEffect

      watchEffect 也是一个帧听器,是一个副作用函数。 它会监听引用数据类型的所有属性,不需要具体到某个属性,一旦运行就会立即监听,组件卸载的时候会停止监听。

      6.1、基本使用

      <template>
        <div>
          <h2>{{ counter }}</h2>
          <button @click="addCounter">+1</button>
        </div>
      </template>
      
      <script >
      import { ref, watchEffect } from 'vue';
      
      export default{
        setup() {
          const counter = ref(100)
      
          const addCounter = () => counter.value++
      
          watchEffect(() => {
            console.log("counter:", counter.value);
          })
      
          return {
            counter,
            addCounter
          }
        }
      }
      
      </script>
      

      watchEffect会默认执行一次,当有变量发生变化,就会执行侦听

      6.2、watchEffect的其他参数

      watchEffect会返回一个返回值,该返回值是一个函数,在满足条件的时候触发返回值函数。我们可以利用这个返回值做一些操作

      6.2.1、stop停止侦听

      这里我们想要实现计数器增加到15的时候停止侦听:

      <template>
        <div>
          <h2>{{ counter }}</h2>
          <button @click="addCounter"> +1 </button>
        </div>
      </template>
      
      <script >
      import { ref, watchEffect } from 'vue';
      
      export default{
        setup() {
          const counter = ref(10);
      
          const addCounter = () => {
            counter.value++;
            if(counter.value >= 15){
                stop();
            }
          };
      
          const stop = watchEffect(() => {
            console.log("counter:", counter.value);
          });
      
          return {
            counter,
            addCounter
          };
        }
      }
      
      </script>
      

      Vue3.3指北(三)_第2张图片

      stop()接收watchEffect的返回值,在手动触发计数器到15之后不再侦听变量的改变。

      6.2.2、onInvalidate消除副作用

      我们做一个假设,假设我们需要根据counter的值去触发对应的网络请求,但是在请求数据的过程中,我们再次触发方法改变了counter的值,我们该如何做才能让每次请求回来的都是正确的数据呢?

      我们也可以这么想,也就是我们只要改变了counter的值,就需要清除上一次的请求,重新执行一次请求。

      watchEffect中有一个参数onInvalidate 可以作为消除副作用,它会返回一个函数

      <template>
        <div>
          <h2>{{ counter }}</h2>
          <button @click="addCounter">+1</button>
        </div>
      </template>
      
      <script >
      import { ref, watchEffect } from 'vue';
      
      export default{
        setup() {
          const counter = ref(10)
      
          const addCounter = () => {
            counter.value++
          }
      
          watchEffect( onInvalidate => {
            onInvalidate(() => {
              console.log("onInvalidate");
            })
            console.log("counter:", counter.value);
          })
      
          return {
            counter,
            addCounter
          }
        }
      }
      
      </script>
      

      Vue3.3指北(三)_第3张图片

      7、组合式API - 父子通信

      7.1、父传子

      如果是setup函数的形式,props 必须以 props 选项的方式声明,props 对象会作为 setup() 函数的第一个参数被传入

      • 在vue3中,只要props这个参数存在,我们就可以直接mustache中使用父组件传递的参数

      基本思想

      1. 父组件中给子组件绑定属性
      2. 子组件内部通过props选项接收数据

      父组件App.vue

      <script setup>
      // 引入子组件
      import sonComVue from './son-com.vue';
      script>
      
      <template>
        
        <sonComVue message="this is app message" />
      template>
      

      子组件son-com.vue

      <script setup>
        // 2.通过 defineProps 接收子组件传递的数据
        const props = defineProps({
          message: String
        })
      
      script>
      
      <template>
          
        {{message}}
      template>
      

      在使用

你可能感兴趣的:(vue.js,前端,javascript)