deep语法
因为之前在记账页已经有一个type组建了,统计页想直接拿过来用。但是我们想要使用scoped将范围缩小在本组建内,那么css怎么深入到我们想拿过来用的type组件里的li呢??
vue给了我们一个新的语法 deep
Scoped CSS
当 <style> 标签有 scoped 属性时,它的 CSS 只作用于当前组件中的元素。这类似于 Shadow DOM 中的样式封装。它有一些注意事项,但不需要任何 polyfill。它通过使用 PostCSS 来实现以下转换:
<style scoped>
.example {
color: red;
}
</style>
<template>
<div class="example">hi</div>
</template>
转换结果:
<style>
.example[data-v-f3f3eg9] {
color: red;
}
</style>
<template>
<div class="example" data-v-f3f3eg9>hi</div>
</template>
#混用本地和全局样式
你可以在一个组件中同时使用有 scoped 和非 scoped 样式:
<style>
/* 全局样式 */
</style>
<style scoped>
/* 本地样式 */
</style>
#子组件的根元素
使用 scoped 后,父组件的样式将不会渗透到子组件中。不过一个子组件的根节点会同时受其父组件的 scoped CSS 和子组件的 scoped CSS 的影响。这样设计是为了让父组件可以从布局的角度出发,调整其子组件根元素的样式。
#深度作用选择器
如果你希望 scoped 样式中的一个选择器能够作用得“更深”,例如影响子组件,你可以使用 >>> 操作符:
<style scoped>
.a >>> .b { /* ... */ }
</style>
上述代码将会编译成:
.a[data-v-f3f3eg9] .b { /* ... */ }
有些像 Sass 之类的预处理器无法正确解析 >>>。这种情况下你可以使用 /deep/ 或 ::v-deep 操作符取而代之——两者都是 >>> 的别名,同样可以正常工作。
使用depp语法的css展示
<style scoped lang="scss">
::v-deep {
.type-tabs-item {
background: #fde3cc;
&.selected {
background: #ffb13d;
}
}
.interval-tabs-item {
height: 48px;
}
}
%item {
padding: 8px 16px;
line-height: 24px;
display: flex;
justify-content: space-between;
align-content: center;
}
.title {
@extend %item;
}
.record {
background: white;
@extend %item;
}
.notes {
margin-right: auto;
margin-left: 16px;
color: #999;
}
</style>
ISO8601
记账时间是按照ISO8601记录的,展示时同样也需要按照时间分组,所以有必要明确什么是ISO8601。
国际标准ISO 8601,是国际标准化组织的日期和时间的表示方法,全称为《数据存储和交换形式·信息交换·日期和时间的表示方法》。目前是2004年12月1日发行的第三版“ISO8601:2004”以替代1998年的第一版“ISO8601:1998”与2000年的第二版“ISO8601:2000”。
日期和时间的组合表示法
合并表示时,要在时间前面加一大写字母T,如要表示东八区时间2004年5月3日下午5点30分8秒,可以写成2004-05-03T17:30:08+08:00或20040503T173008+08。
如何使用ISO8601
Day.js
day.js是Moment.js 的 2kB 轻量化方案,拥有同样强大的 API
Day.js 是一个轻量的处理时间和日期的 JavaScript 库,和 Moment.js 的 API 设计保持完全一样. 如果您曾经用过 Moment.js, 那么您已经知道如何使用 Day.js
dayjs()
.startOf('month')
.add(1, 'day')
.set('year', 2018)
.format('YYYY-MM-DD HH:mm:ss')
- 🕒 和 Moment.js 相同的 API 和用法
- 💪 不可变数据 (Immutable)
- 🔥 支持链式操作 (Chainable)
- 🌐 国际化 I18n
- 📦 仅 2kb 大小的微型库
- 👫 全浏览器兼容
文档
访问 day.js.org 网站查看更详细的文档
安装
npm install dayjs --save
📚安装指南
API
Day.js 有很多 API 来解析、处理、校验、增减、展示时间和日期
dayjs('2018-08-08') // 解析
dayjs().format('{YYYY} MM-DDTHH:mm:ss SSS [Z] A') // 展示
dayjs()
.set('month', 3)
.month() // 获取
dayjs().add(1, 'year') // 处理
dayjs().isBefore(dayjs()) // 查询
总体代码
<template>
<Layout>
<Tabs class-prefix="type" :data-source="recordTypeList" :value.sync="type"/>
<ol>
<li v-for="(group, index) in groupedList" :key="index">
<h3 class="title">{{beautify(group.title)}} <span>¥{{group.total}}</span></h3>
<ol>
<li v-for="item in group.items" :key="item.id"
class="record"
>
<span>{{tagString(item.tags)}}</span>
<span class="notes">{{item.notes}}</span>
<span>¥{{item.amount}} </span>
</li>
</ol>
</li>
</ol>
</Layout>
</template>
<script lang="ts">
import Vue from 'vue';
import {Component} from 'vue-property-decorator';
import Tabs from '@/components/Tabs.vue';
import recordTypeList from '@/constants/recordTypeList';
import dayjs from 'dayjs';
import clone from '@/lib/clone';
@Component({
components: {Tabs},
})
export default class Statistics extends Vue {
tagString(tags: Tag[]) {
return tags.length === 0 ? '无' : tags.join(',');
}
beautify(string: string) {
const day = dayjs(string);
const now = dayjs();
if (day.isSame(now, 'day')) {
return '今天';
} else if (day.isSame(now.subtract(1, 'day'), 'day')) {
console.log('hi');
return '昨天';
} else if (day.isSame(now.subtract(2, 'day'), 'day')) {
return '前天';
} else if (day.isSame(now, 'year')) {
return day.format('M月D日');
} else {
return day.format('YYYY年M月D日');
}
}
get recordList() {
return (this.$store.state as RootState).recordList;
}
get groupedList() {
const {recordList} = this;
if (recordList.length === 0) {return [];}
const newList = clone(recordList)
.filter(r => r.type === this.type)
.sort((a, b) => dayjs(b.createdAt).valueOf() - dayjs(a.createdAt).valueOf());
type Result = { title: string, total?: number, items: RecordItem[] }[]
const result: Result = [{title: dayjs(newList[0].createdAt).format('YYYY-MM-DD'), items: [newList[0]]}];
for (let i = 1; i < newList.length; i++) {
const current = newList[i];
const last = result[result.length - 1];
if (dayjs(last.title).isSame(dayjs(current.createdAt), 'day')) {
last.items.push(current);
} else {
result.push({title: dayjs(current.createdAt).format('YYYY-MM-DD'), items: [current]});
}
}
result.map(group => {
group.total = group.items.reduce((sum, item) => {
console.log(sum);
console.log(item);
return sum + item.amount;
}, 0);
});
return result;
}
beforeCreate() {
this.$store.commit('fetchRecords');
}
type = '-';
recordTypeList = recordTypeList;
}
</script>
<style scoped lang="scss">
::v-deep {
.type-tabs-item {
background: #fde3cc;
&.selected {
background: #ffb13d;
}
}
.interval-tabs-item {
height: 48px;
}
}
%item {
padding: 8px 16px;
line-height: 24px;
display: flex;
justify-content: space-between;
align-content: center;
}
.title {
@extend %item;
}
.record {
background: white;
@extend %item;
}
.notes {
margin-right: auto;
margin-left: 16px;
color: #999;
}
</style>