前端项目配置 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.ts
import { 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=private
this.$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.vue
beforeRouteEnter(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使用辅助函数 js
import { 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')
@Component
export 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 加入
还未添加个人简介
评论