VueCli3構(gòu)建TS項(xiàng)目的方法步驟
使用vue-cli3
構(gòu)建Typescript
項(xiàng)目
import 和 require
require
: 以同步的方式檢索其他模塊的導(dǎo)出 (開發(fā))
import
: 動(dòng)態(tài)地加載模塊 (生產(chǎn))
相關(guān)文檔:module methods
vue-cli3
vue create project-name
vue-cli3配置, 生成目錄結(jié)構(gòu):
│ .browserslistrc │ .gitignore │ .postcssrc.js // postcss 配置 │ babel.config.js │ cypress.json │ package.json // 依賴 │ README.md │ tsconfig.json // ts 配置 │ eslint.json // eslint 配置 │ yarn.lock │ ├─public // 靜態(tài)頁面 │ │ favicon.ico │ │ index.html │ │ manifest.json │ │ robots.txt │ │ │ └─img │ └─icons │ ├─src // 主目錄 │ │ App.vue // 頁面主入口 │ │ main.ts // 腳本主入口 │ │ registerServiceWorker.ts // PWA 配置 │ │ router.ts // 路由 │ │ shims-tsx.d.ts // 相關(guān) tsx 模塊注入 │ │ shims-vue.d.ts // Vue 模塊注入 │ │ store.ts // vuex 配置 │ │ │ ├─assets // 靜態(tài)資源 │ │ logo.png │ │ │ ├─components // 組件 │ │ HelloWorld.vue │ │ │ └─views // 頁面 │ About.vue │ Home.vue │ └─tests // 測(cè)試用例 ├─e2e │ ├─plugins │ │ index.js │ ├─specs │ │ test.js │ └─support │ commands.js │ index.js └─unit HelloWorld.spec.ts
改造后的目錄結(jié)構(gòu):
│ .browserslistrc │ .gitignore │ .postcssrc.js // postcss 配置 │ babel.config.js │ cypress.json │ package.json // 依賴 │ README.md // 項(xiàng)目 readme │ tsconfig.json // ts 配置 │ eslint.json // eslint 配置 │ vue.config.js // webpack 配置 │ yarn.lock │ ├─public // 靜態(tài)頁面 │ │ favicon.ico │ │ index.html │ │ manifest.json │ │ robots.txt │ │ │ └─img │ └─icons ├─scripts // 相關(guān)腳本配置 ├─src // 主目錄 │ │ App.vue // 頁面主入口 │ │ main.ts // 腳本主入口 │ │ registerServiceWorker.ts // PWA 配置 │ │ shims-tsx.d.ts │ │ shims-vue.d.ts │ │ │ ├─assets // 靜態(tài)資源 │ │ logo.png │ │ │ ├─components │ │ HelloWorld.vue │ │ │ ├─filters // 過濾 │ ├─lib // 全局插件 │ ├─router // 路由配置 │ │ index.ts │ │ │ ├─scss // 樣式 │ ├─store // vuex 配置 │ │ index.ts │ │ │ ├─typings // 全局注入 │ ├─utils // 工具方法(axios封裝,全局方法等) │ └─views // 頁面 │ About.vue │ Home.vue │ └─tests // 測(cè)試用例 ├─e2e │ ├─plugins │ │ index.js │ │ │ ├─specs │ │ test.js │ │ │ └─support │ commands.js │ index.js │ └─unit HelloWorld.spec.ts
eslint 和 tslint
tslint配置
關(guān)閉不能cosole
:
"no-console": false
"space-before-function-paren": ["error", { "anonymous": "always", "named": "always", "asyncArrow": "always" }]
tslint分號(hào)的配置:
"semicolon": [true, "never"]
eslint配置
在項(xiàng)目中是使用eslint
規(guī)范空格:'indent': 0
路由改造
引入組件方式
dev
使用require
:
/** * 開發(fā)環(huán)境載入文件 * @param fileName 文件路徑,不包括文件名 * @param viewPath 視圖目錄 */ module.exports = (file: string, viewPath: string = 'views') => { return require(`@/${viewPath}/${file}.vue`).default }
prod
使用import
:
/** * 生產(chǎn)環(huán)境載入文件 * @param fileName 文件路徑,不包括文件名 * @param viewPath 視圖目錄 */ module.exports = (file: string, viewPath: string = 'views') => { return import(`@/${viewPath}/${file}.vue`) }
路由處理邏輯
改文件在app.vue
中引入:
/** * 路由處理邏輯 */ import router from '@/router/index' router.beforeEach((to: any, from: any, next: any) => { if (to.name === 'login') { next({name: 'home/index'}) } else { next() } })
router-view
一個(gè)<router-view />
對(duì)應(yīng)一個(gè)路由層級(jí),下一級(jí)<router-view />
對(duì)應(yīng)路由表中的children
路由
router 中的meta
配置每個(gè)路由的單獨(dú)特性
title
, keepalive
, main
, desc
, icon
, hidden
, auth
keep-alive
vue中的<keep-alive></keep-alive>
其它生命周期不執(zhí)行,只執(zhí)行:activated
和 deactivated
axios改造
npm i axios --save
typings
在根目錄創(chuàng)建typings
文件,里面定義, 全局注入。
需要哪些接口引入哪些接口文件。
創(chuàng)建ajax.d.ts
文件,并聲明后臺(tái)返回的數(shù)據(jù)格式。
declare namespace Ajax { // axios return data export interface AxiosResponse { data: AjaxResponse } // reqposne interface export interface AjaxResponse { id: number error: null | object jsonrpc: string result: any } }
使用,在src
根目錄下都可以使用。
let res: Ajax.AxiosResponse = { data: {"id": "1533610056745", "result": 1, "error": null, "jsonrpc": "2.0"} }
cookies的處理
安裝cookies的包:npm i js-cookie --save
增加項(xiàng)目前綴,封裝cookie, localStorage, sessionStorage 增刪改等方法
/** * 操作 cookie, localStorage, sessionStorage 封裝 */ import Cookies from 'js-cookie' import { isNil } from 'lodash' const prefix = process.env.VUE_APP_PREFIX /** * ============ Cookie ============ */ export function getCookie (name: string): string { return Cookies.get(prefix + name) } export function setCookie (name: string, value: any, params= {}): void { if (isEmpty(value)) return Cookies.set(prefix + name, value, params) } export function removeCookie (name: string, params= {}): void { Cookies.remove(prefix + name, params) } /** * ============ localStorage ============ */ export function setLocalStorage (name: string, value: any): void { if (isEmpty(value)) return window.localStorage.setItem(prefix + name, value) } export function getLocalStorage (name: string) { return window.localStorage.getItem(prefix + name) } export function removeLocalStorage (name: string) { window.localStorage.removeItem(prefix + name) } export function clearLocal () { window.localStorage.clear() } /** * ============ sessionStorage ============ */ export function setSessionStorage (name: string, value: any): void { if (isEmpty(value)) return window.sessionStorage.setItem(prefix + name, value) } export function getSessionStorage (name: string) { window.sessionStorage.getItem(prefix + name) } export function removeSessionStorage (name: string) { window.sessionStorage.removeItem(prefix + name) } /** * 判斷值是否為null或者undefined或者''或者'undefined' * @param val value */ function isEmpty (val: any) { if (isNil(val) || val === 'undefined' || val === '') { return true } return false }
fetch
對(duì)axios
進(jìn)行二次封裝,增加請(qǐng)求前后的攔截
import axios from 'axios' /** * 創(chuàng)建 axios 實(shí)例 */ const service = axios.create({ timeout: 3000 }) /** * req 攔截器 */ service.interceptors.request.use((config: object): object => { return config }, (error: any): object => { return Promise.reject(error) }) /** * res 攔截器 */ service.interceptors.response.use((response: any) => { const res = response.data if (res.error) { if (process.env.NODE_ENV !== 'production') { console.error(res) } return Promise.reject(res) } return Promise.resolve(res) }) export default service
請(qǐng)求參數(shù)統(tǒng)一處理
/** * 統(tǒng)一參數(shù)處理 * 請(qǐng)求url處理 */ const qs = require('qs') import { merge, isPlainObject } from 'lodash' import { getCookie } from '@/utils/cookies' /** * 接口參數(shù)拼接 * @param opts 接口參數(shù) * @param opsIdParams 是否傳遞opsId * @param requestType post 還是 get 參數(shù)處理 * @param otherParams 是否傳有其它參數(shù) * @example * commonParams({ * 'method': cmdName.login, * 'params': params * }, false, undefined, false) */ export function commonParams (opts: object, opsIdParams: boolean= true, requestType: string= 'post', otherParams: boolean= true): object { const params = { json: JSON.stringify(merge({ id: new Date().getTime(), jsonrpc: '2.0', params: dealParams(opsIdParams, otherParams), }, opts || {})), } return requestType === 'post' ? qs.stringify(params) : params } /** * 請(qǐng)求接口的地址處理 * @param urlData 請(qǐng)求接口 * @param type 請(qǐng)求路徑 * @example url(cmdName.login) */ export function url (urlData: string, type: any = process.env.VUE_APP_API_PATH) { // @example https://example.com + agsgw/api/ + auth.agent.login return process.env.VUE_APP_API_URL + type + urlData } /** * params 參數(shù)的處理 * @param opsIdParams 是否傳遞opsId * @param otherParams 是否傳有其它參數(shù) */ function dealParams (opsIdParams: boolean, otherParams: boolean | object): object { let obj: any = {} // opsIdParams 默認(rèn)傳opsId if (opsIdParams) { obj.opsId = getCookie('token') || '' } // otherParams其他默認(rèn)參數(shù), 如sn if (otherParams === true) { // obj.sn = getCookie('switchSn') || '' } else { // 其他object if (isPlainObject(otherParams)) { obj = {...obj, ...otherParams} } } return obj }
接口名稱單獨(dú)作為一個(gè)文件
/** * 后臺(tái)接口名稱 */ const cmdName = { login: 'auth.agent.login' } export default cmdName
組合文件
/** * 組合請(qǐng)求http的請(qǐng)求 */ import fetch from '@/utils/fetch' import cmdName from './cmdName' import { commonParams, url } from './commonParams' export { fetch, cmdName, commonParams, url }
導(dǎo)出的請(qǐng)求文件
import { fetch, cmdName, url, commonParams } from '@/api/common' export function login (params: object) { return fetch({ url: url(cmdName.login), method: 'post', data: commonParams({ method: cmdName.login, params }) }) }
使用接口方式
import * as API from '@/api/index' API.login(params).then(res => { })
store改造
vuex
的作用:分離遠(yuǎn)程記錄加載到本地存儲(chǔ)(操作)和 檢索從store
中的getter
- 數(shù)據(jù)加載策略
- 細(xì)節(jié)/全局構(gòu)造請(qǐng)求
- 導(dǎo)航響應(yīng)
- 權(quán)限(配合router控制權(quán)限)
使用:
- 使用
module
形式 - 全局的一些操作,方法,放入
store
中,業(yè)務(wù)邏輯盡量少放,項(xiàng)目全局方法可以放入。例如:cookie
,global cache
action(異步)
: api的操作, 調(diào)用方式:this.$store.dispatch(functionName, data)
mutations(同步)
: dom相關(guān)操作,方法名一般使用常量,
調(diào)用方式: this.$store.commit(mutationsName, data)
this.$store.getters[XXX] => this.$store.getters[namespaced/XXX] this.$store.dispatch(XXX, {}) => this.$store.dispatch(namespaced/XXX, {}) this.$store.commit(XXX, {}) => this.$store.commit(namespaced/XXX, {})
組件內(nèi)的Vue
<template> <div> <div>用戶名:<input type="text" v-model="username" /></div> <div>密碼:<input type="password" v-model="passwd" /></div> <div>{{computedMsg}}</div> </div> </template> <script lang="ts"> import { Component, Prop, Vue, Provide } from 'vue-property-decorator' // 引入組件 @Component({ components: { // input } }) export default class Login extends Vue { // data @Provide() private username: string = '' @Provide() private passwd: string = '' // methods login (u: string, p: string) { } // computed get computedMsg () { return 'username: ' + this.username } // life cycle mounted () { } } </script>
other
公用組件: dateRange
, pagination
, icon-font
, clock
, proxyAutocomplete
, dialog
全局注入
Vue.component(modal.name, modal) // dialog Vue.component(pagination.name, pagination) // 分頁 Vue.component(dateRange.name, dateRange) // 日期 Vue.component(proxyAutocomplete.name, proxyAutocomplete) // 遠(yuǎn)程模糊搜索 Vue.component(card.name, card) // el-tabs Vue.component(tabLoad.name, tabLoad) // el-tabs
在main.ts
中引入公用組件文件夾下的useElement
import '@/components/useElement'
一些問題
不能直接new
// 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type. // 不能直接new一個(gè)函數(shù),通過重新as一個(gè)變量,或者new其原型的constructor 都可以解決 // const encodePsw = new Encode.prototype.constructor().encodePsw(this.passwd) const E = Encode as any const encodePsw = new E().encodePsw(this.passwd)
不能直接導(dǎo)入文件后再追加屬性或方法
import * as filters from '@/filters/index' // 全局filter const F = filters as any Object.keys(filters).forEach(item => { Vue.filter(item, F[item]) })
declare var Chart: any; @Component({ selector: 'my-component', templateUrl: './my-component.component.html', styleUrls: ['./my-component.component.scss'] }) export class MyComponent { //you can use Chart now and compiler wont complain private color = Chart.color; }
vue.config.js
const path = require('path') const debug = process.env.NODE_ENV !== 'production' const VueConf = require('./src/assets/js/libs/vue_config_class') const vueConf = new VueConf(process.argv) module.exports = { baseUrl: vueConf.baseUrl, // 根域上下文目錄 outputDir: 'dist', // 構(gòu)建輸出目錄 assetsDir: 'assets', // 靜態(tài)資源目錄 (js, css, img, fonts) pages: vueConf.pages, lintOnSave: true, // 是否開啟eslint保存檢測(cè),有效值:ture | false | 'error' runtimeCompiler: true, // 運(yùn)行時(shí)版本是否需要編譯 transpileDependencies: [], // 默認(rèn)babel-loader忽略mode_modules,這里可增加例外的依賴包名 productionSourceMap: true, // 是否在構(gòu)建生產(chǎn)包時(shí)生成 sourceMap 文件,false將提高構(gòu)建速度 configureWebpack: config => { // webpack配置,值位對(duì)象時(shí)會(huì)合并配置,為方法時(shí)會(huì)改寫配置 if (debug) { // 開發(fā)環(huán)境配置 config.devtool = 'cheap-module-eval-source-map' } else { // 生產(chǎn)環(huán)境配置 } Object.assign(config, { // 開發(fā)生產(chǎn)共同配置 resolve: { alias: { '@': path.resolve(__dirname, './src'), '@c': path.resolve(__dirname, './src/components'), 'vue$': 'vue/dist/vue.esm.js' } } }) }, chainWebpack: config => { // webpack鏈接API,用于生成和修改webapck配置,https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md if (debug) { // 本地開發(fā)配置 } else { // 生產(chǎn)開發(fā)配置 } }, css: { // 配置高于chainWebpack中關(guān)于css loader的配置 modules: true, // 是否開啟支持‘foo.module.css'樣式 extract: true, // 是否使用css分離插件 ExtractTextPlugin,采用獨(dú)立樣式文件載入,不采用<style>方式內(nèi)聯(lián)至html文件中 sourceMap: false, // 是否在構(gòu)建樣式地圖,false將提高構(gòu)建速度 loaderOptions: { // css預(yù)設(shè)器配置項(xiàng) css: { localIdentName: '[name]-[hash]', camelCase: 'only' }, stylus: {} } }, parallel: require('os').cpus().length > 1, // 構(gòu)建時(shí)開啟多進(jìn)程處理babel編譯 pluginOptions: { // 第三方插件配置 }, pwa: { // 單頁插件相關(guān)配置 https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-pwa }, devServer: { open: true, host: '0.0.0.0', port: 8080, https: false, hotOnly: false, proxy: { '/api': { target: '<url>', ws: true, changOrigin: true } }, before: app => {} } }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
一文讀懂vue動(dòng)態(tài)屬性數(shù)據(jù)綁定(v-bind指令)
這篇文章主要介紹了vue動(dòng)態(tài)屬性數(shù)據(jù)綁定(v-bind指令)的相關(guān)資料,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下2020-07-07vue中watch和computed的區(qū)別與使用方法
這篇文章主要給大家介紹了關(guān)于vue中watch和computed的區(qū)別與使用方法的相關(guān)資料,文中通過實(shí)例代碼結(jié)束的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Vue具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08vue element-ui導(dǎo)航實(shí)現(xiàn)全屏/取消全屏功能
這篇文章主要介紹了vue element-ui導(dǎo)航實(shí)現(xiàn)全屏/取消全屏功能,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08vue菜單欄聯(lián)動(dòng)內(nèi)容頁面tab的實(shí)現(xiàn)示例
本文主要介紹了vue菜單欄聯(lián)動(dòng)內(nèi)容頁面tab的實(shí)現(xiàn)示例,左側(cè)菜單欄與右側(cè)內(nèi)容部分聯(lián)動(dòng),當(dāng)點(diǎn)擊左側(cè)的菜單,右側(cè)會(huì)展示對(duì)應(yīng)的tab,具有一定的參考價(jià)值,感興趣的可以了解一下2024-01-01vue項(xiàng)目之?dāng)?shù)量占比進(jìn)度條實(shí)現(xiàn)方式
這篇文章主要介紹了vue項(xiàng)目之?dāng)?shù)量占比進(jìn)度條實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12VUEX 數(shù)據(jù)持久化,刷新后重新獲取的例子
今天小編就為大家分享一篇VUEX 數(shù)據(jù)持久化,刷新后重新獲取的例子,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-11-11Vue+Node實(shí)現(xiàn)商品列表的分頁、排序、篩選,添加購(gòu)物車功能詳解
這篇文章主要介紹了Vue+Node實(shí)現(xiàn)商品列表的分頁、排序、篩選,添加購(gòu)物車功能,結(jié)合實(shí)例形式分析了vue.js前臺(tái)商品分頁、排序、篩選等功能及后臺(tái)node.js處理技巧,需要的朋友可以參考下2019-12-12