本篇文章给大家分享的是有关使用VueCli3怎么构建一个TS项目,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。
创新互联公司主要从事网站制作、成都网站制作、网页设计、企业做网站、公司建网站等业务。立足成都服务凉山州,十年网站建设经验,价格优惠、服务专业,欢迎来电咨询建站服务:18982081108
使用vue-cli3构建Typescript项目
import 和 require
require: 以同步的方式检索其他模块的导出 (开发)
import: 动态地加载模块 (生产)
vue-cli3
vue create project-name
vue-cli3配置, 生成目录结构:
│ .browserslistrc │ .gitignore │ .postcssrc.js // postcss 配置 │ babel.config.js │ cypress.json │ package.json // 依赖 │ README.md │ tsconfig.json // ts 配置 │ eslint.json // eslint 配置 │ yarn.lock │ ├─public // 静态页面 │ │ favicon.ico │ │ index.html │ │ manifest.json │ │ robots.txt │ │ │ └─img │ └─icons │ ├─src // 主目录 │ │ App.vue // 页面主入口 │ │ main.ts // 脚本主入口 │ │ registerServiceWorker.ts // PWA 配置 │ │ router.ts // 路由 │ │ shims-tsx.d.ts // 相关 tsx 模块注入 │ │ shims-vue.d.ts // Vue 模块注入 │ │ store.ts // vuex 配置 │ │ │ ├─assets // 静态资源 │ │ logo.png │ │ │ ├─components // 组件 │ │ HelloWorld.vue │ │ │ └─views // 页面 │ About.vue │ Home.vue │ └─tests // 测试用例 ├─e2e │ ├─plugins │ │ index.js │ ├─specs │ │ test.js │ └─support │ commands.js │ index.js └─unit HelloWorld.spec.ts
改造后的目录结构:
│ .browserslistrc │ .gitignore │ .postcssrc.js // postcss 配置 │ babel.config.js │ cypress.json │ package.json // 依赖 │ README.md // 项目 readme │ tsconfig.json // ts 配置 │ eslint.json // eslint 配置 │ vue.config.js // webpack 配置 │ yarn.lock │ ├─public // 静态页面 │ │ favicon.ico │ │ index.html │ │ manifest.json │ │ robots.txt │ │ │ └─img │ └─icons ├─scripts // 相关脚本配置 ├─src // 主目录 │ │ App.vue // 页面主入口 │ │ main.ts // 脚本主入口 │ │ registerServiceWorker.ts // PWA 配置 │ │ shims-tsx.d.ts │ │ shims-vue.d.ts │ │ │ ├─assets // 静态资源 │ │ logo.png │ │ │ ├─components │ │ HelloWorld.vue │ │ │ ├─filters // 过滤 │ ├─lib // 全局插件 │ ├─router // 路由配置 │ │ index.ts │ │ │ ├─scss // 样式 │ ├─store // vuex 配置 │ │ index.ts │ │ │ ├─typings // 全局注入 │ ├─utils // 工具方法(axios封装,全局方法等) │ └─views // 页面 │ About.vue │ Home.vue │ └─tests // 测试用例 ├─e2e │ ├─plugins │ │ index.js │ │ │ ├─specs │ │ test.js │ │ │ └─support │ commands.js │ index.js │ └─unit HelloWorld.spec.ts
eslint 和 tslint
tslint配置
关闭不能cosole:
"no-console": false
tslint的函数前后空格:
"space-before-function-paren": ["error", {
"anonymous": "always",
"named": "always",
"asyncArrow": "always"
}]tslint分号的配置:
"semicolon": [true, "never"]
eslint配置
在项目中是使用eslint
规范空格:'indent': 0
路由改造
引入组件方式
dev使用require:
/**
* 开发环境载入文件
* @param fileName 文件路径,不包括文件名
* @param viewPath 视图目录
*/
module.exports = (file: string, viewPath: string = 'views') => {
return require(`@/${viewPath}/${file}.vue`).default
}prod使用import:
/**
* 生产环境载入文件
* @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
一个对应一个路由层级,下一级 对应路由表中的children路由
router 中的meta
配置每个路由的单独特性
title, keepalive, main, desc, icon, hidden, auth
keep-alive
vue中的其它生命周期不执行,只执行:activated 和 deactivated
axios改造
npm i axios --save

typings
在根目录创建typings文件,里面定义, 全局注入。
需要哪些接口引入哪些接口文件。
创建ajax.d.ts文件,并声明后台返回的数据格式。
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
增加项目前缀,封装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
对axios进行二次封装,增加请求前后的拦截
import axios from 'axios'
/**
* 创建 axios 实例
*/
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请求参数统一处理
/**
* 统一参数处理
* 请求url处理
*/
const qs = require('qs')
import { merge, isPlainObject } from 'lodash'
import { getCookie } from '@/utils/cookies'
/**
* 接口参数拼接
* @param opts 接口参数
* @param opsIdParams 是否传递opsId
* @param requestType post 还是 get 参数处理
* @param otherParams 是否传有其它参数
* @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
}
/**
* 请求接口的地址处理
* @param urlData 请求接口
* @param type 请求路径
* @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 参数的处理
* @param opsIdParams 是否传递opsId
* @param otherParams 是否传有其它参数
*/
function dealParams (opsIdParams: boolean, otherParams: boolean | object): object {
let obj: any = {}
// opsIdParams 默认传opsId
if (opsIdParams) {
obj.opsId = getCookie('token') || ''
}
// otherParams其他默认参数, 如sn
if (otherParams === true) {
// obj.sn = getCookie('switchSn') || ''
} else {
// 其他object
if (isPlainObject(otherParams)) {
obj = {...obj, ...otherParams}
}
}
return obj
}接口名称单独作为一个文件
/**
* 后台接口名称
*/
const cmdName = {
login: 'auth.agent.login'
}
export default cmdName组合文件
/**
* 组合请求http的请求
*/
import fetch from '@/utils/fetch'
import cmdName from './cmdName'
import { commonParams, url } from './commonParams'
export {
fetch,
cmdName,
commonParams,
url
}导出的请求文件
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的作用:分离远程记录加载到本地存储(操作)和 检索从store 中的getter

