1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        關(guān)于 vue3 + typescript 項目中常用的知識點匯總

        共 16412字,需瀏覽 33分鐘

         ·

        2021-07-19 05:57

        作者:FinGet

        https://juejin.cn/post/6980267119933931551

        創(chuàng)建項目

        image.png

        基礎(chǔ)語法

        定義data

        • script標簽上lang="ts"
        • 定義一個類型type或者接口interface來約束data
        • 可以使用ref或者toRefs來定義響應(yīng)式數(shù)據(jù)
        • 使用refsetup讀取的時候需要獲取xxx.value,但在template中不需要
        • 使用reactive時,可以用toRefs解構(gòu)導(dǎo)出,在template就可以直接使用了
        <script lang="ts">
        import { defineComponent, reactive, ref, toRefs } from 'vue';

        type Todo = {
          id: number,
          name: string,
          completed: boolean
        }

        export default defineComponent({
          const data = reactive({
            todoList: [] as Todo[]
          })
          const count = ref(0);
          console.log(count.value)
          return {
            ...toRefs(data)
          }
        })
        </script>
        復(fù)制代碼

        定義props

        props需要使用PropType泛型來約束。

        <script lang="ts">
        import { defineComponent, PropType} from 'vue';

        interface UserInfo = {
          id: number,
          name: string,
          age: number
        }

        export default defineComponent({
          props: {
            userInfo: {
              typeObject as PropType<UserInfo>, // 泛型類型
              required: true
            }
          },
        })
        </script>
        復(fù)制代碼

        定義methods

        <script lang="ts">
        import { defineComponent, reactive, ref, toRefs } from 'vue';

        type Todo = {
          id: number,
          name: string,
          completed: boolean
        }

        export default defineComponent({
          const data = reactive({
            todoList: [] as Todo[]
          })
          // 約束輸入和輸出類型
          const newTodo = (name: string):Todo  => {
            return {
              id: this.items.length + 1,
              name,
              completed: false
            };
          }
          const addTodo = (todo: Todo): void => {
            data.todoList.push(todo)
          }
          return {
            ...toRefs(data),
            newTodo,
            addTodo
          }
        })
        </script>
        復(fù)制代碼

        vue-router

        • createRouter創(chuàng)建router實例
        • router的模式分為:
        • createWebHistory -- history模式
        • createWebHashHistory -- hash模式
        • routes的約束類型是RouteRecordRaw
        import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
        import Home from '../views/Home.vue';
        const routes: Array< RouteRecordRaw > = [
          {
            path: '/',
            name: 'Home',
            component: Home,
          },
          {
            path: '/about',
            name: 'About',
            component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
          }
        ];

        const router = createRouter({
          history: createWebHistory(process.env.BASE_URL),
          routes
        });

        export default router;
        復(fù)制代碼

        擴展路由額外屬性

        在實際項目開發(fā)中,常常會遇到這么一個場景,某一個路由是不需要渲染到側(cè)邊欄導(dǎo)航上的,此時我們可以給該路由添加一個hidden屬性來實現(xiàn)。

        在ts的強類型約束下,添加額外屬性就會報錯,那么我們就需要擴展RouteRecordRaw類型。

        // 聯(lián)合類型
        type RouteConfig = RouteRecordRaw & {hidden?: boolean}; //hidden 是可選屬性
        const routes: Array<RouteConfig> = [
          {
            path: '/',
            name: 'Home',
            component: Home,
            hidden: true,
            meta: {
              permission: true,
              icon: ''
            }
          }
        ];
        復(fù)制代碼

        在setup中使用

        需要導(dǎo)入useRouter創(chuàng)建一個router實例。

        <script lang="ts">
        import { useRouter } from 'vue-router';
        import { defineComponent } from 'vue';
        export default defineComponent({
          setup () {
            const router = useRouter();
            goRoute(path) {
               router.push({path})
            }
          }
        })
        </script>
        復(fù)制代碼

        vuex

        使用this.$store

        import { createStore } from 'vuex';
        export type State = {
          count: number
        }

        export default createStore({
          state: {
            count: 0
          }
        });
        復(fù)制代碼

        需要創(chuàng)建一個聲明文件vuex.d.ts

        // vuex.d.ts
        import {ComponentCustomProperties} from 'vue';
        import {Store} from 'vuex';
        import {State} from './store'
        declare module '@vue/runtime-core' {
            interface ComponentCustomProperties {
                $store: Store<State>
            }
        }
        復(fù)制代碼

        在setup中使用

        1. 定義InjecktionKey
        2. 在安裝插件時傳入key
        3. 在使用useStore時傳入
        import { InjectionKey } from 'vue';
        import { createStore, Store } from 'vuex';

        export type State = {
          count: number
        }
        // 創(chuàng)建一個injectionKey
        export const key: InjectionKey<Store<State>> = Symbol('key');
        復(fù)制代碼
        // main.ts
        import store, { key } from './store';
        app.use(store, key);
        復(fù)制代碼
        <script lang="ts">
        import { useStore } from 'vuex';
        import { key } from '@/store';
        export default defineComponent({
          setup () {
            const store = useStore(key);
            const count = computed(() => store.state.count);
            return {
              count
            }
          }
        })
        </script>
        復(fù)制代碼

        模塊

        新增一個todo模塊。導(dǎo)入的模塊,需要是一個vuex中的interface Module的對象,接收兩個泛型約束,第一個是該模塊類型,第二個是根模塊類型。

        // modules/todo.ts
        import { Module } from 'vuex';
        import { State } from '../index.ts';

        type Todo = {
          id: number,
          name: string,
          completed: boolean
        }

        const initialState = {
          todos: [] as Todo[]
        };

        export type TodoState = typeof initialState;

        export default {
          namespaced: true,
          state: initialState,
          mutations: {
            addTodo (state, payload: Todo) {
              state.todos.push(payload);
            }
          }
        as Module<TodoState, State>; //Module<S, R> S 該模塊類型 R根模塊類型
        復(fù)制代碼
        // index.ts
        export type State = {
          count: number,
          todo?: TodoState // 這里必須是可選,不然state會報錯
        }

        export default createStore({
          state: {
            count: 0
          }
          modules: {
            todo
          }
        });
        復(fù)制代碼

        使用:

        setup () {
          console.log(store.state.todo?.todos);
        }
        復(fù)制代碼

        elementPlus

        yarn add element-plus
        復(fù)制代碼

        完整引入

        import { createApp } from 'vue'
        import ElementPlus from 'element-plus';import 'element-plus/lib/theme-chalk/index.css';import App from './App.vue';
        import 'dayjs/locale/zh-cn'
        import locale from 'element-plus/lib/locale/lang/zh-cn'
        const app = createApp(App)
        app.use(ElementPlus, { size'small'zIndex3000, locale })
        app.mount('#app')
        復(fù)制代碼

        按需加載

        需要安裝babel-plugin-component插件:

        yarn add babel-plugin-component -D

        // babel.config.js
        plugins: [
            [
              'component',
              {
                libraryName'element-plus',
                styleLibraryName'theme-chalk'
              }
            ]
        ]

        復(fù)制代碼
        import 'element-plus/lib/theme-chalk/index.css';
        import 'dayjs/locale/zh-cn';
        import locale from 'element-plus/lib/locale';
        import lang from 'element-plus/lib/locale/lang/zh-cn';
        import {
          ElAside,
          ElButton,
          ElButtonGroup,
        from 'element-plus';

        const components: any[] = [
          ElAside,
          ElButton,
          ElButtonGroup,
        ];

        const plugins:any[] = [
          ElLoading,
          ElMessage,
          ElMessageBox,
          ElNotification
        ];

        const element = (app: any):any => {
          // 國際化
          locale.use(lang);
          // 全局配置
          app.config.globalProperties.$ELEMENT = { size: 'small' };
          
          components.forEach(component => {
            app.component(component.name, component);
          });

          plugins.forEach(plugin => {
            app.use(plugin);
          });
        };

        export default element;
        復(fù)制代碼
        // main.ts
        import element from './plugin/elemment'

        const app = createApp(App);
        element(app);
        復(fù)制代碼

        axios

        axios的安裝使用和vue2上沒有什么大的區(qū)別,如果需要做一些擴展屬性,還是需要聲明一個新的類型。

        type Config = AxiosRequestConfig & {successNotice? : boolean, errorNotice? : boolean}
        復(fù)制代碼
        import axios, { AxiosResponse, AxiosRequestConfig } from 'axios';
        import { ElMessage } from 'element-plus';
        const instance = axios.create({
          baseURL: process.env.VUE_APP_API_BASE_URL || '',
          timeout: 120 * 1000,
          withCredentials: true
        });

        // 錯誤處理
        const err = (error) => {
          if (error.message.includes('timeout')) {
            ElMessage({
              message: '請求超時,請刷新網(wǎng)頁重試',
              type'error'
            });
          }
          if (error.response) {
            const data = error.response.data;
            if (error.response.status === 403) {
              ElMessage({
                message: 'Forbidden',
                type'error'
              });
            }
            if (error.response.status === 401) {
              ElMessage({
                message: 'Unauthorized',
                type'error'
              });
            }
          }
          return Promise.reject(error);
        };

        type Config = AxiosRequestConfig & {successNotice? : boolean, errorNotice? : boolean}

        // 請求攔截
        instance.interceptors.request.use((config: Config) => {
          config.headers['Access-Token'] = localStorage.getItem('token') || '';
          return config;
        }, err);

        // 響應(yīng)攔截
        instance.interceptors.response.use((response: AxiosResponse) => {
          const config: Config = response.config;

          const code = Number(response.data.status);
          if (code === 200) {
            if (config && config.successNotice) {
              ElMessage({
                message: response.data.msg,
                type'success'
              });
            }
            return response.data;
          } else {
            let errCode = [402403];
            if (errCode.includes(response.data.code)) {
              ElMessage({
                message: response.data.msg,
                type'warning'
              });
            }
          }
        }, err);

        export default instance;
        復(fù)制代碼

        setup script

        官方提供了一個實驗性的寫法,直接在script里面寫setup的內(nèi)容,即:setup script。

        之前我們寫組件是這樣的:

        <template>
          <div>
            {{count}}
            <ImgReview></ImgReview >
          </div>
        </template>

        <script lang="ts">
        import { ref, defineComponent } from "vue";
        import ImgReview from "./components/ImgReview.vue";

        export default defineComponent({
          components: {
            ImgReview,
          },
          setup() {
            const count = ref(0);
            return { count };
          }
        });
        </script>

        復(fù)制代碼

        啟用setup script后:在script上加上setup

        <template>
          <div>
            {{count}}
            <ImgReview></ImgReview>
          </
        div>
        </template>
        <script lang="ts" setup>
        import { ref } from "vue";
        import ImgReview from "./
        components/ImgReview.vue";
        const count = ref(0);
        </script>
        復(fù)制代碼

        是不是看起來簡潔了很多,組件直接導(dǎo)入就行了,不用注冊組件,數(shù)據(jù)定義了就可以用。其實我們可以簡單的理解為script包括的內(nèi)容就是setup中的,并做了return。

        導(dǎo)出方法

        <script lang="ts" setup>
        const handleClick = (typestring) => {
          console.log(type);
        }
        </script>
        復(fù)制代碼

        定義props

        使用props需要用到defineProps來定義,具體用法跟之前的props寫法類似:

        基礎(chǔ)用法

        <script lang="ts" setup>
        import { defineProps } from "vue";
        const props = defineProps(['userInfo''gameId']);
        </script>
        復(fù)制代碼

        構(gòu)造函數(shù)進行檢查 給props定義類型:

        const props = defineProps({
          gameId: Number,
          userInfo: {
              typeObject,
              required: true
          }
        });
        復(fù)制代碼

        使用類型注解進行檢查

        defineProps<{
          name: string
          phoneNumber: number
          userInfo: object
          tags: string[]
        }>()
        復(fù)制代碼

        可以先定義好類型:

        interface UserInfo {
          id: number,
          name: string,
          age: number
        }

        defineProps<{
          name: string
          userInfo: UserInfo
        }>()
        復(fù)制代碼

        defineEmit

        <script lang="ts" setup>
        import { defineEmit } from 'vue';

        // expects emits options
        const emit = defineEmit(['kk''up']);
        const handleClick = () => {
          emit('kk''點了我');
        };
        </script>
        復(fù)制代碼
        <Comp @kk="handleClick"/>

        <script lang="ts" setup>
        const handleClick = (data) => {
          console.log(data)
        }
        </script>
        復(fù)制代碼

        獲取上下文

        在標準組件寫法里,setup 函數(shù)默認支持兩個入?yún)ⅲ?/p>

        參數(shù)類型含義
        propsobject由父組件傳遞下來的數(shù)據(jù)
        contextobject組件的執(zhí)行上下文

        在setup script 中使用useContext獲取上下文:

        <script lang="ts" setup>
         import { useContext } from 'vue'
         const { slots, attrs } = useContext();
        </script>
        復(fù)制代碼

        獲取到的slots,attrssetup里面的是一樣的。

        瀏覽 56
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            国产乳交| aaaaaa免费看片 | 中文字幕乱码亚洲无线码小说 | 全黄裸体做爰视频 | 台湾久久久久三极片 | 亚洲无码专区视频 | 国产一级淫 | 激情免费视频在线观看 | 午夜少妇696969区 | 99啪啪视频 |