Vue3学习笔记

149 阅读8分钟

第三阶段:vue3的学习与实战

Day91.Vue3的优势:
    1.更容易维护:
        1.组合式API
        2.更好的TypeScript支持
    2.更快的速度:
        1.重写diff算法
        2.模版编译优化
        3.更高效的组件初始化
    3.更小的体积:
        1.良好的Treeshaking
        2.按需引入
    4.更优的数据响应式:
        Proxy
   

2.Vue3 组合式APIvs Vue2 选项式 API

需求:点击按钮,让数字 +1
  <script>
    export default {
      data () {
        return {
        count:0
      }
    },
    methods: {
      addCount (){
        this.count++
        }
      }
    }
  </script>

  <script setup>
      import { ref } from 'vue'
      const count = ref(0)
      const addCount = () => count.value++
  </script>
1.代码量变少了
2.分散式维护转为集中式维护,更易封装复用

3.项目目录和关键文件

   1.关键文件:
    1.vite.config.js-项目的配置文件 基于vite的配置
    2.package.json-项目包文件 核心依赖项变成了 Vue3.x和 vite
    3.main.js-入口文件 createApp函数创建应用实例
    4.app.vue-根组件 SFC单文件组件 script-template-style
        变化-:脚本script和模板template顺序调整
        变化二:模板template不再要求唯一根元素
        变化三:脚本script添加setup标识支持组合式API
    5.index.html-单页入口 提供id为app的挂载点

4.setup选项中写代码的特点

<template>
    <!-- 使用数据和方法-->
    {{ message }}
    <button @click="logMessage">
        log message
    </button>
</template>

5. script setup语法糖

1.原始复杂写法
    <script>
      export default {
        setup (){
        // 数据
        const message = 'this is message'
        // 函数
        const logMessage = () => {
          console.log(message)
        }
        return {
          message,
          logMessage
        }
      }
    }
    </script>
2.语法糖写法
    <script setup>
      // 数据
      const message ='this is message
      // 函数
      const logMessage = () =>{
        console.log(message)
      }
    </script>
3.总结
    1.setup选项的执行时机?
        beforecreate钩子之前 自动执行
    2.setup写代码的特点是什么?
        定义数据+函数 然后以对象方式return
    3.<script setup>解决了什么问题?
        经过语法糖的封装更简单的使用组合式API
    4.setup中的this还指向组件实例吗?
        指向undefined

6.

1.reactive()
    1.作用:接受对象类型数据的参数传入并返回一个响应式的对象
    2.核心步骤:
        <script setup>
          // 导入
          import { reactive } from 'vue'
          
          // 执行函数 传入参数 变量接收5
          const state = reactive(对象类型数据)
        </script>
        1. 从 vue 包中导入 reactive 函数
        2.在 <script setup>中执行 reactive 函数并传入类型为对象的初始值,并使用变量接收返回值
2.ref()
    1.作用:接收简单类型或者对象类型的数据传入并返回一个响应式的对象
    2.核心步骤:<script setup>
              // 导入
              import { ref } from 'vue'
              // 执行函数 传入参数 变量接收
              const count = ref(简单类型或者复杂类型数据)
            </script>
        1.从 vue 包中导入 ref 函数
        2.在<script setup>中执行 ref 函数并传入初始值,使用变量接收 ref 函数的返回值
3.总结
    1.reactive和ref函数的共同作用是什么?
        用函数调用的方式生成响应式数据
    2. reactive vs ref ?
        1.reactive不能处理简单类型的数据
        2.ref参数类型支持更好但是必须通过.value访问修改
        3.ref函数的内部实现依赖于reactive函数
    3.在实际工作中推荐使用哪个?
        推荐使用ref函数,更加灵活统一

7.computed计算属性函数

计算属性基本思想和Vue2的完全一致,组合式API下的计算属性只是修改了写法
核心步骤:1.导入computed函数
        2.执行函数 在回调参数中return基于响应式数据做计算的值,用变量接收
            <script setup>
              // 导入
              import { computed }from 'vue'
              // 执行函数 变量接收 在回调参数中return计算值
              const computedState = computed(() => {
                return 基于响应式数据做计算之后的值
              })
            </script>
3.总结
    最佳实践
        1.计算属性中不应该有“副作用”
            比如异步请求/修改dom
        2.避免直接修改计算属性的值
            计算属性应该是只读的,特殊情况可以配置 get set
  

8.watch函数

1.作用:侦听一个或者多个数据的变化,数据变化时执行回调函数
2.俩个额外参数:1.immediate(立即执行)2.deep(深度侦听)
    1.基础使用-侦听单个数据
        1.导入watch函数
        2.执行watch函数传入要侦听的响应式数据(ref对象)和回调函数
            <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>
    2.immediate
        说明:在侦听器创建时立即触发回调,响应式数据变化之后继续执行回调
            const count =ref(0)
            watch(count, () => {
              console.log('count发生了变化')
            }, {
            immediate: true
            })
    3.精确侦听对象的某个属性
        需求:在不开启deep的前提下,侦听age的变化,只有age变化时才执行回调
            const info = ref({
              name :'cp'
              age: 18
            })
            
            watch(
              () => info.value.age,
              () => console.log('age发生变化了')
            )
    4.总结
        1.作为watch函数的第一个参数,ref对象需要添加.value吗?
            不需要,第一个参数就是传 ref 对象
        2.watch只能侦听单个数据吗?
            单个 或者 多个
        3.不开启deep,直接监视 复杂类型,修改属性 能触发回调吗?
            不能,默认是浅层侦听
        4.不开启deep,精确侦听对象的某个属性?
            可以把第一个参数写成函数的写法,返回要监听的具体属性