数据加载策略
细节/全局构造请求
导航响应
权限(配合router控制权限)
使用:
使用
module形式全局的一些操作,方法,放入
store中,业务逻辑尽量少放,项目全局方法可以放入。例如:cookie,global cache
action(异步): api的操作, 调用方式:this.$store.dispatch(functionName, data)
mutations(同步): dom相关操作,方法名一般使用常量,
调用方式: 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, {})组件内的Vue
用户名:密码:{{computedMsg}}
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) // 远程模糊搜索 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一个函数,通过重新as一个变量,或者new其原型的constructor 都可以解决 // const encodePsw = new Encode.prototype.constructor().encodePsw(this.passwd) const E = Encode as any const encodePsw = new E().encodePsw(this.passwd)
不能直接导入文件后再追加属性或方法
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', // 构建输出目录
assetsDir: 'assets', // 静态资源目录 (js, css, img, fonts)
pages: vueConf.pages,
lintOnSave: true, // 是否开启eslint保存检测,有效值:ture | false | 'error'
runtimeCompiler: true, // 运行时版本是否需要编译
transpileDependencies: [], // 默认babel-loader忽略mode_modules,这里可增加例外的依赖包名
productionSourceMap: true, // 是否在构建生产包时生成 sourceMap 文件,false将提高构建速度
configureWebpack: config => { // webpack配置,值位对象时会合并配置,为方法时会改写配置
if (debug) { // 开发环境配置
config.devtool = 'cheap-module-eval-source-map'
} else { // 生产环境配置
}
Object.assign(config, { // 开发生产共同配置
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) {
// 本地开发配置
} else {
// 生产开发配置
}
},
css: { // 配置高于chainWebpack中关于css loader的配置
modules: true, // 是否开启支持‘foo.module.css'样式
extract: true, // 是否使用css分离插件 ExtractTextPlugin,采用独立样式文件载入,不采用

咨询
建站咨询