Vue + TS 开发应用
使用vue-cli3创建项目,增加TypeScript
(*) Babel
(*) TypeScript
( ) Progressive Web App (PWA) Support
(*) Router
(*) Vuex
(*) CSS Pre-processors
(*) Linter / Formatter
1
2
3
4
5
6
7
2
3
4
5
6
7
使用less和tslint即可
这里你会看到和普通生成js的项目有些不同
- 1.shims-tsx.d.ts,允许你以.tsx结尾的文件,在Vue项目中编写jsx代码
- 2.shims-vue.d.ts TypeScript识别.vue 文件
一.更新ts路由文件
import Vue from 'vue';
import Router from 'vue-router';
import Todo from './views/Todo.vue';
Vue.use(Router);
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/',
name: 'todo',
component: Todo, // 访问/ 的时候显示todo组件
},
{
path: '/list',
name: 'list', // 访问/list时显示 列表组件
component: () => import(/* webpackChunkName: "List" */ './views/List.vue'),
},
],
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
二.在components下新增Todo.vue
<template>
<div>
<ul>
<li v-for="(item,index) in lists" :key="index">
<span v-if="currentIndex !== index">{{item.text}}</span>
<input type="text" v-else />
</li>
</ul>
</div>
</template>
<script lang="ts">
// Component来注册组件
import { Component, Vue } from "vue-property-decorator";
@Component
export default class Todo extends Vue {
public currentIndex = -1;
public lists = [ // 声明数据列表
{
text: "睡觉 呼呼~~~",
complete: false
},
{
text: "玩游戏 呼呼~~~",
complete: false
}
];
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
三.JSX编写todo-item组件
属性传递(@Prop)
import { Component, Prop, Vue } from 'vue-property-decorator';
interface Item {
text: string;
complete: boolean;
}
@Component
export default class TodoItem extends Vue {
// 属性校验
@Prop(Object) public item!: Item; // 循环的每一项
@Prop(Number) public index!: number; // 当前循环的索引
@Prop(Number) public currentIndex!: number; // 默认哪一项是当前编辑状态
public render() { // 组件需要拥有render方法
return <div>
{this.index !== this.currentIndex ? <span>{this.item.text}</span> : <input />}
</div>;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 在Todo中引入TodoItem组件
<li v-for="(item,index) in lists" :key="index">
<TodoItem :item="item" :index="index" :currentIndex="currentIndex"></TodoItem>
</li>
1
2
3
4
2
3
4
四.引入elementUI
// 在main.js中引入elementUI
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
1
2
3
4
2
3
4
五.使用elementUI
public editingContent = ''; // 编辑的值
public handleChange(value: string) {
this.editingContent = value;
}
protected render() {
return <li>
{this.index === this.currentIndex ?
<div>
<el-input value={this.editingContent} size='small' on-input={this.handleChange} style={{ width: '200px' }}></el-input>
<el-button type='primary' size='small' icon='el-icon-check'></el-button>
<el-button type='danger' size='small' icon='el-icon-close'></el-button>
</div>
: <div>
<span class='content'>{this.item.text}</span>
<el-button type='default' size='small' icon='el-icon-edit'></el-button>
</div>
}
</li >;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
六.组件间通信(@Emit)
实现编辑功能
<TodoItem
v-for="(item,index) in lists"
:key="index"
:item="item"
:index="index"
:currentIndex="currentIndex"
@edit="edit" // 像子组件传递edit事件
></TodoItem>
public edit(index: number) {
this.currentIndex = index;
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
子组件触发父组件的方法
public edit() {
this.$emit('edit', this.index);
}
<el-button type='primary' size='small' icon='el-icon-edit' on-click={this.edit}></el-button>
1
2
3
4
2
3
4
可以使用装饰器
import { Component, Prop, Vue, Emit } from 'vue-property-decorator';
@Emit('edit') // 如果发射的事件名和方法名相同,则可以省略
public edit() {
return this.index; // 返回的结果或作为向上传递的内容
}
1
2
3
4
5
2
3
4
5
实现保存功能
<TodoItem
v-for="(item,index) in lists"
:key="index"
:item="item"
:index="index"
:currentIndex="currentIndex"
@edit="edit"
@save="save"
@close="close"
></TodoItem>
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
将save方法传递给子组件
public save({index,content}:{index:number,content:string}){
this.lists[index].text = content;
this.close();
}
public close() {
this.currentIndex = -1;
}
1
2
3
4
5
6
7
2
3
4
5
6
7
子组件调用save方法
@Emit()
public save() {
return {
index: this.index,
content: this.editingContent
}
}
<el-button type='primary' on-click={this.save} size='small' icon='el-icon-check'></el-button>
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
七.数据的监控(@Watch)
这里我们可以监控索引的变化
import { Component, Prop, Vu
e, Emit, Watch } from 'vue-property-decorator';
@Watch('currentIndex')
public changeIndex() { // 索引变化讲内容赋予给当前编辑的内容
this.editingContent = this.item.text;
}
1
2
3
4
5
6
2
3
4
5
6
八.将数据迁移至vuex
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
list: [
{
text: '睡觉 呼呼~~~',
complete: false,
},
{
text: '玩游戏 呼呼~~~',
complete: false,
},
],
},
mutations: {
updateList(state, { index, content }) {
state.lists[index].text = content;
}
},
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
安装vuex-class
npm i vuex-class
1
import { State, Mutation } from "vuex-class";
@State("lists") public lists!: Item[];
@Mutation("updateList") public updateList!: (obj: IChangeItem) => void;
public save(item: IChangeItem) {
this.updateList(item); // 通过mutation更新状态
this.close();
}
1
2
3
4
5
6
7
2
3
4
5
6
7
到此我们就对ts编写vue,就有了具体的掌握
← Vue优化