9.Vue3的生命周期API(选项式 VS 组合式)

选项式API                       组合式API
  beforeCreate/created            setup
  beforeMount                     onBeforeMount
  mounted                         onMounted
  beforeUpdate                    onBeforeUpdate
  updated                         onUpdated
  beforeUnmount                   onBeforeUnmount
  unmounted                       onUnmounted
1.组合式API下的父传子
    1.基本思想
        1.父组件中给子组件绑定属性
        2.子组件内部通过props选项接收
    2.defineProps 原理:就是编译阶段的一个标识,实际编译器解析时,遇到后会进行编译转换
    3.总结
      父传子
        1.父传子的过程中通过什么方式接收props?
            defineProps({属性名:类型})
        2.setup语法糖中如何使用父组件传过来的数据?
            const props=defineProps({属性名:类型})
            props.xxX

      子传父
        1.子传父的过程中通过什么方式得到emit方法?
            defineEmits(「'事件名称’)
        2.怎么触发事件
            emit('自定义事件名'参数)

10.如何使用(以获取dom为例 组件同理)

<script setup>
    import { ref } from 'vue'
    //1.调用ref函数得到ref对象
    const h1Ref = ref(null)
</scrip>

<templat>
    <!-- 2.通过ref标识绑定ref对象 -->
    <h1 ref="h1Ref">我是dom标签h1</h1>
</template>
    1.调用ref函数生成一个ref对象
    2.通过ref标识绑定ref对象到标签
3.总结
    1.获取模板引用的时机是什么?
        组件挂载完毕
    2.defineExpose编译宏的作用是什么?
        显式暴露组件内部的属性和方法

11.

1.跨层传递普通数据
1.顶层组件通过provide函数提供数据
2.底层组件通过inject函数获取数据
    顶层组件:provide('key',顶层组件中的数据)
    底层组件:const message = inject('key')

2.跨层传递响应式数据
在调用provide函数时,第二个参数设置为ref对象
    顶层组件:provide('app-key',ref对象)
    底层组件:const message =inject('app-key')

3.跨层传递方法
顶层组件可以向底层组件传递方法,底层组件调用方法修改顶层组件中的数据
    顶层组件:const setCount = () => {
              count.value++
            }
            provide('setCount-key', setCount)
    底层组件:const setCount = inject('setCount-key')

12.Vue3.3新特性-defineoptions

1.背景说明:
    1.有<script setup>之前,如果要定义 props,emits 可以轻而易举地添加一个与 setup 平级的属性。
    2.但是用了 <script setup>后,就没法这么干了 setup 属性已经没有了,自然无法添加与其平级的属性。
2.为了解决这一问题,引入了 defineProps 与 defineEmits 这两个宏。但这只解决了 props 与 emits 这两个属性。
    1.如果我们要定义组件的 name 或其他自定义的属性,还是得回到最原始的用法--再添加一个普通的 <script>标签
    2.这样就会存在两个<script>标签。让人无法接受,
3.所以在 Vue 3.3 中新引入了 defineOptions 宏。顾名思义,主要是用来定义 Options AP!的选项。可以用defineOptions 定义任意的选项,props,emits,expose,slots 除外(因为这些可以使用 defineXXX 来做到)

13.Vue3 中的v-model和 defineModel

在vue3中,自定义组件上使用v-mode1,相当于传递一个modelValue属性,同时触发 update:modelValue 事件
    <Child v-model="isVisible">
    // 相当于
    <Child :modelValue="isVisible" @update:modelValue="isVisible=$event">
我们需要先定义 props,再定义 emits 。其中有许多重复的代码。如果需要修改此值,还需要手动调
    <script setup>
        const modelValue = defineModel()
        modelValue .value++
    </script>

14.什么是Pinia

        1.PiniaVue 的最新 状态管理工具 ,是 Vuex 的 替代品
    1.提供更加简单的API(去掉了 mutation)
    2.提供符合,组合式风格的API(和 Vue3 新语法统一)
    3.去掉了 modules 的概念,每一个 store 都是一个独立的模块
    4.配合 TypeScript 更加友好,提供可靠的类型推断
2.手动添加PiniaVue项目
    在实际开发项目的时候,关于Pinia的配置,可以在项目创建时自动添加现在我们初次学习,从零开始:
        1.使用 Vite 创建一个空的 Vue3 项目
            npm create vue@latest
        2.按照官方文档 安装 pinia 到项目中
3.action异步实现
    1.编写方式:异步action函数的写法和组件中获取异步数据的写法完全一致
    2.接口地址:http://geek.itheima.net/v10/channels
    3.需求:Pinia中获取频道列表数据并把数据渲染App组件的模板中
4.总结
    1. Pinia是用来做什么的?
        新一代的状态管理工具,替代vuex
    2.Pinia中还需要mutation吗?
        不需要,action 既支持同步也支持异步
    3Pinia如何实现getter?
        computed计算属性函数
    4.Pinia产生的Store如何解构赋值数据保持响应式?
        storeToRefs
    5.Pinia 如何快速实现持久化?
        pinia-plugin-persistedstate