7

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

 3 years ago
source link: https://www.cnblogs.com/ypSharing/p/15304219.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

一、搭建基础项目

vite详解
vue3API详解

1、vite创建项目

使用 vite 搭建项目

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

根据步骤选择:

  1. 框架(vue,react…)
  2. js或ts

3、运行项目

cd 项目目录
npm install
npm run dev

2、环境变量设置介绍

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);

vite配置多环境打包

  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"
 }

二、配置Router

1、安装路由

这里要注意我们安装的要是4以上的所有采用@next进行安装

npm i vue-router@next -S

2、配置路由

在 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

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension (opens new window),提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。

1、安装vuex

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

npm install vuex@next --save

2、配置vuex

安装完成之后,需要先初始化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");

4、页面调用

  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(...) 映射 state store.mapGetters({...}) 映射 getters store.mapGettersOfKeys(...) 映射 getters store.mapActions({...}) 映射 actions store.mapActionsOfKeys(...) 映射 actions store.mapMutations({...}) 映射 mutations store.mapMutationsOfKeys(...) 映射 mutations
<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>

四、alias起别名

  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、定义data

  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>

2、定义props

props需要使用PropType泛型来约束

<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>

3、定义methods

<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>

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK