天天看點

Vue3.x全家桶+vite+TS-搭建Vue3.x項目

搭建基礎項目、vite建立項目、運作項目、環境變量設定介紹\vite配置多環境打包、配置Router、安裝路由、配置路由、引入、配置Vuex、安裝vuex、配置vuex、引入、頁面調用、alias起别名、基礎文法、定義data、定義props、定義methods

目錄

  • 一、搭建基礎項目
    • 1、vite建立項目
    • 3、運作項目
    • 2、環境變量設定介紹
      • vite配置多環境打包
  • 二、配置Router
    • 1、安裝路由
    • 2、配置路由
    • 3、引入
  • 三、配置Vuex
    • 1、安裝vuex
    • 2、配置vuex
    • 4、頁面調用
  • 四、alias起别名
  • 五、基礎文法
    • 1、定義data
    • 2、定義props
    • 3、定義methods

vite詳解

vue3API詳解

使用 vite 搭建項目

npm init @vitejs/app
or
yarn create @vitejs/app
           

根據步驟選擇:

  1. 項目名稱
  2. 架構(vue,react…)
  3. js或ts

cd 項目目錄
npm install
npm run dev
           

vite serve 時是development開發模式, vite build時是production生産模式。

分别建立配置檔案: .env.development 、.env.production

注意: 命名規範

VITE_為字首的變量才會暴露給經過vite

處理的代碼

.env.development

# .env.development
VITE_APP_TITLE = MY PROJECT
           

.env.production

# .env.production

NODE_ENV = development

#base api
VITE_APP_BASE_API = 'http://vitetest.com'
           

讀取環境變量

讀取環境變量使用import.meta.env.xxx,可在 main.js中測試

// base api
console.log(import.meta.env.VITE_APP_BASE_API);

// title
console.log(import.meta.env.VITE_APP_TITLE);
           

  1. 安裝cross-env
    • cross-env 通過js在平台設定不同的環境變量的工具
    npm install --save-dev cross-env
               
  2. 配置環境

    在項目打包的時候,我們通常需要根據環境變量來區分不同的環境,以請求不同的背景接口

    那麼我們在項目的根目錄下建立如下的環境配置檔案,以production為例,在項目根目錄下建立.env.production,并新增環境變量VITE_PROJECT_ENV = 'production',需要注意的是,環境變量必須以VITE開頭

# .env.production
NODE_ENV = development
#base api
VITE_APP_BASE_API = 'http://vitetest.com'
#環境變量
VITE_PROJECT_ENV = 'production'
           
  1. 配置打包

    修改package.json (根據自己的實際情況增減)

"scripts": {
    "serve": "cross-env vite --mode development",
    "product": "cross-env vite --mode production",

    "build": "cross-env vite build --mode development",
    "build:product": "cross-env vite build --mode production"
 }
           

這裡要注意我們安裝的要是4以上的所有采用@next進行安裝

npm i vue-router@next -S
           

在 src 下建立 router 檔案夾,并在檔案夾内建立 index.ts

vue-router 參數

  1. 建立router執行個體:createRouter
  2. router的模式分為:

    - createWebHistory -- history模式

    - createWebHashHistory -- hash模式

  3. routes的限制類型是:RouteRecordRaw
import { createRouter, createWebHashHistory } from 'vue-router';
import Home from '../views/Home.vue';
const router = createRouter({
  history: createWebHashHistory(),
  routes: [
    {
        path: '/',
        name: 'Home',
        component: Home,
    },
     {
        path: '/about',
        name: 'About',
        component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
    }
  ]
});

export default router

           

擴充路由額外屬性

在實際項目開發中,常常會遇到這麼一個場景,某一個路由是不需要渲染到側邊欄導航上的,此時我們可以給該路由添加一個hidden屬性來實作。

在ts的強類型限制下,添加額外屬性就會報錯,那麼我們就需要擴充

RouteRecordRaw

類型。

// 聯合類型


import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
type RouteConfig = RouteRecordRaw & {hidden?: boolean}; //hidden 是可選屬性
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(),
  routes
});

export default router;
           

我們在main.ts檔案中引入Vue-Router,如下所示。

import router from './router';
createApp(App).use(router).mount("#app");
           

最後和vue2一樣在App.vue中寫入挂在渲染的元件

<router-view/>
           

Vuex 是一個專為 Vue.js 應用程式開發的狀态管理模式。它采用集中式存儲管理應用的所有元件的狀态,并以相應的規則保證狀态以一種可預測的方式發生變化。Vuex 也內建到 Vue 的官方調試工具 devtools extension (opens new window),提供了諸如零配置的 time-travel 調試、狀态快照導入導出等進階調試功能。

使用Vuex之前,需要先安裝Vuex插件,如下所示。

npm install vuex@next --save
           

安裝完成之後,需要先初始化Vuex。首先,建立一個store/index.ts檔案,添加如下代碼

import { createStore } from 'vuex'
export default createStore({
  state: {
  },
  mutations: {
  },
  actions: {
  },
  modules: {
  }
})
           

封裝一下

不同子產品執行不同的業務邏輯。

以使用者子產品為例

  1. 建立user.ts
