美文网首页
[前端开发] Vue3 +Typescript 工作笔记

[前端开发] Vue3 +Typescript 工作笔记

作者: 杨山炮 | 来源:发表于2023-03-11 16:29 被阅读0次
    image.png

    特殊文件夹说明:

    • types 定义一些Typescript 数据约束
    • use 组合是函数的统一管理 ,文件名默认以use开头

    Vue3一些新特性

    • Composition API

      • 创建响应式对象的方式: ref 、toRef、toRefs、reactive
        • ref() 函数根据给定的值创建一个响应式的数据对象,传入的为基本数据类型,例如字符串、数字、boolean 等,返回值是一个对象,这个对象上只包含一个 value 属性,只在setup函数内部访问ref函数需要加.value
        • reactive 方法 根据传入的对象 ,创建返回一个深度响应式对象
        • 针对一个响应式对象(reactive 封装)的 prop(属性)创建一个ref,且保持响应式
        • toRefs 是一种用于破坏响应式对象并将其所有属性转换为 ref 的实用方法
      import {ref, reactive, toRef, toRefs} from 'vue';
      export default {
      name:'App'
      setup(){
       let stringRef = ref("");
       let obj = {name : 'alice', age : 12};
       let reactiveRef = reactive(obj)
       let objNameToRef= toRef(obj, 'name');
       let objToRefs = toRefs(reactiveRef )
         return {stringRef ,reactiveRef ,objNameToRef,...objToRefs }
       }
      }
      
    • watchEffect && watch 区别

    1.watch可以访问新值和旧值,watchEffect不能访问。
    2.watchEffect有副作用,DOM挂载或者更新之前就会触发,需要我们自己去清除副作用。
    3.watch是惰性执行,也就是只有监听的值发生变化的时候才会执行,但是watchEffect不同,每次代码加载watchEffect都会执行。
    4.watch需要指明监听的对象,也需要指明监听的回调。watchEffect会立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。

    import {ref, reactive, toRef, toRefs} from 'vue';
    export default {
        name:'App'
        setup(){
         let obj = {name : 'alice', age : 12};
         let reactiveRef = reactive(obj)
         watch(()=>reactiveRef .name,(old,newVal)=>{},{deep:true})
         watch([()=>reactiveRef .name,()=>reactiveRef.age],(old,newVal)=>{},{deep:true})
        }
    } 
    
    import type { UnwrapRef,Ref  } from 'vue'
    import { ref } from 'vue'
    #useLoading.js
    export function useLoading(initState: boolean): [Ref<boolean>, () => void] {
      const state = ref(initState)
      const toggleLoading = function () {
        state.value = !state.value
      }
      return [state, toggleLoading]
    }
    #useAsync.js
    export function useAsync<T>(asyncFn: () => Promise<T>, initValue: T, immediate = true) {
      const [toggleLoading] = useLoading(false)
      const data = ref(initValue)
      const error = ref(null)
      const execute = function () {
        toggleLoading()
        error.value = null
        return asyncFn()
          .then((res) => {
            data.value = res as UnwrapRef<T>
            toggleLoading()
          })
          .catch((err) => {
            error.value = err
            toggleLoading()
          })
      }
      if (immediate) {
        execute()
      }
      return {
        pending,
        data,
        error,
        execute,
      }
    }
    

    UnwrapRef<T>类型,就是对Ref类型就行反解

    • 内置组件Teleport
      <Teleport> 是一个内置组件,它可以将一个组件内部的一部分模板“传送”到该组件的 DOM 结构外层的位置去。
    <template>
    <button @click="open = true">Open Modal</button>
    
    <Teleport to="body">
      <div v-if="open" class="modal">
        <p>modal将会被插入到body下面</p>
        <button @click="open = false">Close</button>
      </div>
    </Teleport>
    </template>
    
    • 异步组件
      vue2
    const asyncPage = () => import('./Lazy.vue')
    

    https://cn.vuejs.org/guide/components/async.html#loading-and-error-states

    Vue3

    <script>
    import { defineAsyncComponent } from 'vue'
    export default {
      components: {
        AdminPage: defineAsyncComponent(() =>
          import('./components/AdminPageComponent.vue')
        )
      }
    }
    </script>
    <template>
      <AdminPage />
    </template>
    

    Typescript在Vue3中的一些用法

    • 自定义事件、属性 defineEmits、defineProps
    <script setup lang="ts">
    import { defineProps, defineEmits } from 'vue'
    
    interface IProps {
      showAction?: boolean
      background?: string
      placeholder?: string
      shape?: string
      modelValue?: string | number
    }
    const props = defineProps<IProps>()
    
    interface IEmits {
      (e: 'search', v?: string | number): void
      (e: 'cancel'): void
      (e: 'clear'): void
      (e: 'update:modelValue', v?: string | number): void
      (e: 'inputClick'): void
    }
    const emits = defineEmits<IEmits>()
    
    const onKeypress = (e: KeyboardEvent) => {
      const ENTER_CODE = 13
      if (e.keyCode === ENTER_CODE) {
        e.preventDefault()
        emits('search', props.modelValue)
      }
    }
    const onClear = () => {
      emits('update:modelValue', '')
      emits('clear')
    }
    </script>
    <template>
    <input
      type="search"
      class="op-field__control"
      :value="modelValue"
      :placeholder="placeholder"
      @keypress="onKeypress"
      @click="emits('inputClick')"
      @input="(e) => emits('update:modelValue', (e.target as HTMLInputElement).value)"
    />
    </template>
    

    Pinia用法

    • defineStore定义仓库
    import {defineStore} from "pinia";
    export const userStore =  defineStore('user',{
      state:()=>{return{
         name:""
     }},
      getters:{},
      actions:{
       updateUser(name){
        this.name = name
       }
      }
    })
    
    • storeToRefs()读取state
    import {storeToRefs} from 'pinia'
    let user = userStore()
    const {name} = storeToRefs(user)
    
    • patch 函数修改state
    • Action通过函数更改state
    • store 的 $reset() 方法将 state 重置为初始值。
    • 通过 store 的 $subscribe() 方法侦听 state 及其变化
    cartStore.$subscribe((mutation, state) => {
      // import { MutationType } from 'pinia'
      mutation.type // 'direct' | 'patch object' | 'patch function'
      // 和 cartStore.$id 一样
      mutation.storeId // 'cart'
      // 只有 mutation.type === 'patch object'的情况下才可用
      mutation.payload // 传递给 cartStore.$patch() 的补丁对象。
    
      // 每当状态发生变化时,将整个 state 持久化到本地存储。
      localStorage.setItem('cart', JSON.stringify(state))
    })
    

    问题:类型“ImportMeta”上不存在属性“env”。

    在 tsconfig.json 文件中添加如下配置即可
    “types”: [ “vite/client” ]

    相关文章

      网友评论

          本文标题:[前端开发] Vue3 +Typescript 工作笔记

          本文链接:https://www.haomeiwen.com/subject/wvmxrdtx.html