实战项目:up2u记帐本总结

问题一:webpack与vue

提交代码,提示vue-cli-service lint found some errorsjavascript

个人解决方法是在报错文件添加/* eslint-disable */vue

使用后成功解决了vue.config.js中的问题java

可是Icon.vue仍是存在报错,error: '__WebpackModuleApi' is not defined (no-undef)webpack

在网上搜索到了相似的问题,Vue.js中的__webpack_public_path__git

我在.eslintrc.js>module.exports添加globals,成功提交代码。github

module.exports = {
    "globals":{
        "__WebpackModuleApi":"writable"
    }
}
复制代码

问题二:拆分组件

Money.vue内容太多,对其进行拆分。在components新建Money文件夹,对应Money.vue的几个div块,建立相应的vue文件。web

image.png

Money.vue中的templatestyle移到相应vue文件中,并在Money.vue中引入。vue-cli

image.png

拆分为几个组件后,效果与原来一致。typescript

image.png

问题三:写Vue组件遇到的错误

写Vue组件的方式(单文件组件)

  1. 用JS对象写
export default {data , props, methods, created, ...}
复制代码
  1. 用TS类写
@Componet
export default class XXX extends Vue{
    xxx: string = 'hi';
    @Prop(Number) xxx: number|undefined;
}
复制代码
  1. 用JS类写
@Compnent
export default class XXX extends Vue{
    xxx = 'hi'
}
复制代码

bug1:在使用TS类写vue组件时,prop没法使用

23行代码报错

image.png

尝试更新typescript后,依旧报错markdown

参考vue-property-decorator文档

@Prop(Number) xxx: number | undefined;
复制代码

成功

解析一下这句代码

image.png

简单来讲,number | undefined是在编译时告诉Vue,xxx的编译类型。而Number是在运行时告诉Vue,xxx是个number。

image.png

扯TS的本质

image.png

注:tsc=>TypeScript compiler,可检查TS,可将TS编译成JS。

bug2:在使用TS类写vue组件时,selectType出错

image.png

声明type: String便可

image.png

问题四:v-model

<template>
  <div> <label class="notes"> <span class="name">备注</span> <input type="text" :value="x" @input="x = $event.target.value" placeholder="点击输入备注..."> </label> </div> </template>

<script lang="ts"> import Vue from 'vue'; import {Component} from 'vue-property-decorator'; @Component export default class Notes extends Vue{ x = ''; } </script>
复制代码

能够简写成

<template>
  <div> <label class="notes"> <span class="name">备注</span> <input type="text" x-model="x" placeholder="点击输入备注..."> </label> </div> </template>

<script lang="ts"> import Vue from 'vue'; import {Component} from 'vue-property-decorator'; @Component export default class Notes extends Vue{ x = ''; } </script>
复制代码

问题五:收集数据

占位,以后整理

问题六:用LocalStorage储存数据

数据收集完以后,想实现如下功能:每次按ok,将数据放到LocalStorage

在父组件Money.vueNumberPad新加了一个监听@submit="saveRecord"

<template>
  <layout class-prefix="layout"> <NumberPad @update:value="onUpdateAmount" @submit="saveRecord"/> ... </layout>
</template>
复制代码
<script lang="ts">
...
  export default class Money extends Vue{
    tags = ['餐饮','交通','购物','居家'];
    recordList: Record[] = [];
    record: Record = {tags: [], notes: '', type: '-', amount: 0};
    ...
    // 新增函数
    saveRecord(){
      this.recordList.push(this.record)
    }
    @Watch('recordList')
    onRecordListChange(){
      window.localStorage.setItem('recordList',JSON.stringify((this.recordList)))
    }
}
</script>
复制代码

在子组件NumberPad.vue文件中的export default中的ok函数中添加代码

<script lang="ts">
...
export default class NumberPad extends Vue {
...
  ok(){
    this.$emit('update:value',this.output);
    this.$emit('submit',this.output); //新增
  }
}
</script>
复制代码

这样用户每次点击ok,都会将数据上传至LocalStorae

可是这里出了一个错误,以下:

第一次输入1,点击ok,打印this.recordListamount是数字1,正确。

image.png

但第二次输入2,点击ok,再打印this.recordListamount获得两次结果都是2,出现bug。

