wordpress实现表格填写功能天津外贸seo推广
前言
框架搭建是独当一面的基础:本文回顾基于vite+vue3.0+ts框架,我会尽量讲的更全更细节,同时方便以后复用
vite环境搭建,构建vite-vue-ts项目
- 安装vite环境
npm init @vitejs/app或者yarn create @vitejs/app
- 使用vite初始化vite+vue+ts的项目
npm init @vitejs/app vite-project或者yarn create @vitejs/app vite-project
- 选择项目类型
cd vite-project
需要进行安装包 npm install 安装成功后进行 yarn dev
至此项目完成了基础的初始化
项目配置
-
路由配置
安装vue-routernpm install vue-router@4或者yarn add vue-router@4
在src下新建一个router文件夹,作为vue-router的配置目录。此目录下再新建index.ts文件,编辑内容如下:
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'; const history = createWebHistory() const routes: Array<RouteRecordRaw> = [{path: '/',redirect: '/home',},{path: '/home',name: 'home',component: () => import('@/views/home/index.vue'),}, ]; const router = createRouter({history,routes, }) export default router
新建一个views文件夹,作为项目界面开发目录。参考router中的配置可知,在views目录下新建home目录并新建index.vue,编辑文件如下:
<template><h2>{{ msg }}</h2><h2>{{ count }}</h2> </template> <script setup lang="ts"> import { ref } from 'vue'const msg = ref('Hello') const count = ref(710) </script><style scoped> </style>
在main.ts中引入vue-router
import { createApp } from 'vue'import App from './App.vue';import router from './router';createApp(App).use(router).mount('#app')
在App.vue中使用vue-router
<template><router-view /></template><script setup lang="ts"></script><style>#app {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;}</style>
这个时候页面报错
无法解析@符号
安装一个path的插件:
npm install --save-dev @types/node
然后对vite.config.ts 进行修改
修改 vite.config.ts 文件:import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue'/************************************* 路径配置 start ********************************/ import { resolve } from 'path' const pathResolve = (dir: string): any => { return resolve(__dirname, ".", dir) }const alias: Record<string, string> = {'@': pathResolve("src") } /************************************* 路径配置 end ********************************/ // https://vitejs.dev/config/ export default defineConfig({plugins: [vue()],resolve: { // ****************** 路径配置新增alias // ****************** 路径配置新增} // ****************** 路径配置新增 })
在tsconfig.node.json添加 compilerOptions 对象属性添加 “allowSyntheticDefaultImports”: true 即可重新启动
-
vuex 配置
安装vuexnpm install vuex@next --save或者yarn add vuex@next --save同时安装 vuex-persist 持久化存储⽽⽣的⼀个插件npm install --save vuex-persistoryarn add vuex-persist
在 src目录下创建一个store文件夹,在里面新建 index.ts、module
编辑index.ts如下:import { createStore } from 'vuex';import VuexPersistence from 'vuex-persist';const persistedState = new VuexPersistence({ // 数据持久化storage: window.sessionStorage,modules: ['keyword'],});const store = createStore({plugins: [persistedState.plugin],modules: {},});export default store;
在main.ts中引入
import { createApp } from 'vue'import App from './App.vue';import router from './router';import store from '@/store';createApp(App).use(router).use(store).mount('#app')
出现错误
ts 配置需要读取项目根路径的 tsconfig.json,添加 paths 配置即可:{"compilerOptions": {"target": "esnext","useDefineForClassFields": true,"module": "esnext","moduleResolution": "node","strict": true,"jsx": "preserve","sourceMap": true,"resolveJsonModule": true,"esModuleInterop": true,"lib": ["esnext", "dom"],"paths": {"@/*": ["./src/*"]}},"include": ["src/**/*.ts","src/**/*.d.ts","src/**/*.tsx","src/**/*.vue"] }
-
css语言 scss
npm install --save-dev sass-loadernpm install --save-dev node-sassnpm install --save-dev sass
成功
-
全局引入element-plus
安装:npm install element-plus
import { createApp } from 'vue'import App from './App.vue';import router from '@/router';import store from '@/store';import ElementPlus from 'element-plus'import 'element-plus/dist/index.css'createApp(App).use(router).use(store).use(ElementPlus).mount('#app')
-
按需导入element
自动导入:安装插件npm install -D unplugin-vue-components unplugin-auto-import
// vite.config.ts import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import AutoImport from 'unplugin-auto-import/vite' import Components from 'unplugin-vue-components/vite' import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' import path from 'path' const { resolve } = require('path') // https://vitejs.dev/config/ export default defineConfig({plugins: [vue(),AutoImport({resolvers: [ElementPlusResolver()],}),Components({resolvers: [ElementPlusResolver()],}),], // 注册插件server: {open: true},resolve: {alias: {'@': resolve(__dirname, './src'),},} })
这时页面多了 两个文件:页面使用elment标签就会自动导入
-
集成Axios
安装:npm install axios
配置接口proxy代理:代理我们可以使用npm 官方文档推荐的dotenv 用于动态获取.env 文件加载到 process.env 安装npm install dotenv
根目录下创建两个 .env 文件:.env.development(开发环境) .env.production(生产环境)
// .env.development 开发环境的代理配置VITE_PUBLIC_PATH='./'VITE_BASE_API='/asr'VITE_TARGET_HOST='http://192.168.0.222:58008'
// .env.productionVITE_PUBLIC_PATH='/'VITE_BASE_API='/asr'
修改 vite.config.ts
import { defineConfig, UserConfig } from 'vite'import vue from '@vitejs/plugin-vue'import AutoImport from 'unplugin-auto-import/vite'import Components from 'unplugin-vue-components/vite'import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'import path from 'path'// @ts-ignoreimport fs from 'fs'// @ts-ignoreimport dotenv from 'dotenv'const { resolve } = require('path')// https://vitejs.dev/config/export default defineConfig(({ mode }: UserConfig): UserConfig => {// 根据环境变量加载环境变量文件const ASR_ENV = dotenv.parse(fs.readFileSync(`.env.${mode}`))return {base: ASR_ENV.VITE_PUBLIC_PATH,server: {host: '0.0.0.0',port: 3000,https: false,proxy: {[ASR_ENV.VITE_BASE_API]: {target: `${ASR_ENV.VITE_TARGET_HOST}`,changeOrigin: true,},},},resolve: {alias: {'@': resolve(__dirname, './src'),},},plugins: [vue(),AutoImport({resolvers: [ElementPlusResolver()],}),Components({resolvers: [ElementPlusResolver()],}),],css: {preprocessorOptions: {scss: {charset: false,},},},build: {minify: 'terser', // 是否进行压缩,boolean | 'terser' | 'esbuild',默认使用esbuild// reportCompressedSize: true,manifest: false, // 是否产出maifest.jsonsourcemap: false, // 是否产出soucemap.jsonchunkSizeWarningLimit: 1500,},}})
封装axios
用到的插件:npm i js-cookie
在src下新建utils文件夹:
// auth.ts// @ts-ignoreimport Cookies from 'js-cookie';const TokenKey = 'asr-token';export const getToken = () => Cookies.get(TokenKey);export const delToken = () => Cookies.remove(TokenKey);
// request.tsimport axios from 'axios'; // 引入axiosimport Vrouter from '@/router'import { getToken } from '@/utils/auth';const Router = Vrouter;console.log('import.meta.env.VITE_BASE_API', import.meta.env.VITE_BASE_API)const service = axios.create({baseURL: import.meta.env.VITE_BASE_API as string,timeout: 99999,});// http request 拦截器service.interceptors.request.use((config:any) => {// 全局添加 tokenif (getToken()) {config.headers['asr-token'] = getToken();}return config;},(error) => {console.error(error);return Promise.reject(error);},);// http response 拦截器service.interceptors.response.use((response) => {if (response.data.code === 9) {// Router.replace('/rejectUser');return}return response.data},(error) => {if (error.response && error.response.status && error.response.status === 403) {// logout().then(() => {// // removeToken()// });}// 网络超时if (error.message && error.message.includes('timeout')) {console.error('请求超时');return error.message;}if (error.response && error.response.status && error.response.status === 500) {// 没有权限console.error('接口异常');return error;}return error;},);export default service;
src下新建types类型文件夹:用于声明类型
/src/types/service/index.tsinterface resModel {code:numbermsg:stringdata:any[propname:string]:any}export interface requestModel {<T>(data?: T): Promise<resModel>}
src/types/service/shims.d.ts
// eslint-disable-next-line @typescript-eslint/no-unused-vars import axios from 'axios';declare module 'axios' {export interface AxiosInstance {<T = any>(config: AxiosRequestConfig): Promise<T>;request<T = any> (config: AxiosRequestConfig): Promise<T>;get<T = any>(url: string, config?: AxiosRequestConfig): Promise<T>;delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<T>;head<T = any>(url: string, config?: AxiosRequestConfig): Promise<T>;post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T>;put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T>;patch<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T>;} }
src下新建api文件夹用于接口API二次封装
使用示例
src/api/user.tsimport request from '@/utils/request'; import { requestModel } from '@/types/service';// 获取用户信息 export const getUserInfo: requestModel = () => request({url: '/info',method: 'get', });// 退出登录 export const logout: requestModel = () => request({url: '/quit',method: 'post', });
-
配置eslint
yarn add eslint@7.2.0 eslint-plugin-vue@7.20.0 vue-eslint-parser @typescript-eslint/parser @typescript-eslint/eslint-plugin@4.33.0 eslint-config-airbnb-base@15.0.0 eslint-plugin-import@2.25.4 -D
根目录设置.eslintrc.js
module.exports = {root: true,globals: {defineEmits: 'readonly',defineProps: 'readonly',},extends: ['plugin:@typescript-eslint/recommended','plugin:vue/vue3-recommended','airbnb-base',],parserOptions: {parser: '@typescript-eslint/parser',ecmaVersion: 2020,},rules: {'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', // 禁用 debugger'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', // 禁用 console'no-bitwise': 'off', // 禁用按位运算符'no-tabs': 'off', // 禁用 tab'array-element-newline': ['error', 'consistent'], // 强制数组元素间出现换行indent: ['error',2,{ MemberExpression: 0, SwitchCase: 1, ignoredNodes: ['TemplateLiteral'] },], // 强制使用一致的缩进quotes: ['error', 'single'], // 强制使用一致的反勾号、双引号或单引号'comma-dangle': ['error', 'always-multiline'], // 要求或禁止末尾逗号'object-curly-spacing': ['error', 'always'], // 强制在大括号中使用一致的空格'max-len': ['error', 120], // 强制一行的最大长度'no-new': 'off', // 禁止使用 new 以避免产生副作用'linebreak-style': 'off', // 强制使用一致的换行风格'import/extensions': 'off', // 确保在导入路径中统一使用文件扩展名'eol-last': 'off', // 要求或禁止文件末尾存在空行'no-shadow': 'off', // 禁止变量声明与外层作用域的变量同名'no-unused-vars': 'warn', // 禁止出现未使用过的变量'import/no-cycle': 'off', // 禁止一个模块导入一个有依赖路径的模块回到自己身上'arrow-parens': 'off', // 要求箭头函数的参数使用圆括号semi: ['error', 'never'], // 要求或禁止使用分号代替 ASI// semi:0, // 取消对分号校验eqeqeq: 'off', // 要求使用 === 和 !=='no-param-reassign': 'off', // 禁止对 function 的参数进行重新赋值'import/prefer-default-export': 'off', // 如果模块只输入一个名字,则倾向于默认输出'no-use-before-define': 'off', // 禁止在变量定义之前使用它们,则倾向于默认输出'no-continue': 'off', // 禁用 continue 语句'prefer-destructuring': 'off', // 优先使用数组和对象解构'no-plusplus': 'off', // 禁用一元操作符 ++ 和 --'prefer-const': 'warn', // 要求使用 const 声明那些声明后不再被修改的变量'global-require': 'off', // 要求 require() 出现在顶层模块作用域中'no-prototype-builtins': 'off', // 禁止直接调用 Object.prototypes 的内置属性'consistent-return': 'off', // 要求 return 语句要么总是指定返回的值,要么不指定'one-var-declaration-per-line': 'off', // 要求或禁止在变量声明周围换行'one-var': 'off', // 强制函数中的变量要么一起声明要么分开声明'import/named': 'off', // 确保命名导入与远程文件中的命名导出相对应'object-curly-newline': 'off', // 强制大括号内换行符的一致性'default-case': 'off', // 要求 switch 语句中有 default 分支'no-trailing-spaces': 'off', // 禁用行尾空格'func-names': 'off', // 要求或禁止使用命名的 function 表达式radix: 'off', // 强制在 parseInt() 使用基数参数'no-unused-expressions': 'off', // 禁止出现未使用过的表达式'no-underscore-dangle': 'off', // 禁止标识符中有悬空下划线'no-nested-ternary': 'off', // 禁用嵌套的三元表达式'no-restricted-syntax': 'off', // 禁用特定的语法'no-await-in-loop': 'off', // 禁止在循环中出现 await'import/no-extraneous-dependencies': 'off', // 禁止使用外部包'import/no-unresolved': 'off', // 确保导入指向一个可以解析的文件/模块'template-curly-spacing': ['error', 'always'], // 要求或禁止模板字符串中的嵌入表达式周围空格的使用'@typescript-eslint/no-var-requires': 'off', // 除import语句外,禁止使用require语句'@typescript-eslint/no-empty-function': 'off', // 不允许空函数'@typescript-eslint/no-explicit-any': 'off', // 禁止使用 any 类型'guard-for-in': 'off', // 要求 for-in 循环中有一个 if 语句'class-methods-use-this': 'off', // 强制类方法使用 this'vue/html-indent': ['error', 2], // 在<template>中强制一致缩进'vue/html-self-closing': 'off', // 执行自闭合的风格'vue/max-attributes-per-line': [ // 强制每行属性的最大数量'warn',{singleline: {max: 3,allowFirstLine: true,},multiline: {max: 1,allowFirstLine: false,},},],'vue/singleline-html-element-content-newline': 'off', // 要求单行元素的内容前后有一个换行符}, }
shift + command + p 组合键打开命令面板,输入 settings 回车打开配置文件。
js { "workbench.iconTheme": "vscode-icons", "workbench.colorTheme": "Default Dark+", "vsicons.dontShowNewVersionMessage": true, "eslint.validate": [ "javascript", "javascriptreact", "vue", "typescript" ], "eslint.format.enable": true, "eslint.alwaysShowStatus": true, "editor.codeActionsOnSave": { "source.fixAll.eslint": true }, "files.associations": { "*.vue": "vue" }, }
直接 control + s 键保存,VSCode 会自动修复代码 ESLint 检测出的错误,帮助我们去除了 ; 逗号。
-
配置rem适配布局
1、根据页面屏幕大小计算每个页面的基准值,即一个rem为多少px
src目录下创建rem.ts
// 基准大小const baseSize = 16// 设置 rem 函数function setRem() {// 当前页面宽度相对于 750 宽的缩放比例,可根据自己需要修改。const scale = document.documentElement.clientWidth / 1920// 设置页面根节点字体大小document.documentElement.style.fontSize = `${baseSize * Math.min(scale, 2)}px`}// 初始化setRem()// 改变窗口大小时重新设置 remwindow.onresize = () => {setRem()}```
注意:如果提示 “无法在 "--isolatedModules" 下编译“rem.ts”,因为它被视为全局脚 本文件。请添加导入、导出或空的 "export {}" 语句来使它成为模块 ”此时你应该在 tsconfig.json 文件中将 isolatedModules 字段设置为 false。
在main.ts中引入:
import './rem'
安装依赖
npm install postcss-pxtorem -D
对vite.config.ts文件添加配置
css: {preprocessorOptions: {scss: {charset: false,},},+ postcss: {+ plugins: [+ postCssPxToRem({+ rootValue: 16, // 1rem的大小+ propList: ['*'], // 需要转换的属性,这里选择全部都进行转换+ }),+ ],+ },},
结束