前言
Vue3.x 即将来袭,使用 TypeScirpt 重构,TypeScript 将成为 vue 社区的标配,出于一名程序员的焦虑,决定现在 Vue2.6.x 踩一波坑。
vue 官方文档已经简略地对 typescript 的支持进行了介绍,我们使用 Vue Cli3 直接生成项目
创建项目
"htmlcode">
╭─~/otherEWokspace ╰─"htmlcode">╭─~/otherEWokspace/ts-vuex-demo "htmlcode">{ "compilerOptions": { "target": "esnext", "module": "esnext", "strict": true, "jsx": "preserve", // 开启对 jsx 的支持 "importHelpers": true, "moduleResolution": "node", "experimentalDecorators": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "sourceMap": true, "baseUrl": ".", "types": [ "webpack-env", "jest" ], "paths": { "@/*": [ "src/*" ] }, "lib": [ "esnext", "dom", "dom.iterable", "scripthost" ] }, "include": [ "src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "tests/**/*.ts", "tests/**/*.tsx" ], "exclude": [ "node_modules" ] }
- target --- 被 tsc 编译后生成 js 文件代码风格
- module --- 被 tsc 编译后生成 js 文件的模块风格
- lib --- 原 ts 文件支持的代码库
我们来看一下示例:
// index.ts export const Greeter = (name: string) => `Hello ${name}`;"module": "commonjs", "target": "es5"
// index.js "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Greeter = function (name) { return "Hello " + name; };"module": "es2015", "target": "es5"
// index.js export var Greeter = function (name) { return "Hello " + name; };"module": "es2015", "target": "es6"
// index.js export const Greeter = (name) => `Hello ${name}`;"module": "commonjs", "target": "es6"
// index.js "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Greeter = (name) => `Hello ${name}`;如果lib没有指定默认注入的库的列表。默认注入的库为:
- 针对于 target:ES5:DOM,ES5,ScriptHost
- 针对于 target:ES6:DOM,ES6,DOM.Iterable,ScriptHost
tslint
类似于 eslint ,对 ts 代码进行检测。
vscode 需要安装tslint 插件 ,并在 vscode 的用户配置中加入以下配置,用来在保存时自动解决 ts 的错误。
// settings.json "editor.codeActionsOnSave": { "source.fixAll.tsLint": true }"_blank" href="https://marketplace.visualstudio.com/items">prettier 插件,对项目进行代码风格的统一和规范
npm i tslint-config-prettier -D添加 tslint.json extends 字段如下:
"extends": ["tslint:recommended", "tslint-config-prettier"]设置 vscode
- 勾选 tslintIntegration ,使 prittier 支持格式化 ts 文件
- "editor.formatOnSave": true 保存时自动格式化
也可以使用 shift + option + f 进行格式化
在根目录下添加 .prttierrc 文件 (应对 prittier 格式化 vue 文件中的 ts 文件时,没办法使用 tslint 规则进行格式化,需要对它单独处理,以免 tslint 报错)
{ "singleQuote": true }shims-vue.d.ts
declare module "*.vue" { import Vue from "vue"; export default Vue; }声明所有以 .vue 结尾的文件,默认导入 vue ,默认导出 Vue,用以在项目中ts文件识别 .vue 结尾文件。
在 main.ts 中,引入一个 vue 组件必须以 .vue 结尾。
import Vue from 'vue'; import App from './App.vue'; import router from './router'; import store from './store'; Vue.config.productionTip = false; new Vue({ router, store, render: (h) => h(App), }).$mount('#app');Vue class
vue-property-decorator
写一个 todolist 组件顺便来介绍 vue-property-decorator,为了方便页面构建,使用 element-ui
element-ui 使用 ts 开发,默认有 .d.ts 的声明文件
npm i element-ui// main.ts import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; Vue.use(ElementUI);在 /src/compenents/ 新建 todoList.vue , 代码如下:
<template> <div class="todo_list"> <el-card class="box-card"> <div slot="header"> <el-row :gutter="18"> <el-col :span="18"> <el-input v-model="todo" placeholder="请输入内容" ></el-input> </el-col> <el-col :span="2"> <el-button type="primary" icon="el-icon-circle-plus-outline" @click="addItem" >add</el-button> </el-col> </el-row> </div> <div v-for="(item,index) in todoList" :key="item" class="text item" @click="removeItem(index)" >{{ item }}</div> </el-card> <label class="text" style="margin-top:20px" >{{todoLength}} records</label> </div> </template><script lang="ts"> import { Component, Prop, Vue, Emit } from 'vue-property-decorator'; @Component export default class HelloWorld extends Vue { public todo: string = ''; @Prop({ default: [] }) private readonly todoList!: string[]; get todoLength(): number { return this.todoList.length; } @Emit() private addItem(): string | undefined { if (this.todo) { return this.todo; } } @Emit('removeItem') private removeItem(index: number): number { return index; } } </script><!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped lang="scss"> .todo_list { display: flex; justify-content: center; flex-direction: column; align-items: center; .box-card { width: 480px; } .text { font-size: 14px; text-align: left; } .item { margin-bottom: 18px; } } </style>对 ts 代码的用法指出以下几点:
- prop 建议写成 xxx!: type 的形式,不然要写成 xxx : type | undefined
- @Emit 可以不传参数,emit 出去的事件名默认是修饰的函数名,但是当函数的命名规则为 camelCase 时需要注册的函数名必须是 kebab-case
- @Emit 传参是由修饰的函数 return value
改造 Home.vue 如下:
<template> <div class="home"> <todoList :todoList="[]" @add-item="addTodoList" @removeItem="addTodoLisItem" /> </div> </template> <script lang="ts"> import { Component, Vue } from 'vue-property-decorator'; import todoList from '@/components/todoList.vue'; // @ is an alias to /src import { State, Getter, Action } from 'vuex-class'; @Component({ components: { todoList } }) export default class Home extends Vue { public addTodoList(val: string) { console.log(val); } private created() { console.log('i add life cycle funciton -- created'); } private addTodoLisItem(index: number) { console.log(index); } } </script>Vuex
有关 ts 中的 vuex 的写法要从vuex-class 说起,在 官方的 vue-property-decorator 中也推荐使用该库。
npm i vuex-class在 src 文件夹中新建 store 文件夹, 在 store 新建 index.ts,todoList.ts
// index.ts import Vue from 'vue'; import Vuex from 'vuex'; import todolist from './todoList'; Vue.use(Vuex); export default new Vuex.Store({ modules: { todolist } });// todoList.ts import { Commit, Dispatch, GetterTree, ActionTree, MutationTree } from 'vuex'; const ADD_TODOLIST = 'ADD_TODOLIST'; const REMOVE_ITEM = 'REMOVE_ITEM'; export interface RootState { version: string; } interface Payload { [propName: string]: any; } interface TodoListType { todoList: string[]; } interface Context { commit: Commit; dispatch: Dispatch; } const dataSource: TodoListType = { todoList: [] }; const getters: GetterTree<TodoListType, RootState> = { getTodoList(state: TodoListType): string[] { return state.todoList; } }; const mutations: MutationTree<TodoListType> = { ADD_TODOLIST: (state: TodoListType, item: string) => { console.log(item); state.todoList.push(item); }, REMOVE_ITEM: (state: TodoListType, removeIndex: number) => { state.todoList = state.todoList.filter((item: string, index: number) => { return removeIndex !== index; }); } }; const actions: ActionTree<TodoListType, RootState> = { addList: async ({ commit }: Context, item: string) => { await Promise.resolve( setTimeout(() => { commit(ADD_TODOLIST, item); }, 100) ); }, removeItem: async ({ commit }: Context, { index }: Payload) => { await Promise.resolve( setTimeout(() => { commit(REMOVE_ITEM, index); }, 100) ); } }; export default { namespaced: true, state: dataSource, getters, mutations, actions };删除原来与 main.ts 同级的 store.ts
对 todoList.ts 需要注意以下几点:
- 对于 getters 、mutations 、actions 响应的 type 可以使用 command + 左键点击 进入声明文件查看,也可以不指定 type ,但是建议写上
- 对于 Payload 解构 tslint 报错的,可以为 Payload 添加类型声明
interface Payload { [propName: string]: any; }代码中的 dataSource 本意为 state ,但是不能用 state 命名,tslint 会和形参 state 冲突
改造 /views/Home.vue 如下:
<template> <div class="home"> <todoList :todoList="todoList" @add-item="addTodoList" @removeItem="addTodoLisItem" /> </div> </template> <script lang="ts"> import { Component, Vue } from 'vue-property-decorator'; import todoList from '@/components/todoList.vue'; // @ is an alias to /src import { State, Getter, Action } from 'vuex-class'; @Component({ components: { todoList } }) export default class Home extends Vue { @State(state => state.todolist.todoList) private todoList!: string[]; @Action('todolist/addList') private addList!: (val: string) => void; @Action('todolist/removeItem') private removeItem!: (index: number) => void; public addTodoList(val: string) { console.log(val); this.addList(val); } private created() { console.log('i add life cycle funciton -- created'); } private addTodoLisItem(index: number) { this.removeItem(index); } } </script>有关 vuex-class 的调用有以下几点注意
- @State 如果有分模块,必须使用 state => state.xxx.xxx 的形式获取state
- @Action 中函数的声明,形参必须和方法保持一致
所有的代码到此为止,使用 npm run serve 即可查看应用,保留原有 routes 文件,保持应用的健壮性。
写在最后
- 本文只是介绍了一个简单构建 ts-vue 应用的例子,对于框架的健壮和可扩展性有需要慢慢考虑,比如 webpack 的配置,适应测试,生产等各种环境的区分,axois 的封装,等等。
- 对于vue + ts 的配方,文章还有很多 vue 的特性没有去兼容,比如 this.refs 的使用,比如 vue-property-decorator 其他特性的使用。
- 由于官方文档对 ts 的介绍有限,所以以上代码肯定有不足的地方,希望大家指正。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!
昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。
这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。
而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?
更新日志
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]