- 收入和支出的切换功能-JS实现
- 收入和支出的切换功能-TS实现
- TS添加props
- WebStrom设置Vue的TS模板
- 计算器组件功能
- 备注组件功能
- 标签组件功能
-曾老湿, 江湖人称曾老大。
-多年互联网运维工作经验,曾负责过大规模集群架构自动化运维管理工作。 -擅长Web集群架构与自动化运维,曾负责国内某大型金融公司运维工作。 -devops项目经理兼DBA。 -开发过一套自动化运维平台(功能如下): 1)整合了各个公有云API,自主创建云主机。 2)ELK自动化收集日志功能。 3)Saltstack自动化运维统一配置管理工具。 4)Git、Jenkins自动化代码上线及自动化测试平台。 5)堡垒机,连接Linux、Windows平台及日志审计。 6)SQL执行及审批流程。 7)慢查询日志分析web界面。
收入和支出的切换功能-JS实现
Types组件的JS |
---|
<template>
<ul class="types">
<li :class="type === '-' && 'selected' " @click="selectType('-')">支出</li>
<li :class="type === ' ' && 'selected' " @click="selectType(' ')">收入</li>
</ul>
</template>
<script>
export default {
name: "Types",
data() {
return {
type: '-' // '-'表示支出,' '表示收入
}
},
methods: {
selectType(type) { // type 只能是'-'和' '中的一个
if (type !== '-' && type !== ' ') {
throw new Error('type is unknown')
}
this.type = type
}
}
};
</script>
<style lang="scss" scoped>
.types {
background: #c4c4c4;
display: flex;
text-align: center;
font-size: 24px;
> li {
width: 50%;
height: 64px;
display: flex;
justify-content: center;
align-items: center;
position: relative;
/*当前li被选中使用 &,如果直接写.selected代表li里面的selected*/
&.selected::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 4px;
background: #333;
}
}
}
</style>
收入和支出的切换功能-TS实现
代码语言:javascript复制<template>
<ul class="types">
<li :class="type === '-' && 'selected' " @click="selectType('-')">支出</li>
<li :class="type === ' ' && 'selected' " @click="selectType(' ')">收入</li>
</ul>
</template>
<script lang="ts">
import Vue from "vue";
import {Component} from "vue-property-decorator";
@Component //装饰器
export default class Types extends Vue {
type = "-"; // '-'表示支出,' '表示收入
selectType(type: string) { // type 只能是'-'和' '中的一个
if (type !== "-" && type !== " ") {
throw new Error("type is unknown");
}
this.type = type;
}
}
</script>
<style lang="scss" scoped>
.types {
background: #c4c4c4;
display: flex;
text-align: center;
font-size: 24px;
> li {
width: 50%;
height: 64px;
display: flex;
justify-content: center;
align-items: center;
position: relative;
/*当前li被选中使用 &,如果直接写.selected代表li里面的selected*/
&.selected::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 4px;
background: #333;
}
}
}
</style>
TS添加props
Types.vue 设置props
代码语言:javascript复制<template>
<ul class="types">
<li :class="type === '-' && 'selected' " @click="selectType('-')">支出</li>
<li :class="type === ' ' && 'selected' " @click="selectType(' ')">收入</li>
</ul>
</template>
<script lang="ts">
import Vue from "vue";
import {Component, Prop} from "vue-property-decorator";
// Prop告诉Vue xxx 不是data 是prop
// Number 告诉 Vue xxx 运行时是个Number
// xxx 属性名
// number | undefined 告诉 TS xxx的编译时类型
@Component //装饰器
export default class Types extends Vue {
type = "-"; // '-'表示支出,' '表示收入
@Prop(Number) xxx: number | undefined;
selectType(type: string) { // type 只能是'-'和' '中的一个
if (type !== "-" && type !== " ") {
throw new Error("type is unknown");
}
this.type = type;
}
mounted() {
console.log(this.xxx);
}
}
</script>
<style lang="scss" scoped>
.types {
background: #c4c4c4;
display: flex;
text-align: center;
font-size: 24px;
> li {
width: 50%;
height: 64px;
display: flex;
justify-content: center;
align-items: center;
position: relative;
/*当前li被选中使用 &,如果直接写.selected代表li里面的selected*/
&.selected::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 4px;
background: #333;
}
}
}
</style>
Money.vue 引用 props
代码语言:javascript复制<template>
<div id="app">
<Layout class-prefix="layout">
<NumberPad/>
<Types :xxx="333"/> <!-- 引用 types中的props传递过来的xxx -->
<Notes/>
<Tags/>
</Layout>
</div>
</template>
<script lang="ts">
import NumberPad from "@/components/Money/NumberPad.vue";
import Types from "@/components/Money/Types.vue";
import Notes from "@/components/Money/Notes.vue";
import Tags from "@/components/Money/Tags.vue";
export default {
name: "Money",
components: {Tags, Notes, Types, NumberPad},
};
</script>
<style lang="scss">
.layout-content {
/*border: 3px solid red;*/
display: flex;
flex-direction: column-reverse;
}
</style>
注意:undefined是默认值,不得不加,但是一旦加上,比如要在任何时候都检查他是不是undefined
代码语言:javascript复制 mounted() {
if(this.xxx === undefined){
console.log('undefined');
}else {
console.log(this.xxx);
}
}

