vue-cli3.0 搭建项目模版教程(ts+vuex+axios)
发布日期:2022-02-26 00:17:45 浏览次数:9 分类:技术文章

本文共 19761 字,大约阅读时间需要 65 分钟。

vue-cli3.0 搭建项目模版教程(ts+vuex+axios)

1.本文模版不适用于小型项目,两三个页面的也没必要用vue 2.对typescript、vue全家桶能够掌握和运用

此次项目模版主要涉及的技术框架: vue2.5 vuex3.0 vue-router3.0 axios typescript3.2 Tip: 由于vue-cli3.0帮我们简化了webpack的配置,我们只需要在根目录下的vue.config.js文件的chainWebpack进行配置即可。

接下来进入正题(前提是你已经安装并配置好了node环境)

一.初始化项目 安装vue-cli3.0 如果你之前安装的是vue-cli2.0版本的,那么你需要先卸载2.0版本,再安装3.0版本

// cnpm 为淘宝镜像 cnpm uninstall vue-cli -g // 卸载 cnpm install -g @vue/cli // 安装新版本 创建项目 vue create vue-cli3-tpl 选择Manually select features回车,按照下图所示选中(空格选中)回车安装插件

然后一路回车,放一下配置图 配置图

等安装完之后,进入项目并启动项目 cd vue-cli3-tpl cnpm run serve 启动后显示如下,第一步完成。

启动成功显示界面 二.删除不必要的文件 1.删除assets、components、views目录下的所有文件。 2.删除./src/store.ts。 3.删除./src/router.ts

三.添加并配置文件 1.添加文件夹并创建文件 1.在根目录下创建scripts文件夹,并添加template.js、component.js 2.在./src目录下创建api文件夹 3.在./src目录下创建config文件夹,并添加index.ts、requestConfig.ts 4.在./src目录下创建router文件夹,并添加index.ts、router.ts 5.在./src目录下创建store文件夹,并添加index.ts和module文件夹 6.在./src目录下创建types文件夹,并添加index.ts、components文件夹和views文件夹 7.在./src目录下创建utils文件夹,并添加common.ts和request.ts 8.在./src/assets目录下创建images和scss两个文件夹,并在scss文件夹下添加common.scss和variables.scss

2.配置文件 首先配置一下根目录下tslint.json,编码习惯还是根据团队的要求来,我自己关闭了很多在我看来很鸡肋的东西,下面是个人的配置,仅供参考