image.png

Local Storage以下

image.png

缘由是由于this.recordList.push(this.record)this.record只是引用,因此第一次ok和第二次ok,都只是引用了record的地址,结果是两个2。

修改代码,record2是一个深拷贝,至关于保存了this.record的副本这样就能够实现预想的功能了。

saveRecord(){
      const record2 = JSON.parse(JSON.stringify(this.record));
      this.recordList.push(record2)
      console.log(this.recordList);
    }
复制代码

问题七: js改写ts报错

  1. 改文件名后缀jsts

image.png

  1. 新建一个custom.d.ts,全局声明RecordItem,赋给data,解决

image.png

image.png

  1. 这里提交代码时,又报了错(晕)
error: 'RecordItem' is not defined (no-undef) at src\views\Money.vue:40:20:
38 |
39 |   saveRecord() {
> 40 |     const record2: RecordItem = model.clone(this.record);
   |                    ^
41 |     record2.createdAt = new Date();
42 |     this.recordList.push(record2);
43 |   }
复制代码

cunstom.d.ts中全局声明的RecordItem,在Money.vue中却提示'RecordItem' is not defined

尝试了不少方法没有成功,最后又从新声明了一个RecordItem,引入Money.vue中。

image.png

后续若是有更好的解决办法会更新。

问题八:关于子组件直接修改父组件的值

代码以下

<template>
  <div>
    <label class="formItem">
      <span class="name">{{ this.fieldName }}</span>
      <input type="text" v-model="value" :placeholder="this.placeholder">
    </label>
  </div>
</template>

<script lang="ts">
...
export default class FormItem extends Vue{
  @Prop({default:''}) value!:string;
...
  onValueChanged(value:string){
    this.$emit('update:value',value)
  }
}
</script>
复制代码

vue不推荐直接在子组件中修改父组件传来的props的值,改写FormItem.vue后,报错以下:

[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "value"
复制代码

解决办法:

改写v-model="value",再也不给value赋值。

经过onValuechangedvalue进行变动。

// 改后
<template>
  <div>
    <label class="formItem">
      <span class="name">{{ this.fieldName }}</span>
      <input type="text"
             :value = "value"
             @input = "onValueChanged=($event.traget.value)"
      :placeholder="placeholder">
    </label>
  </div>
</template>

<script lang="ts">
...
export default class FormItem extends Vue{
  @Prop({default:''}) readonly value!:string;
...
  onValueChanged(value:string){
    this.$emit('update:value',value)
  }
}
</script>
复制代码

问题九:解决id生成问题

问题描述

举个例子,在组件tagListModel.vuecreate以下

type TagListModel = {
  ...
  create: (name: string) => 'success' | 'duplicated'
  ...
}
const tagListModel: TagListModel = {
  ...
  create(name) {
    const names = this.data.map(item => item.name)
    if(names.indexOf(name) >= 0) { return 'duplicated'; }
    this.data.push({ id:name, name: name });
    this.save();
    return 'success';
  },
  ...
}
复制代码

建立相同name的标签,就会提示重复。

101.10.10.2.gif

后来添加了新功能,在编辑标签页面能够改标签名,就出现了以下bug——改变标签{id:1, name:1}name,再次新建标签时,不能识别标签重复。

101.10.10.1.gif

解决思路

  1. 首先一个id赋给了标签,就不要再修改了,由于路由用了id做为url的地址的一部分。
{
    path: '/labels/edit/:id',
    component: EditLabel
  },
复制代码

id若是变了,刷新页面就不存在了。

  1. 其次,id是不能重复的,否则/label/edit/1到底对应哪个标签页?

  2. 个人作法是每新建一个标签,id自增。虽然可能会爆栈,可是能知足很大一部分需求。

实现思路大体说一下,代码能够访问个人github

新建一个ts组件实现id的自增功能,在tagListModel.ts组件的create方法引入这个自增id

问题十: ISO 8601

维基百科-日期和时间的组合表示法

用法以下:

日期和时间的组合表示法,要在时间前面加一大写字母T,如要表示东八区时间2004年5月3日下午5点30分8秒,能够写成2004-05-03T17:30:08+08:00或20040503T173008+08。

image.png

相关文章
相关标签/搜索