import REQUEST_DATA from "@/api/requestHandler";
const state = {
    userInfo:[]
};
const mutations = {
    setStateItem(state:any, data:any) {
        state[data.key] = data.value;
    }
};

const actions = {

    async getUserData({ commit }:any, data?:any):Promise<any> {
        try {
            const res = await REQUEST_DATA('userInfoUri', data);
            if (res.data.code == 200) {
                commit("setStateItem", {
                    key: "reasonList",
                    value: res.data.data
                });
                data.cb && data.cb(res.data.data.satisfaction_status)
            } else {
               //給出錯誤提示toast
                return false;
            }
        } catch (e) {
            return false;
        }
    },
};

export default {
    state,
    actions,
    mutations,
    namespaced: true
};
           
  1. index.ts中調用
import { createStore } from 'vuex'
import user from './modules/user'
const store =  createStore({
  modules: {
    user,
  },
})

export default store
           

我們在main.ts檔案中引入Vuex,如下所示。

import { createApp } from 'vue'
import App from './App.vue'
import router from './router';
import store from './store'

createApp(App).use(store).use(router).mount("#app");
           

  1. import { useStore } from 'vuex';
  2. const store = useStore();
  • store中的方法:
方法 介紹
store.state.xxx 通路 state
store.getters.xxx 通路 getter
store.xxx 通路 Store 的函數
store.commit("xxx", payload?) 調用 (優化限制,以強化提示)
store.commits.xxx(payload?) 調用 commit
store.dispatch("xxx", payload?)
store.dispatchs.xxx(payload?) 調用 dispatch
store.subscribe(fn) 優化限制,以強化提示
store.subscribeAction(fn)
store.mapState({...}) 映射 state
store.mapStateOfKeys(...)
store.mapGetters({...}) 映射 getters
store.mapGettersOfKeys(...)
store.mapActions({...}) 映射 actions
store.mapActionsOfKeys(...)
store.mapMutations({...}) 映射 mutations
store.mapMutationsOfKeys(...)
<template>
  <h1>Home Page</h1>
  <h2>{{count}}</h2>
  <button @click="handleClick">click</button>
</template>

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

export default defineComponent({
  setup () {
    const store = useStore();
    const count = computed(() => store.state.home.count);
    const handleClick = () => {
      store.commit('user/add');
    };
    return {
      handleClick,
      count
    };
  }
})
</script>
           

  1. vite.config.ts

    在過去使用vue-cli的時候,我們總是使用@去引入某些檔案,由于Vite沒有提供類似的配置,是以我們需要手動的對其進行相關配置,才能繼續使用@符号去快捷的引入檔案。首先,我們需要修改vite.config.ts的配置。

    核心代碼

resolve: {
    alias: [
      {
        find: '@',
        replacement: '/src',
      },
      { find: 'views', replacement: '/src/views' },
      { find: 'components', replacement: '/src/components' },
    ]
  }
           
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  resolve:{
      alias:[
          {
              find:'@',
              replacement:'/src'
          },
          {
            find:'views',
            replacement:'/src/views'
          },
          {
            find:'components',
            replacement:'/src/components'
          },
          
          
      ]
  }
})

           
  1. tsconfig.json

    然後,我們在修改tsconfig.json檔案

"types": ["vite/client", "jest"],
        "baseUrl": ".",
        "paths": {
          "@/*": ["src/*"]
        } 
           
{
    "compilerOptions": {
        "target": "esnext",
        "useDefineForClassFields": true,
        "module": "esnext",
        "moduleResolution": "node",
        "strict": true,
        "jsx": "preserve",
        "sourceMap": true,
        "resolveJsonModule": true,
        "esModuleInterop": true,
        "lib": [
            "esnext",
            "dom"
        ],
        "types": ["vite/client", "jest"],
        "baseUrl": ".",
        "paths": {
          "@/*": ["src/*"]
        } 
    },
    "include": [
        "src/**/*.ts",
        "src/**/*.d.ts",
        "src/**/*.tsx",
        "src/**/*.vue"
    ]
}
           

  1. script标簽上:lang="ts"
  2. 定義一個類型type或者接口:interface來限制data
  3. 定義響應式資料:可以使用ref或者toRefs來
  4. 使用ref在setup讀取的時候需要擷取xxx.value,但在template中不需要
  5. 使用reactive時,可以用toRefs解構導出,在template就可以直接使用了
<script lang="ts">
import { defineComponent, reactive, ref, toRefs } from "vue";

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

export default defineComponent({
    setup() {
        const data = reactive({
            todoList: [] as Todo[],
        });
        const count = ref(0);
        console.log(count.value);
        return {
        ...toRefs(data),
        };
    },
});
</script>
           

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

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

export default defineComponent({
  props: {
    userInfo: {
      type: Object as PropType<UserInfo>, // 泛型類型
      required: true,
    },
  },
});
</script>
           

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

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

export default defineComponent({
  setup() {
    const data = reactive({
      todoList: [] as Todo[],
    });
    // 限制輸入和輸出類型
    const newTodo = (name: string): Todo => {
      return {
        id: 1,
        name,
        completed: false,
      };
    };
    const addTodo = (todo: Todo): void => {
      data.todoList.push(todo);
    };
    return {
      ...toRefs(data),
      newTodo,
      addTodo,
    };
  },
});
</script>