{ "defaultSeverity": "warning", "extends": [ "tslint:recommended" ], "linterOptions": { "exclude": [ "node_modules/**" ] }, "rules": { "quotemark": false, // 字符串文字需要单引号或双引号。 "indent": false, // 使用制表符或空格强制缩进。 "member-access": false, // 需要类成员的显式可见性声明。 "interface-name": false, // 接口名要求大写开头 "ordered-imports": false, // 要求将import语句按字母顺序排列并进行分组。 "object-literal-sort-keys": false, // 检查对象文字中键的排序。 "no-consecutive-blank-lines": false, // 不允许连续出现一个或多个空行。 "no-shadowed-variable": false, // 不允许隐藏变量声明。 "no-trailing-whitespace": false, // 不允许在行尾添加尾随空格。 "semicolon": false, // 是否分号结尾 "trailing-comma": false, // 是否强象添加逗号 "eofline": false, // 是否末尾另起一行 "prefer-conditional-expression": false, // for (... in ...)语句必须用if语句过滤 "curly": true, //for if do while 要有括号 "forin": false, //用for in 必须用if进行过滤 "import-blacklist": true, //允许使用import require导入具体的模块 "no-arg": true, //不允许使用 argument.callee "no-bitwise": true, //不允许使用按位运算符 "no-console": false, //不能使用console "no-construct": true, //不允许使用 String/Number/Boolean的构造函数 "no-debugger": true, //不允许使用debugger "no-duplicate-super": true, //构造函数两次用super会发出警告 "no-empty": true, //不允许空的块 "no-eval": true, //不允许使用eval "no-floating-promises": false, //必须正确处理promise的返回函数 "no-for-in-array": false, //不允许使用for in 遍历数组 "no-implicit-dependencies": false, //不允许在项目的package.json中导入未列为依赖项的模块 "no-inferred-empty-object-type": false, //不允许在函数和构造函数中使用{}的类型推断 "no-invalid-template-strings": true, //警告在非模板字符中使用${ "no-invalid-this": true, //不允许在非class中使用 this关键字 "no-misused-new": true, //禁止定义构造函数或new class "no-null-keyword": false, //不允许使用null关键字 "no-object-literal-type-assertion": false, //禁止object出现在类型断言表达式中 "no-return-await": true, //不允许return await "arrow-parens": false, //箭头函数定义的参数需要括号 "adjacent-overload-signatures": false, // Enforces function overloads to be consecutive. "ban-comma-operator": true, //禁止逗号运算符。 "no-any": false, //不需使用any类型 "no-empty-interface": true, //禁止空接口 {} "no-internal-module": true, //不允许内部模块 "no-magic-numbers": false, //不允许在变量赋值之外使用常量数值。当没有指定允许值列表时,默认允许-1,0和1 "no-namespace": [true, "allpw-declarations"], //不允许使用内部modules和命名空间 "no-non-null-assertion": true, //不允许使用!后缀操作符的非空断言。 "no-parameter-reassignment": true, //不允许重新分配参数 "no-reference": true, // 禁止使用/// <reference path=> 导入 ,使用import代替 "no-unnecessary-type-assertion": false, //如果类型断言没有改变表达式的类型就发出警告 "no-var-requires": false, //不允许使用var module = require("module"),用 import foo = require('foo')导入 "prefer-for-of": true, //建议使用for(..of) "promise-function-async": false, //要求异步函数返回promise "max-classes-per-file": [true, 2], // 一个脚本最多几个申明类 "variable-name": false, "prefer-const": false // 提示可以用const的地方 } } 1.打开./scripts/template.js,并添加以下内容

/*

  • @Description: 页面快速生成脚本
  • @Date: 2018-12-06 10:28:08
  • @LastEditTime: 2018-12-10 09:43:50
  • / const fs = require('fs') const path = require('path') const basePath = path.resolve(__dirname, '../src')

const dirName = process.argv[2] const capPirName = dirName.substring(0, 1).toUpperCase() + dirName.substring(1) if (!dirName) { console.log('文件夹名称不能为空!') console.log('示例:npm run tep ${capPirName}') process.exit(0) }

/**

  • @msg: vue页面模版
  • / const VueTep = `
    {
    {data.pageName}}
<script lang="ts" src="./${dirName}.ts"></script>

`

// ts 模版 const tsTep = `import { Component, Vue } from "vue-property-decorator" import { Getter, Action } from "vuex-class" import { ${capPirName}Data } from '@/types/views/${dirName}.interface' // import { } from "@/components" // 组件

@Component({}) export default class About extends Vue { // Getter // @Getter ${dirName}.author

// Action // @Action GET_DATA_ASYN

// data data: ${capPirName}Data = { pageName: '${dirName}' }

created() { // }

activated() { // }

mounted() { // }

// 初始化函数 init() { // }

} `

// scss 模版 const scssTep = `@import "@/assets/scss/variables.scss";

.${dirName}-wrap { width: 100%; } `

// interface 模版 const interfaceTep = `// ${dirName}.Data 参数类型 export interface ${capPirName}Data { pageName: string }

// VUEX ${dirName}.State 参数类型 export interface ${capPirName}State { data?: any }

// GET_DATA_ASYN 接口参数类型 // export interface DataOptions {}

`

// vuex 模版 const vuexTep = `import { ${capPirName}State } from '@/types/views/${dirName}.interface' import { GetterTree, MutationTree, ActionTree } from 'vuex' import * as ${capPirName}Api from '@/api/${dirName}'

const state: ${capPirName}State = { ${dirName}: { author: undefined } }

// 强制使用getter获取state const getters: GetterTree<${capPirName}State, any> = { author: (state: ${capPirName}State) => state.${dirName}.author }

// 更改state const mutations: MutationTree<${capPirName}State> = { // 更新state都用该方法 UPDATE_STATE(state: ${capPirName}State, data: ${capPirName}State) { for (const key in data) { if (!data.hasOwnProperty(key)) { return } state[key] = data[key] } } }

const actions: ActionTree<${capPirName}State, any> = { UPDATE_STATE_ASYN({ commit, state: ${capPirName}State }, data: ${capPirName}State) { commit('UPDATE_STATE', data) }, // GET_DATA_ASYN({ commit, state: LoginState }) { // ${capPirName}.getData() // } }

export default { state, getters, mutations, actions }

`

// api 接口模版 const apiTep = `import Api from '@/utils/request'

export const getData = () => { return Api.getData() }

`

fs.mkdirSync(${basePath}/views/${dirName}) // mkdir

process.chdir(${basePath}/views/${dirName}) // cd views fs.writeFileSync(${dirName}.vue, VueTep) // vue fs.writeFileSync(${dirName}.ts, tsTep) // ts fs.writeFileSync(${dirName}.scss, scssTep) // scss

process.chdir(${basePath}/types/views); // cd types fs.writeFileSync(${dirName}.interface.ts, interfaceTep) // interface

process.chdir(${basePath}/store/module); // cd store fs.writeFileSync(${dirName}.ts, vuexTep) // vuex

process.chdir(${basePath}/api); // cd api fs.writeFileSync(${dirName}.ts, apiTep) // api

process.exit(0) 2.打开./scripts/component.js,并添加以下内容

/*

  • @Description: 组件快速生成脚本
  • @Date: 2018-12-06 10:26:23
  • @LastEditTime: 2018-12-10 09:44:19
  • /

const fs = require('fs') const path = require('path') const basePath = path.resolve(__dirname, '../src')

const dirName = process.argv[2] const capPirName = dirName.substring(0, 1).toUpperCase() + dirName.substring(1) if (!dirName) { console.log('文件夹名称不能为空!') console.log('示例:npm run tep ${capPirName}') process.exit(0) }

/**

  • @msg: vue页面模版
  • / const VueTep = `
    {
    {data.componentName}}
<script lang="ts"> import { Component, Vue, Prop } from "vue-property-decorator" import { Getter, Action } from 'vuex-class' import { ${capPirName}Data } from '@/types/components/${dirName}.interface' // import { } from "@/components" // 组件 @Component({}) export default class About extends Vue { // prop @Prop({ required: false, default: '' }) name!: string // data data: ${capPirName}Data = { componentName: '${dirName}' } created() { // } activated() { // } mounted() { // } } </script>

`

// interface 模版 const interfaceTep = `// ${dirName}.Data 参数类型 export interface ${capPirName}Data { componentName: string }

`

fs.mkdirSync(${basePath}/components/${dirName}) // mkdir

process.chdir(${basePath}/components/${dirName}) // cd views fs.writeFileSync(${dirName}.vue, VueTep) // vue

process.chdir(${basePath}/types/components) // cd components fs.writeFileSync(${dirName}.interface.ts, interfaceTep) // interface

process.exit(0) 3.打开./src/config/index.ts,并添加以下内容

/**

  • 线上环境
  • / export const ONLINEHOST: string = '

/**

  • 测试环境
  • / export const QAHOST: string = '

/**

  • 线上mock
  • / export const MOCKHOST: string = '

/**

  • 是否mock
  • / export const ISMOCK: boolean = true

/**

  • 当前的host ONLINEHOST | QAHOST | MOCKHOST
  • / export const MAINHOST: string = ONLINEHOST

/**

  • 请求的公共参数
  • / export const conmomPrams: any = {}

/**

  • @description token在Cookie中存储的天数,默认1天
  • / export const cookieExpires: number = 1

4.打开./src/config/requestConfig.ts,并添加以下内容

export default { getData: '/mock/5c09ca373601b6783189502a/example/mock', // 随机数据 来自 easy mock } 5.打开./src/router/index.ts,并添加以下内容

import Vue from 'vue' import Router from 'vue-router' import routes from './router' import { getToken } from '@/utils/common'

Vue.use(Router)

const router = new Router({ routes, mode: 'history' })

// 登陆页面路由 name const LOGIN_PAGE_NAME = 'login'

// 跳转之前 router.beforeEach((to, from, next) => { const token = getToken() if (!token && to.name !== LOGIN_PAGE_NAME) { // 未登录且要跳转的页面不是登录页 next({ name: LOGIN_PAGE_NAME // 跳转到登录页 }) } else if (!token && to.name === LOGIN_PAGE_NAME) { // 未登陆且要跳转的页面是登录页 next() // 跳转 } else if (token && to.name === LOGIN_PAGE_NAME) { // 已登录且要跳转的页面是登录页 next({ name: 'index' // 跳转到 index 页 }) } else { if (token) { next() // 跳转 } else { next({ name: LOGIN_PAGE_NAME }) } } })

// 跳转之后 router.afterEach(to => { // })

export default router 6.打开./src/router/router.ts,并添加以下内容

/**

  • meta 可配置参数
  • @param {boolean} icon 页面icon
  • @param {boolean} keepAlive 是否缓存页面
  • @param {string} title 页面标题
  • / export default [ { path: '/', redirect: '/index' }, { path: '/login', name: 'login', component: () => import('@/views/login/login.vue'), meta: {
    icon: '',keepAlive: true,title: 'login'
    } }, { path: '/index', name: 'index', component: () => import('@/views/index/index.vue'), meta: {
    icon: '',keepAlive: true,title: 'index'
    } } ]

7.打开./src/store/index.ts,并添加以下内容

import Vue from 'vue' import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({ state: { // }, mutations: { // }, actions: { // }, modules: { // } })

8.打开./src/utils/common.ts,在此之前先下载js-cookie,并添加以下内容

// 下载js-cookie cnpm i js-cookie --S cnpm install @types/js-cookie --D /*

  • @Description: 公共函数
  • @Author: asheng
  • @Date: 2018-12-07 11:36:27
  • @LastEditors: asheng
  • @LastEditTime: 2018-12-12 13:37:30
  • /

import Cookies from 'js-cookie' import { cookieExpires } from '@/config' // cookie保存的天数

/**

  • @Author: asheng
  • @msg: 存取token
  • @param {string} token
  • / export const TOKEN_KEY: string = 'token' export const setToken = (token: string) => { Cookies.set(TOKEN_KEY, token, { expires: cookieExpires || 1 }) } export const getToken = () => { const token = Cookies.get(TOKEN_KEY) if (token) { return token } else { return false } }

/**

  • @param {String} url
  • @description 从URL中解析参数
  • / export const getParams = (url: string) => { const keyValueArr = url.split('?')[1].split('&') let paramObj: any = {} keyValueArr.forEach(item => { const keyValue = item.split('=') paramObj[keyValue[0]] = keyValue[1] }) return paramObj }

/**

  • 判断一个对象是否存在key,如果传入第二个参数key,则是判断这个obj对象是否存在key这个属性
  • 如果没有传入key这个参数,则判断obj对象是否有键值对
  • / export const hasKey = (obj: any, key: string | number) => { if (key) { return key in obj } else { const keysArr = Object.keys(obj) return keysArr.length } }

/**

  • @msg: 获取系统当前时间
  • @param {string} fmt 时间格式 具体看代码
  • @return: string
  • / export const getDate = (fmt: any) => { let time = '' const date = new Date() const o: any = { "M+": date.getMonth() + 1, // 月份 "d+": date.getDate(), // 日 "H+": date.getHours(), // 小时 "m+": date.getMinutes(), // 分 "s+": date.getSeconds(), // 秒 "q+": Math.floor((date.getMonth() + 3) / 3), // 季度 "S": date.getMilliseconds() // 毫秒 } if (/(y+)/.test(fmt)) { time = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length)) } for (const k in o) { if (new RegExp("(" + k + ")").test(fmt)) {
    time = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)))
    } } return time }

/**

  • @msg: 获取系统当前时间
  • @param {string} date 时间
  • @param {string} fmt 时间格式
  • @return: string
  • / export const formatDate = (date: any, fmt: string) => { let time = '' const o: any = { "M+": date.getMonth() + 1, // 月份 "d+": date.getDate(), // 日 "H+": date.getHours(), // 小时 "m+": date.getMinutes(), // 分 "s+": date.getSeconds(), // 秒 "q+": Math.floor((date.getMonth() + 3) / 3), // 季度 "S": date.getMilliseconds() // 毫秒 } if (/(y+)/.test(fmt)) { time = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length)) } for (const k in o) { if (new RegExp("(" + k + ")").test(fmt)) {
    time = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)))
    } } return time }

// copy in the 'fx-fuli' utils /**

  • 校验手机号是否正确
  • @param phone 手机号
  • /

export const verifyPhone = (phone: string | number) => { const reg = /^1[34578][0-9]{9}$/ const _phone = phone.toString().trim() let toastStr = _phone === '' ? '手机号不能为空' : !reg.test(_phone) && '请输入正确手机号' return { errMsg: toastStr, done: !toastStr, value: _phone } }

export const verifyStr = (str: string | number, text: string) => { const _str = str.toString().trim() const toastStr = _str.length ? false : 请填写${text}~ return { errMsg: toastStr, done: !toastStr, value: _str } }

// 截取字符串 export const sliceStr = (str: any, sliceLen: number) => { if (!str) { return '' } let realLength = 0 const len = str.length let charCode = -1 for (let i = 0; i < len; i++) { charCode = str.charCodeAt(i) if (charCode >= 0 && charCode <= 128) { realLength += 1 } else { realLength += 2 } if (realLength > sliceLen) { return ${str.slice(0, i)}... } }

return str }

/**

  • JSON 克隆
  • @param {Object | Json} jsonObj json对象
  • @return {Object | Json} 新的json对象
  • / export function objClone(jsonObj: any) { let buf: any if (jsonObj instanceof Array) { buf = [] let i = jsonObj.length while (i--) {
    buf[i] = objClone(jsonObj[i])
    } return buf } else if (jsonObj instanceof Object) { buf = {} for (let k in jsonObj) {
    buf[k] = objClone(jsonObj[k])
    } return buf } else { return jsonObj } } 9.打开./src/utils/request.ts,先下载axios,并添加以下内容

// 下载axios cnpm i axios --S import axios, { AxiosResponse, AxiosRequestConfig } from 'axios' import { MAINHOST, ISMOCK, conmomPrams } from '@/config' import requestConfig from '@/config/requestConfig' import { getToken } from '@/utils/common' import router from '@/router'

declare type Methods = "GET" | "OPTIONS" | "HEAD" | "POST" | "PUT" | "DELETE" | "TRACE" | "CONNECT" declare interface Datas { method?: Methods [key: string]: any } const baseURL = process.env.NODE_ENV === 'production' ? MAINHOST : location.origin const token = getToken()

class HttpRequest { public queue: any // 请求的url集合 public constructor() { this.queue = {} } destroy(url: string) { delete this.queue[url] if (!Object.keys(this.queue).length) { // hide loading } } interceptors(instance: any, url?: string) { // 请求拦截 instance.interceptors.request.use((config: AxiosRequestConfig) => { // 添加全局的loading... if (!Object.keys(this.queue).length) { // show loading } if (url) { this.queue[url] = true } return config }, (error: any) => { console.error(error) }) // 响应拦截 instance.interceptors.response.use((res: AxiosResponse) => { if (url) { this.destroy(url) } const { data, status } = res if (status === 200 && ISMOCK) { return data } // 如果是mock数据,直接返回 if (status === 200 && data && data.code === 0) { return data } // 请求成功 return requestFail(res) // 失败回调 }, (error: any) => { if (url) { this.destroy(url) } console.error(error) }) } async request(options: AxiosRequestConfig) { const instance = axios.create() await this.interceptors(instance, options.url) return instance(options) } }

// 请求失败 const requestFail = (res: AxiosResponse) => { let errStr = '网络繁忙!' // token失效重新登陆 if (res.data.code === 1000001) { return router.replace({ name: 'login' }) }

return { err: console.error({ code: res.data.errcode || res.data.code, msg: res.data.errmsg || errStr }) } }

// 合并axios参数 const conbineOptions = (_opts: any, data: Datas, method: Methods): AxiosRequestConfig => { let opts = _opts if (typeof opts === 'string') { opts = { url: opts } } const _data = { ...conmomPrams, ...opts.data, ...data } const options = { method: opts.method || data.method || method || 'GET', url: opts.url, header: { 'user-token': token }, baseURL } return options.method !== 'GET' ? Object.assign(options, { data: _data }) : Object.assign(options, { params: _data }) }

const HTTP = new HttpRequest()

/**

  • 抛出整个项目的api方法

  • / const Api = (() => { const apiObj: any = {} const requestList: any = requestConfig const fun = (opts: AxiosRequestConfig | string) => { return async (data = {}, method: Methods = "GET") => {

    if (!token) {  console.error('No Token')  return router.replace({ name: 'login' })}const newOpts = conbineOptions(opts, data, method)const res = await HTTP.request(newOpts)return res

    } } Object.keys(requestConfig).forEach((key) => { apiObj[key] = fun(requestList[key]) })

    return apiObj })()

export default Api as any

10.打开./src/main.ts,引用common.scss

import "@/assets/scss/common.scss" 11.打开./src/App.vue,按照如下修改(未贴代码表示不变)

12.还有非常重要的一步,打开根目录下的vue.config.js,如果没有就自己创建一个,放在根目录下,并添加以下内容

const path = require('path')

const resolve = dir => { return path.join(__dirname, dir) }

// 线上打包路径,请根据项目实际线上情况 const BASE_URL = process.env.NODE_ENV === 'production' ? '/' : '/'

module.exports = { baseUrl: BASE_URL, outputDir: 'dist', // 打包生成的生产环境构建文件的目录 assetsDir: '', // 放置生成的静态资源路径,默认在outputDir indexPath: 'index.html', // 指定生成的 index.html 输入路径,默认outputDir pages: undefined, // 构建多页 productionSourceMap: false, // 开启 生产环境的 source map? chainWebpack: config => { // 配置路径别名 config.resolve.alias .set('@', resolve('src')) .set('_c', resolve('src/components')) }, css: { modules: false, // 启用 CSS modules extract: true, // 是否使用css分离插件 sourceMap: false, // 开启 CSS source maps? loaderOptions: {} // css预设器配置项 }, devServer: { port: 8080, // 端口 proxy: ' // 设置代理 } } 13.打开根目录下的package.json,在scripts中添加如下代码

"scripts": { ... "tep": "node scripts/template", "com": "node scripts/component" } 四.编写业务代码 1.编写page页 运行我们之前添加的脚本命令,创建page,也就是运行之前写的template.js这个脚本,实现快速创建我们所需要的page模版,而不需要一个一个的再创建,大大节省了时间,如果不用用脚本跑也是可以的,分别需要创建以下文件夹:

在views文件夹下创建login文件夹,再向login文件夹下添加login.vue、login.ts、login.scss 在./src/api下添加login.ts 在./src/store/module下添加login.ts 在./src/types/views下添加login.interface.ts 是不是非常繁琐,还可能搞错(不推荐,浪费时间 0.0),而使用脚本只需要在命令行敲一条命令搞定(推荐)如下(根据demo需求,我们创建两个页面index、login):

cnpm run tep index cnpm run tep login 打开./src/views/login/login.ts,发现报错,没有安装模块vuex-class,安装一下就好了

cnpm i vuex-class --S 再运行创建组件脚本,随意创建一个test组件

cnpm run com test ok,这时候发现./src/components目录下创建了test组件,为了引用组件更方便看起来更优雅,我们在./src/components目录下添加一个index.ts,把所有组件都引入到这里,作为一个中转文件,如下:

import Test from './test/test.vue'

export { Test } 引用组件 上面创建好了组件后,打开./src/views/login/login.ts,如下引用:

import { Test } from "@/components" // 组件

@Component({ components: { Test } }) 在./src/views/login/login.vue中添加组件

这时候页面显示为如下:

组件示意图 调用http请求示例 最后再说一下怎么调用http请求吧,在这之前,先重启一遍服务

cnpm run serve 按照我的步骤来,启动是不会报错的,如果报错,那么可以留言看到会回复,或者重新走一遍。 没问题的话,我们按照如下步骤: 1.打开./src/config/requestConfig.ts文件添加接口,由于我们之前的添加过了,那么我们进行下一步。 2.打开./src/api/login.ts文件添加请求函数,我们之前也写好了,跳过。 3.进入./src/store/module/login.ts文件,把GET_DATA_ASYN函数的注释打开。 4.在./src/store/index.ts中的module添加login,如下:

// modules import Login from './module/login' import Index from './module/index'

export default new Vuex.Store({ ... modules: { Login, Index } } 完成上述动作后就可以在任意页面调用了,我们打开./src/views/index/index.ts,如下调用:

export default class About extends Vue { @Action GET_DATA_ASYN

created() { this.GET_DATA_ASYN() } }

转载地址:https://blog.csdn.net/tmatende/article/details/109541101 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Linux umask文件创建时的权限的缺省模式
下一篇:SpringBoot 三招组合拳,手把手教你打出优雅的后端接口

发表评论

最新留言

逛到本站,mark一下
[***.202.152.39]2024年04月14日 09时00分21秒