WebStrom设置Vue的TS模板
如此依赖,我们写TS就需要设置一下Vue的模板

代码语言:javascript复制<template>
<div>#[[$END$]]#</div>
</template>
<script lang="ts">
import Vue from 'vue';
import {Component} from 'vue-property-decorator';
@Component
export default class ${COMPONENT_NAME} extends Vue {
}
</script>
计算器组件功能
代码语言:javascript复制<template>
<div class="numberPad">
<div class="output">{{output}}</div>
<div class="buttions">
<button @click="inputContent">1</button>
<button @click="inputContent">2</button>
<button @click="inputContent">3</button>
<button @click="remove">删除</button>
<button @click="inputContent">4</button>
<button @click="inputContent">5</button>
<button @click="inputContent">6</button>
<button @click="clear">清空</button>
<button @click="inputContent">7</button>
<button @click="inputContent">8</button>
<button @click="inputContent">9</button>
<button @click="ok" class="ok">OK</button>
<button @click="inputContent" class="zero">0</button>
<button @click="inputContent">.</button>
</div>
</div>
</template>
<script lang="ts">
import Vue from "vue";
import {Component, Prop} from "vue-property-decorator";
@Component //装饰器
export default class NumberPad extends Vue {
output = "0";
inputContent(event: MouseEvent) {
const button = (event.target as HTMLButtonElement); // 强制指定类型,如果不指定,你没法判断event是什么类型
console.log(button.textContent);
const input = button.textContent!; // 感叹号和下面一行用法一样,就是这个东西不会为空
// const input = button.textContent as string;
if (this.output.length === 16) {
return;
}
if (this.output === "0") {
if ("0123456789".indexOf(input) >= 0) {
this.output = input;
} else {
this.output = input;
}
return;
}
if (this.output.indexOf(".") >= 0 && input === ".") {
return;
}
this.output = input;
}
remove() {
if(this.output.length === 1){
this.output = '0';
}else {
this.output = this.output.slice(0, -1);
}
}
clear() {
this.output = '0'
}
// ok() {
// }
}
</script>
<style lang="scss" scoped>
@import "~@/assets/style/helper.scss";
.numberPad {
.output {
font-size: 36px;
font-family: Consolas, monospace; // 等宽字体,Consolas是windows的,monospace是编程字体
padding: 9px 16px;
text-align: right;
height: 72px;
@extend %innerShadow;
}
.buttions {
// 代替clearfix,但是如果写在这里就会很重复,那么我们就使用变量的方式,我与重复不共戴天。
/*&::after{*/
/* content: '';*/
/* display: block;*/
/* clear: both;*/
/*}*/
// 此处引用helper.scss的变量
@extend %clearFix;
> button {
width: 25%;
height: 64px;
float: left;
background: transparent;
border: none;
&.ok {
height: 64*2px;
float: right;
}
&.zero {
width: 25*2%;
}
$bg: lightgreen;
&:nth-child(1) {
background: $bg;
}
&:nth-child(2), &:nth-child(5) {
background: darken($bg, 4%);
}
&:nth-child(3), &:nth-child(6), &:nth-child(9) {
background: darken($bg, 4*2%);
}
&:nth-child(4), &:nth-child(7), &:nth-child(10) {
background: darken($bg, 4*3%);
}
&:nth-child(8), &:nth-child(11), &:nth-child(13) {
background: darken($bg, 4*4%);
}
&:nth-child(14) {
background: darken($bg, 4*5%);
}
&:nth-child(12) {
background: darken($bg, 4*6%);
}
}
}
}
</style>
备注组件功能
代码语言:javascript复制<template>
<label class="notes">
{{value}}
<span class="name">备注</span>
<input type="text" :value="value"
@input="onInput"
placeholder="在这里添加备注">
</label>
</template>
<script lang="ts">
import Vue from "vue";
import {Component} from "vue-property-decorator";
@Component
export default class Notes extends Vue {
value = "";
onInput(event: KeyboardEvent) {
const input = event.target as HTMLInputElement;
this.value = input.value;
}
}
</script>
<style lang="scss" scoped>
.notes {
font-size: 14px;
background: #f5f5f5;
padding-left: 16px;
display: flex;
align-items: center;
.name {
padding-right: 16px;
}
input {
height: 64px;
flex-grow: 1;
background: transparent;
border: none;
padding-right: 16px;
}
}
</style>
知识点:如果代码如下
代码语言:javascript复制:value = "x"
@input = "x = $event.target.value"
可以使用v-model
v-model="x"
修改代码使用v-model |
---|
<template>
<div>
<label class="notes">
<span class="name">备注</span>
<input type="text"
v-model="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 {
value = "";
}
</script>
<style lang="scss" scoped>
.notes {
font-size: 14px;
background: #f5f5f5;
padding-left: 16px;
display: flex;
align-items: center;
.name {
padding-right: 16px;
}
input {
height: 64px;
flex-grow: 1;
background: transparent;
border: none;
padding-right: 16px;
}
}
</style>

