# 记账页面

Money 组件及布局如下:

money

# .sync修饰符实现响应式

通过.sync修饰符绑定则可以统一在父组件上收集各个子组件的状态.

<Panel :expression.sync="record.amount" />
<Tab :value.sync="record.type" />
<InputItem :notes.sync="record.notes" />
<Tag :labels.sync="labels" :selectedTags.sync="record.tags" />
1
2
3
4

# Tag组件解析

此组件的看点只有switchTag函数.当被触发时, 它首先根据传入的标签名判断已有的selectedTags数组里是否包含这个标签, 有则删除, 没有则添加.从而影响样式的更新.其次,发射更新事件(以配合.sync), 返回值是选中的标签组成的数组.

@Emit("update:selectedTags")
    switchTag(label: string) {
      const index = this.selectedTags.indexOf(label)
      if (index >= 0) {
        this.selectedTags.splice(index, 1)
      } else {
        this.selectedTags.push(label)
      }
      return this.selectedTags
    }
1
2
3
4
5
6
7
8
9
10

# InputItem组件解析

该组件比较简单, 这里只提一个知识点, 在模板里的事件函数:





 












<template>
  <input
    :placeholder="placeholder"
    :value="notes"
    @input="handleChange($event.target.value)"
    type="text"
  />
</template>

<script>
export default {
  handleChange(val) {
    this.$emit("update:notes", val);
  }
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# Tab组件

该组件是我的Giao UI 里引用的组件, 具体实现在另一篇博客里.

# Panel组件

# 布局

键盘是使用浮动来做的, 如图所示:

float

除 Ok 键以外的 button 都向左浮动, OK 键向右浮动. 每个 button 的width25%. 而 0 键宽度单独设置为50%. 最后要在浮动元素的父元素上清除浮动:

parentElement {
  clear: both;
  display: block;
}
1
2
3
4

# 获取用户输入值

通过点击事件的e.target.textContent可以获取键盘对应数值.

# 防御性编程

为防止用户做出一些非正常输入, 做防御性编程是很重要的.

# 输入数字的最大长度只能有 16 位

if (this.output.length === 16) {
  return;
}
1
2
3

# 初始为 0, 当输入数字后 0 应该消失

if (this.output === "0") {
  if ("0123456789".indexOf(input) >= 0) {
    this.output = input;
  } else {
    this.output += input;
  }
  return;
}
1
2
3
4
5
6
7
8

当我们输入的值是"0123456789"里的任意一个, 那么原来的0都会被替换, 否则累加, 在这里只有输入小数点才会累加.

# 只能输一个小数点

if (this.output.indexOf(".") >= 0 && input === ".") {
  return;
}
1
2
3

当输入里有小数点时且输入中又含有小数点则返回.

# 退格

deleteNumber() {
  const length = this.output.length
  this.output = this.output.substr(0, length - 1) // 获取除了最后一个字符以外的新字符串
  if (length === 1) {
    this.output = "0" //归零
  }
}
1
2
3
4
5
6
7