欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

VueCli3构建TS项目的方法步骤

程序员文章站 2022-07-22 08:04:20
使用vue-cli3构建typescript项目 import 和 require require: 以同步的方式检索其他模块的导出 (开发) import: 动态地...

使用vue-cli3构建typescript项目

import 和 require

require: 以同步的方式检索其他模块的导出 (开发)

import: 动态地加载模块 (生产)

相关文档:

vue-cli3

vue create project-name

, 生成目录结构:

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

"space-before-function-paren": ["error", {
 "anonymous": "always",
 "named": "always",
 "asyncarrow": "always"
}]

的配置:

"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

一个<router-view />对应一个路由层级,下一级<router-view /> 对应路由表中的children路由

router 中的meta

配置每个路由的单独特性

title, keepalive, main, desc, icon, hidden, auth

keep-alive

vue中的<keep-alive></keep-alive>其它生命周期不执行,只执行:activateddeactivated

axios改造

npm i axios --save

VueCli3构建TS项目的方法步骤

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

VueCli3构建TS项目的方法步骤

  • 数据加载策略
  • 细节/全局构造请求
  • 导航响应
  • 权限(配合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

<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

VueCli3构建TS项目的方法步骤

全局注入

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,采用独立样式文件载入,不采用<style>方式内联至html文件中
  sourcemap: false, // 是否在构建样式地图,false将提高构建速度
  loaderoptions: { // css预设器配置项
   css: {
    localidentname: '[name]-[hash]',
    camelcase: 'only'
   },
   stylus: {}
  }
 },
 parallel: require('os').cpus().length > 1, // 构建时开启多进程处理babel编译
 pluginoptions: { // 第三方插件配置
 },
 pwa: { // 单页插件相关配置 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 => {}
 }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。