ts+ vue2
一、环境搭建
- 创建项目 vue create xxx
- 默认选择安装了vue2.0
- 启动项目
- 在项目下安装 vue add @vue/script
- npm i vuex
- 搭建完成
二、创建子组件
1. 头部组件 MenuBar
xml
<template>
<div class="header-wrapper">
<div class="header-item">
<div class="img-item">
<img src="../assets/img/kjj.png"/>
</div>
<span>Vue2.0 + TypeScript</span>
</div>
<div class="select-item">
<el-dropdown trigger="click" @command="doNew">
<span class="el-dropdown-link">
新建<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item icon="el-icon-plus">文本便签</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<div class="space-item"></div>
<div>
<el-dropdown trigger="click" @command="doChange" >
<el-badge class="mark" :value="doFilter(-1)">
<span class="el-dropdown-link">
全部<i class="el-icon-caret-bottom el-icon--right"></i>
</span>
</el-badge>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item class="clearfix" command=-1>
全部
<el-badge class="mark" :value="doFilter(-1)"/>
</el-dropdown-item>
<el-dropdown-item class="clearfix" command=0 divided>
工作
<el-badge class="mark" :value="doFilter(0)"/>
</el-dropdown-item>
<el-dropdown-item class="clearfix" command=1>
生活
<el-badge class="mark" :value="doFilter(1)"/>
</el-dropdown-item>
<el-dropdown-item class="clearfix" command=2>
学习
<el-badge class="mark" :value="doFilter(2)"/>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
</div>
</template>
<script lang="ts">
import {Vue, Component} from 'vue-property-decorator';
import ItemData from "@/model/ItemData";
@Component
export default class MenuBar extends Vue {
value: string = ''
//点击新建,出现编辑框
doNew() {
// 点击新增初始化tranMemo,不然transMemo的初值是null
this.$store.state.transMemo = new ItemData(-1, 0);
this.$store.state.isshow = true
}
doFilter(cid: number): number {
if (cid === -1) {
return this.$store.state.actionHelper.memoList.length
} else {
return this.$store.state.actionHelper.memoList.filter((ele) => {
return ele.categoryId == cid;
}).length
}
}
doChange(val){
this.$store.state.fliterCateId = val;
}
}
</script>
<style scoped lang="scss">
.header-wrapper {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
.space-item {
height: 60px;
width: 40px;
background-color: #409EFF;
}
.header-item {
display: flex;
align-items: center;
height: 60px;
.img-item {
height: 40px;
width: 40px;
img {
height: 100%;
width: 100%;
border-radius: 50%;
border: 1px solid red;
}
}
span {
display: inline-block;
font-size: 20px;
font-weight: bold;
color: #fff;
margin-left: 10px;
}
}
.select-item {
display: flex;
flex-direction: row;
align-items: center;
}
}
</style>
2. 标签组件 MemoItem
xml
<template>
<div class="memo-container">
<div class="memo">
<div class="mark"></div>
<div class="memo-heading">
<h5 class="title">{{ memo.title }}</h5>
<ul class="tools">
<li class="edit" @click="showEdit"></li>
<li class="delete" @click="doDel"></li>
</ul>
</div>
<h6 class="memo-info">
<span class="timeStamp">{{ memo.createTime }}</span>
<span class="category"
>分类:{{
$store.state.aHelper.getCategoryName(memo.categoryId)
}}</span
>
</h6>
<div class="content">
<div class="text">{{ memo.content }}</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import ItemData from "@/model/ItemData";
import { Vue, Component, Prop } from "vue-property-decorator";
@Component
export default class MemoItem extends Vue {
@Prop() memo!: ItemData;
doDel(): void {
if (!window.confirm(`确认删除【${this.memo.title}】的笔记吗?`)) return;
// 确认后,就删除
this.$store.state.aHelper.remove(this.memo.id);
}
showEdit(): void {
// 1.创建副本
let newMemo = JSON.parse(JSON.stringify(this.memo));
// 2.传递给transmemo
this.$store.commit('showEditMemo', newMemo);
}
}
</script>
3. 编辑组件 MemoEditor
xml
<template>
<el-dialog
:visible.sync="$store.state.isshow"
width="30%"
append-to-body
:show-close="false">
<el-card class="box-card">
<template #header>
<div class="card-header">
<el-input type="text" placeholder="标题" v-model="memo.title"></el-input>
<el-dropdown @command="handleCommand" class="el-dropdown-item">
<span class="el-dropdown-link">{{memo.categoryId == 0 ? '工作': memo.categoryId == 1? '生活':'学习' }}
<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command=0>工作</el-dropdown-item>
<el-dropdown-item command=1>生活</el-dropdown-item>
<el-dropdown-item command=2>学习</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<div class="el-button-item">
<el-button class="button" type="text" @click="doSave" icon="el-icon-message"></el-button>
<el-button class="button" type="text" @click="doCancel" icon="el-icon-circle-close"></el-button>
</div>
</div>
</template>
<div>
<el-input
type="textarea"
:rows="2"
placeholder="请输入内容"
v-model="memo.content">
</el-input>
</div>
</el-card>
</el-dialog>
</template>
<script lang="ts">
import {Vue, Component} from 'vue-property-decorator';
import ItemData from "@/model/ItemData";
@Component
export default class MemoEditor extends Vue {
memo: ItemData = new ItemData(-1, 0);
created(): void {
this.memo = this.$store.state.transMemo
}
handleCommand(val) {
this.memo.categoryId = val;
}
doCancel() {
this.$store.state.isshow = false
}
doSave() {
if (this.memo && this.memo.categoryId > -1 && this.memo.title.trim().length > 0 && this.memo.content.trim().length > 0) {
if (this.memo.id <= -1) {
this.$store.state.actionHelper.addData(this.memo)
} else {
this.$store.state.actionHelper.editData(this.memo)
}
this.$store.state.isshow = false
} else {
window.alert('数据输入不完整!')
}
}
}
</script>
<style scoped lang="scss">
.item {
margin-bottom: 18px;
font-size: 14px;
}
/deep/ .el-card__header {
padding: 10px 0 10px 10px;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
/deep/ .el-card__body {
padding: 10px;
}
.second-item {
font-size: 14px;
display: flex;
justify-content: space-between;
padding: 5px 10px;
}
/deep/ .el-textarea__inner {
height: 300px;
resize: none;
}
.el-card {
width: 100%;
}
.el-button-item {
width: 80px;
}
.el-dropdown-item {
width: 120px;
margin-left: 15px;
}
</style>
4. MenuList组件
xml
<template>
<div class="list-item">
<MemoItem v-for="item in filterMemo()" :key="item.id" :memo="item"/>
</div>
</template>
<script lang="ts">
import {Vue, Component} from 'vue-property-decorator'
import MemoItem from "@/components/MemoItem.vue";
import ItemData from "@/model/ItemData";
@Component({
components: {
MemoItem
}
})
export default class MemoList extends Vue {
memoArr:Array<ItemData> = this.$store.state.actionHelper.memoList;
filterMemo():Array<ItemData> {
if(this.$store.state.fliterCateId == -1){
return this.memoArr;
}else{
return this.memoArr.filter((item)=>{
return item.categoryId == this.$store.state.fliterCateId
})
}
}
}
</script>
<style scoped lang="scss">
.list-item {
display: flex;
flex-wrap: wrap;
}
</style>
三、vue2.0特点
1. 2.0的组件导入方式,采用注解
2. 现红色提示,可能是变量未赋值等,更改package.json
json
"rules": {
"no-unused-vars": 0,
"vue/no-unused-components": [
"off",
{
"ignoreWhenBindingPresent": true
}
],
"prefer-const": "off"
}
3. 在书写css样式时,采用了scss语法,安装相关组件,注意版本问题
kotlin
"node-sass": "^4.14.1",
"sass-loader": "^7.3.1",
npm install node-sass@4.14.1 -D
npm install sass-loader@7.3.1 -D
4.main.ts文件内容
javascript
import Vue from 'vue'
import App from './App.vue'
import './assets/css/global.css'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import store from './store/index'
Vue.config.productionTip = false
Vue.use(ElementUI)
new Vue({
store,
render: h => h(App),
}).$mount('#app')
四、实现功能
1. 创建跨组件共享数据文件store
typescript
import Vue from 'vue'
import Vuex from 'vuex'
import ActionHelper from "@/store/ActionHelper";
Vue.use(Vuex)
let store = new Vuex.Store({
state: {
isshow: false,
actionHelper: new ActionHelper(),
transMemo: null,// 传递数据的桥梁
fliterCateId: -1
},
mutations: {
showEditMemo(state: any, editMemo: any) {
state.transMemo = editMemo;
state.isshow = true;
}
}
})
export default store
2. 设计便签的数据模型:MemoItem类
typescript
class ItemData {
id: number
categoryId: number
title: string
content: string
createTime: string
constructor(id: number = -1, categoryId: number = -1, title: string = '', content: string = '', createTime: string) {
this.id = id;
this.categoryId = categoryId;
this.title = title;
this.content = content;
this.createTime =this.toselfDate(Date.now()) ;
}
toselfDate(dateSpan: number): string {
let date = new Date(dateSpan);
let str = date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate() + ' ' + date.getHours() + ':' + date.getMinutes();
return str;
}
}
export default ItemData
3. 设计枚举的数据模型
arduino
enum CateEnum {
Work,
Life = 1,
Study
}
export default CateEnum
4. 创建操作localstorage的类DataHelper
typescript
// DataHelper主要实现对localstorage的操作
// 0.构造类
class DataHelper {
dataKey: string
primaryKey: string
constructor(dataKey: string, primaryKey: string) {
this.dataKey = dataKey;
this.primaryKey = primaryKey
}
// 1.读数据
readData(): any {
// 1.读取数据
let strData: string | null = localStorage.getItem(this.dataKey);
// 2.将json转成json对象
let arrData: any = [];
if (strData != null) {
arrData = JSON.parse(strData);
}
return arrData;
}
// 2.存数据
saveData(arrData: Array<Object>): void {
// 1.将json对象装成字符串
let strData: string = JSON.stringify(arrData);
// 2.存储
localStorage.setItem(this.dataKey, strData);
}
// 3.新增数据
addData(newDataObj: any): number {
// 1. 读取本地现有的数据
let dataArray = this.readData();
if (dataArray == null) {
dataArray = [];
}
// 3.自动生成主键,id
let newId = dataArray.length > 0 ? dataArray[dataArray.length - 1].id + 1 : 1;
// 4.将id添加到对象中
dataArray.id = newId;
// 5.将数组保存到本地
dataArray.push(newDataObj);
this.saveData(dataArray);
// 6.返回newId的值
return newId;
}
// 4.删除数据
removeData(id: string | number): boolean {
// 1.获取本地数据
let arrData: any = this.readData();
// 2.查找下标 删除
let index = arrData.findIndex((ele: any) => {
return ele[this.primaryKey] == id;
})
// 3.重新保存删除后的数据
if (index > -1) {
arrData.splice(index, 1);
this.saveData(arrData);
return true;
}
return false;
}
}
export default DataHelper;
5. 在main.ts测试DataHelper的方法
ini
// 0.测试构造的itemdata类
// let itemData = new ItemData(1,1,'标题','内容');
// console.log(itemData)
// 1.测试构造的枚举类型
// let itemData = new ItemData(1,CateEnum.Work,'标题','内容');
// console.log(itemData)
// ****************DataHelper***********
// 2.测试新增数据(新增的数据id都是-1)
// let itemData = new ItemData();
// let dh:DataHelper = new DataHelper('keyData', 'id');
// console.log(dh.addData(itemData))
// 3.删除数据
// let dh:DataHelper = new DataHelper('keyData','id');
// dh.removeData('-1');
// 4.测试读数据
// let dh:DataHelper = new DataHelper('keyData','id');
// console.log(dh.readData());
6. 创建操作类ActionHelper
ini
import DataHelper from "@/store/DataHelper";
import ItemData from "@/model/ItemData";
class ActionHelper {
// 1.在Datahelper的基础上再次封装
dh: DataHelper = new DataHelper('keyData', 'id');
// 2.定义一个便签数组
memoList: Array<ItemData>;
constructor() {
// 便签数组的初始化数据,就是从本身读取数据,相当于vue的create方法,读取数据
this.memoList = this.dh.readData();
}
// 读取数据
readData(): Array<ItemData> {
let arrData = this.dh.readData();
// 将获取的数据,装成itemdata类型
let arrItem = arrData.map((ele) => {
// @ts-ignore
let item: ItemData = new ItemData(); // item是itemData类型的空对象
// 0.第一种方式 // 给空对象赋值
// item = ele;
// 1.第二种方式 // 给空对象赋值
item.id = ele.id;
item.categoryId = ele.categoryId;
item.title = ele.title;
item.content = ele.content;
item.createTime = ele.createTime;
return item;
})
return arrItem;
}
// 新增
addData(item: ItemData): number {
// 0.新增笔记到本地
item.id = this.dh.addData(item);
// 1.将笔记添加到memoList
this.memoList.push(item);
// 2.将笔记数组从新保存本地
this.dh.saveData(this.memoList);
return item.id;
}
// 修改
editData(item: ItemData): void {
// 0.先找到下标
let editItem = this.memoList.find((ele) => {
return ele.id == item.id;
})
// 1.修改对象
if (editItem) {
editItem.categoryId = item.categoryId;
editItem.title = item.title;
editItem.content = item.content;
}
// 2.保存对象
this.dh.saveData(this.memoList);
}
// 删除
delData(id: number): void {
// 0.找下标
let index = this.memoList.findIndex((ele) => {
return ele.id == id;
})
if (index > -1) {
this.memoList.splice(index, 1);
}
this.dh.saveData(this.memoList);
}
}
export default ActionHelper;
7. 在main.ts中测试
ini
//**************ActionHelper*************
// 0.测试新增(数据的id正常递增)
// let ah:ActionHelper = new ActionHelper();
// let item:ItemData = new ItemData();
// ah.addData(item);
// 1.测试修改(修改不存在的对象,会覆盖)
// let ah:ActionHelper = new ActionHelper();
// let item:ItemData = new ItemData(1,1,'我爱你11','我爱学习');
// ah.editData(item);
// 2.测试删除
// let ah:ActionHelper = new ActionHelper();
// ah.delData(1);
8. 实现新增功能
arduino
- 点击新增,实现弹框 点击新增的时候,设置全局的isshow值是true
javascript
//点击新建,出现编辑框
doNew() {
// 点击新增初始化tranMemo,不然transMemo的初值是null
this.$store.state.transMemo = new ItemData(-1, 0);
this.$store.state.isshow = true
}
9. 实现保存功能
diff
- 保存第一步对数据进行校验
- 分为新增保存
- 分为修改保存
kotlin
doSave() {
if (this.memo && this.memo.categoryId > -1 && this.memo.title.trim().length > 0 && this.memo.content.trim().length > 0) {
if (this.memo.id <= -1) {
this.$store.state.actionHelper.addData(this.memo)
} else {
this.$store.state.actionHelper.editData(this.memo)
}
this.$store.state.isshow = false
} else {
window.alert('数据输入不完整!')
}
}
10. 实现修改功能
diff
- 点击修改的时候,出现弹框
- 修改时,弹框内出现数据 在点击修改的时候,创建当前标签数据的副本,并且把数据传到共享数据文件中
javascript
doEdit():void{
// 创建副本
let newMemo = JSON.parse(JSON.stringify(this.memo));
// 提交数据到桥梁
this.$store.commit('showEditMemo',newMemo);
}
diff
- 展示组件MemoEditor的时候,在created方法中获取标签副本的值
kotlin
created(): void {
this.memo = this.$store.state.transMemo
}
11. 实现删除功能
javascript
doDel() {
if (!window.confirm(`确认删除【${this.memo.title}的标签吗?】`)) return
this.$store.state.actionHelper.delData(this.memo.id);
}
12. 统计类别的个数
kotlin
doFilter(cid: number): number {
if (cid === -1) {
return this.$store.state.actionHelper.memoList.length
} else {
return this.$store.state.actionHelper.memoList.filter((ele) => {
return ele.categoryId == cid;
}).length
}
}
13. 点击不同的类别,展示不同的便签内容
diff
- 把分类的值,传给全局的变量,fliterCateId
kotlin
doChange(val){
this.$store.state.fliterCateId = val;
}
diff
- 在memoList展示便签的时候,做过滤处理
kotlin
filterMemo():Array<ItemData> {
if(this.$store.state.fliterCateId == -1){
return this.memoArr;
}else{
return this.memoArr.filter((item)=>{
return item.categoryId == this.$store.state.fliterCateId
})
}
}
五、gitee共享
六、展示
ts+vue3
一、环境搭建
- 创建项目 vue create xxx
- 选择安装了vue3.0
- 启动项目
- 在项目下安装 vue add @vue/script // 安装ts
- npm i vuex
- 搭建完成
二、创建子组件
-
头部组件 MenuBar
-
标签组件 MemoItem
-
编辑组件 MemoEditor
三、vue3.0特点
-
vue3.0的组件导入方式
-
编辑文件是会出现红色提示,可能是变量未赋值等,更改package.json
json
"rules": {
"no-unused-vars": 0,
"vue/no-unused-components": [
"off",
{
"ignoreWhenBindingPresent": true
}
],
"prefer-const": "off"
}
- 在书写css样式时,采用了scss语法,安装相关组件,注意版本问题
kotlin
"node-sass": "^4.14.1",
"sass-loader": "^7.3.1",
npm install node-sass@4.14.1 -D
npm install sass-loader@7.3.1 -D
- main.ts文件内容
javascript
import {createApp} from 'vue'
import {Elementplus} from './element-ui'
import App from './App.vue';
import './assets/css/global.css'
const app = createApp(App);
// 调用
Elementplus(app);
// 使用
createApp(App).use(Elementplus).mount('#app')
- vue3.0采用按需引入element-plus的方式,安装插件
arduino
"babel-plugin-import": "^1.13.3",
npm install babel-plugin-import -D