前端项目配置 ts,axios,router,vuex
发布于: 2021 年 05 月 06 日
1.使用 tslint.json,如下配置仅供参考
{ "rules": { // TS特性 "member-access": true, // 设置成员对象的访问权限(public,private,protect) "member-ordering": [// 设置修饰符顺序 true, { "order": [ "public-static-field", "public-static-method", "protected-static-field", "protected-static-method", "private-static-field", "private-static-method", "public-instance-field", "protected-instance-field", "private-instance-field", "public-constructor", "protected-constructor", "private-constructor", "public-instance-method", "protected-instance-method", "private-instance-method" ] } ], "no-empty-interface":true,// 不允许空接口 "no-parameter-reassignment":true,// 不允许修改方法输入参数 "prefer-for-of":true,// 如果for循环中没有使用索引,建议是使用for-of
// 功能特性 "await-promise":true,// 不允许没有Promise的情况下使用await "curly":true,// if/for/do/while强制使用大括号 "forin":true,// 使用for in语句时,强制进行hasOwnProperty检查 "no-arg":true,// 不允许使用arguments.callee // "no-bitwise":true, // 不允许使用特殊运算符 &, &=, |, |=, ^, ^=, <<, <<=, >>, >>=, >>>, >>>=, ~ "no-conditional-assignment":true,// do while/for/if/while 语句中将会对例如if(a=b)进行检查 // "no-console":true,// 不允许使用console对象 "no-debugger":true,// 不允许使用debugger "no-duplicate-super":true,// 不允许super() 两次使用在构造函数中 "no-empty":true,// 函数体不允许空 "no-eval":true,// 不允许使用eval "no-for-in-array":true,// 不允许对Array使用for-in "no-invalid-template-strings":true,// 只允许在模板字符串中使用${ "no-invalid-this":true,// 不允许在class之外使用this "no-null-keyword":true,// 不允许使用null,使用undefined代替null,指代空指针对象 "no-sparse-arrays":true,// 不允许array中有空元素 "no-string-throw":true,// 不允许throw一个字符串 "no-switch-case-fall-through":true,// 不允许case段落中在没有使用breack的情况下,在新启一段case逻辑 "no-unsafe-finally":true,// 不允许在finally语句中使用return/continue/break/throw "no-unused-expression":true,// 不允许使用未使用的表达式 "no-use-before-declare":true,// 在使用前必须声明 "no-var-keyword":true,// 不允许使用var "radix":true,// parseInt时,必须输入radix精度参数 "restrict-plus-operands":true,// 不允许自动类型转换,如果已设置不允许使用关键字var该设置无效 "triple-equals":true,// 必须使用恒等号,进行等于比较 "use-isnan":true,// 只允许使用isNaN方法检查数字是否有效
// 维护性功能 "indent":[true, "spaces", 4],// 每行开始以4个空格符开始 "linebreak-style":[true,"CR/LF"],// 换行符格式 CR/LF可以通用使用在windows和osx "max-classes-per-file":[true,1],// 每个文件中可定义类的个数 "max-file-line-count":[true,500],// 定义每个文件代码行数 "max-line-length":[true,120],// 定义每行代码数 "no-default-export":true,// 禁止使用export default关键字,因为当export对象名称发生变化时,需要修改import中的对象名。https://github.com/palantir/tslint/issues/1182#issue-151780453 "no-duplicate-imports":true,// 禁止在一个文件内,多次引用同一module
// 格式 "align":[true,"parameters","arguments","statements","members","elements"],// 定义对齐风格 "array-type":[true,"array"],// 建议使用T[]方式声明一个数组对象 "class-name":true,// 类名以大驼峰格式命名 "comment-format":[true, "check-space"],// 定义注释格式 "encoding":true,// 定义编码格式默认utf-8 "import-spacing":true,// import关键字后加空格 "interface-name":[true,"always-prefix"],// interface必须以I开头 "jsdoc-format":true,// 注释基于jsdoc风格 "new-parens":true,// 调用构造函数时需要用括号 "no-consecutive-blank-lines":[true,2],// 不允许有空行 "no-trailing-whitespace": [// 不允许空格结尾 true, "ignore-comments", "ignore-jsdoc" ], "no-unnecessary-initializer":true,// 不允许没有必要的初始化 "variable-name":[true,"check-format",// 定义变量命名规则 "allow-leading-underscore", "allow-trailing-underscore", "ban-keywords"] }}复制代码
{ "defaultSeverity": "warning", "extends": [ "tslint:recommended" ], "linterOptions": { "exclude": [ "node_modules/**", ] }, "rules": { "quotemark": [ true, "single" ], "indent": [ true, "spaces", 4 ], "interface-name": false, "ordered-imports": false, "object-literal-sort-keys": false, "no-consecutive-blank-lines": false, "no-console": [ false ], "only-arrow-functions": [ false ], "member-access": [ true, "no-public" ], "no-unused-expression": [ true, "allow-fast-null-checks", "allow-new", "allow-tagged-template" ], "arrow-parens": [ "as-needed" ], "max-line-length": [ true, { "limit": 180, "ignore-pattern": "^import |^export {(.*?)} |import(.*?)" } ], "no-empty": [ true, "allow-empty-catch", "allow-empty-functions" ], "space-before-function-paren": { "severity": "off" }, "eofline": false, "no-shadowed-variable": false }}
复制代码
2.使用 axios
接口域名放在.env 文件里 process.env.VUE_APP_BASE_URL
封装一个 axios
import axios from 'axios';import Qs from 'qs';
import { hideLoading, showLoading } from '../units/index'const instance: any = axios.create({ baseURL: process.env.VUE_APP_BASE_URL, timeout: 1000, validateStatus: function (status) { return status >= 200 && status < 300; }, transformRequest: [function (data) { // 对 data 进行任意转换处理 return Qs.stringify(data) }],});
export enum ApiRequestMethod { get = 'get', post = 'post', delete = 'delete', put = 'put',}export interface ApiRequestParam { url: string; method?: ApiRequestMethod; data?: object; params?: object; headers?: object; timeout?: number; responseType?: string; [propName: string]: any;}
// 添加请求拦截器instance.interceptors.request.use((config: any) => { let { use } = config; // 1,加载loading // 2.配置Token // 在发送请求之前做些什么 // config.headers.Authorization = Token; console.log(config); if (use.autoLoading) { showLoading(); } return config;}, (error: any) => { // 对请求错误做些什么 return Promise.reject(error);});
instance.interceptors.response.use((response: any) => { let { data, config } = response; // 对响应数据做点什么 console.log(response, 'succ'); hideLoading() // 是否请求成功 if (data.statusCode === '000000') { return Promise.resolve(response); } else { data.desc ? alert(data.desc) : config.use.autoTipError ? alert(config.use.autoTipError) : ''; return Promise.reject(response); } }, (error: any) => { // 1.关闭loading // 2.全局处理报错信息 const { response, status } = error if (response) { // 3.服务器的状态码处理(validateStatus配置相关):401 500 switch (status) { case 401: // 未登录
break;
case 403: // 拒绝访问
break; case 404: // 请求失败
break; } } else { // 是否未连接网络 if (!window.navigator.onLine) { alert('请检查网络'); } } return Promise.reject(error);});
export const apiRequest = ( params: ApiRequestParam, autoLoading: boolean = true, autoTipError: string = '', ) => { console.log(params, autoLoading, autoTipError, Qs.stringify({a:'9p掘金'})); instance.defaults.use = { autoLoading, autoTipError } return instance(params)}
复制代码
使用封装好的接口
// xx.tsimport { ApiRequestMethod, apiRequest } from '../axios';const index = (params: any) => { return apiRequest({ params, method: ApiRequestMethod.get, url: '/common/weather/get15DaysWeatherByArea?apiKey=ZZGPUJJ6eaae98f6de9f6019aab2909ef47612004bf3cd0', }, false, 'errrrrr')};
export default { index,};
// xxx.vue使用封装好的接口import {getToken} from 'xx'getToken({}).then().catch((err) =>{})
复制代码
3.使用 router
普通路由
{ path: '/vip', name: 'vip', component: () => import(/* webpackChunkName: "about" */ '../views/About.vue') },复制代码
2.嵌套路由
{ path: '/test', name: 'test', component: () => import(/* webpackChunkName: "test" */ '../views/test.vue') children: [ { path: '', // 第一个展示为空 name: '', component: '', } ] }, test.vue<templeat> <p>我是test.vue组件</p> <router-view> // 渲染子组件里面的内容</templeat>复制代码
3.动态路由匹配
{ path: '/vip/:id', name: 'vip', component: () => import(/* webpackChunkName: "about" */ '../views/About.vue') },
// xx.vue this.$router.push({ name: 'vip', // 路由名称,唯一 params: { id: '123' } // 动态匹配id: http://localhost:8080/#/vip/123 })复制代码
4.动态传参 query
// 带查询参数,变成 /register?plan=privatethis.$router.push({ name: 'vip', query: { plan: 'private' }})复制代码
5.操作路由的几种方式
this.$router.push() // 入栈this.$router.replace({}) // 替换当前路由this.$router.router.go(n) // 前进后退步数,更换指针位置,与 window.history.go(n)相似复制代码
6.路由组件传参
布尔模式:用于动态路由,模板渲染对象模式:静态的时候有用函数模式: { path: '/search', component: SearchUser, props: route => { return { // 返回参数 } } }复制代码
7.导航守卫
路由守卫: 写在routes配置里面 beforeEnter:路由只独享这一个钩子,在rutes里配置;用的少
组件内的守卫: 注意:这类路由钩子是写在组件内部: beforeRouteEnter(to, from, next) 进入路由前,此时实例还没创建,无法获取到zhis beforeRouteUpdate (to, from, next) 路由更新时触发的钩子函数 beforeRouteLeave(to, from, next) 离开当前路由,此时可以用来保存数据,或数据初始化,或关闭定时器等等
全局守卫:router.beforeEach 全局前置守卫 // 这个用的多router.beforeResolve 全局解析守卫(2.5.0+) 在beforeRouteEnter调用之后调用.router.afterEach 全局后置钩子 进入路由之后 注意:不支持next(),只能写成这种形式router.afterEach((to, from) => {});
复制代码
8.路由元信息:meta:any
9.滚动行为
// 这个功能只在支持 history.pushState 的浏览器中可用 scrollBehavior (to, from, savedPosition) { // 浏览器的前进后退才会触发 if (savedPosition) { return savedPosition; } else if (to.hash) { // 跳到hash的位置 return { selector: to.hash, behavior: 'smooth', } } else { return { x: 0, y: 0, } } // return 期望滚动到哪个的位置 }
复制代码
10.使用 vue-class-component 提供的 Component.registerHooks 来注册钩子
import Component from 'vue-class-component'
Component.registerHooks([ 'beforeRouteEnter', 'beforeRouteLeave', 'beforeRouteUpdate' // for vue-router 2.2+])
xx.vuebeforeRouteEnter(to: unknown, from: unknown, next: any) { console.log('beforeRouteEnter',to) next() // 在渲染该组件的对应路由被 confirm 前调用 // 不!能!获取组件实例 `this` // 因为当守卫执行前,组件实例还没被创建}复制代码
4.使用 vuex
安装引用
import Vue from 'vue'import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({ state: { count: 0 }, getters(){ name(state){ return val; } }, mutations: { increment (state, val) { state.count++ } }, // 异步操作 actions: { name(ctx, obj){} }})
xx.vue使用辅助函数 jsimport { mapState, mapMutations, mapGetters } from 'vuex'computed: { ...mapState([ // 映射 this.count 为 store.state.count 'count' ])}methods: { ...mapMutations([name]), ...mapGetters([name]) // 类似于计算属性,组合,全局数据}复制代码
2.命名空间
const moduleA = { namespaced: true, state: () => ({ ... }), mutations: { ... }, actions: { ... }, getters: { ... }}
const moduleB = { namespaced: true, state: () => ({ ... }), mutations: { ... }, actions: { ... }}
const store = new Vuex.Store({ modules: { a: moduleA, b: moduleB }})
xx.vue使用computed: { ...mapState('some/nested/module', { a: state => state.a, b: state => state.b })},methods: { ...mapActions('some/nested/module', [ 'foo', // -> this.foo() 'bar' // -> this.bar() ])}复制代码
3.在 ts 中使用 vuex-class
import Vue from 'vue'import Component from 'vue-class-component'import { State, Getter, Action, Mutation, namespace} from 'vuex-class' const someModule = namespace('path/to/module') @Componentexport class MyComp extends Vue { @State('foo') stateFoo @State(state => state.bar) stateBar @Getter('foo') getterFoo @Action('foo') actionFoo @Mutation('foo') mutationFoo @someModule.Getter('foo') moduleGetterFoo // If the argument is omitted, use the property name // for each state/getter/action/mutation type @State foo @Getter bar @Action baz @Mutation qux created () { this.stateFoo // -> store.state.foo this.stateBar // -> store.state.bar this.getterFoo // -> store.getters.foo this.actionFoo({ value: true }) // -> store.dispatch('foo', { value: true }) this.mutationFoo({ value: true }) // -> store.commit('foo', { value: true }) this.moduleGetterFoo // -> store.getters['path/to/module/foo'] }}复制代码
划线
评论
复制
发布于: 2021 年 05 月 06 日阅读数: 29
版权声明: 本文为 InfoQ 作者【★】的原创文章。
原文链接:【http://xie.infoq.cn/article/62f414cdbb685d308022e0219】。文章转载请联系作者。
★
关注
还未添加个人签名 2020.08.05 加入
还未添加个人简介











评论