标签组件功能
tags.vue |
---|
<template>
<div class="tags">
<div class="new">
<button @click="create">新增标签</button>
</div>
<ul class="current">
<li v-for="tag in dataSource" :key="tag"
:class="{selected: selectedTags.indexOf(tag)>=0}"
@click="toggle(tag)">{{tag}}
</li>
</ul>
</div>
</template>
<script lang="ts">
import Vue from "vue";
import {Component, Prop} from "vue-property-decorator";
@Component
export default class Tags extends Vue {
@Prop(Array) readonly dataSource: string[] | undefined;
selectedTags: string[] = [];
toggle(tag: string) {
const index = this.selectedTags.indexOf(tag);
if (index >= 0) {
this.selectedTags.splice(index, 1);
} else {
this.selectedTags.push(tag);
}
}
create() {
const name = window.prompt("请输入标签名:");
if (name === "") {
alert("标签名不能为空");
} else if (this.dataSource) {
this.$emit("update:dataSource", [...this.dataSource, name]);
}
//if (this.dataSource) {
// this.dataSource.push(name!); // 不能改外部数据
//}
}
}
</script>
<style lang="scss" scoped>
.tags {
font-size: 14px;
padding: 16px;
flex-grow: 1;
display: flex;
flex-direction: column-reverse;
> .current {
display: flex;
flex-wrap: wrap;
> li {
$bg: #d9d9d9;
background: $bg;
/* 只有一行内容的时候可以让line-height=height让字体居中 */
$h: 24px;
height: $h;
line-height: $h;
border-radius: $h/2;
padding: 0 16px;
margin-right: 12px;
margin-top: 4px;
&.selected {
background: darken($bg, 50%);
color: #fff;
}
}
}
> .new {
padding-top: 16px;
button {
background: transparent;
border: none;
color: #999;
border-bottom: 1px solid;
padding: 0 4px;
}
}
}
</style>
Money.vue |
---|
<template>
<div id="app">
<Layout class-prefix="layout">
<NumberPad/>
<Types/> <!-- 引用 types中的props传递过来的xxx -->
<Notes/>
<Tags :data-source.sync="tags"/>
</Layout>
</div>
</template>
<script lang="js">
import NumberPad from "@/components/Money/NumberPad.vue";
import Types from "@/components/Money/Types.vue";
import Notes from "@/components/Money/Notes.vue";
import Tags from "@/components/Money/Tags.vue";
export default {
name: "Money",
components: {Tags, Notes, Types, NumberPad},
data() {
return {
tags: ['衣', '食', '住', '行', '奢侈品']
}
}
};
</script>
<style lang="scss">
.layout-content {
display: flex;
flex-direction: column-reverse;
}
</style>