elementui :on-remove怎么用_当产品和我说elementUI的datepicker要加上时区

背景

背景ElementUIDatePicker组件是不能设置时区的,组件显示的时间所使用的时区是打开页面的客户端所在的系统所使用的时区。需求:我在本地打开页面,使用DatePicker组件筛选日志,组件中超过今天的时间置灰不可选。这个“今天”所使用的时区是特定的时区(比如美国纽约)。譬如:本地(中国)现在是2020-08-03 08:51:29,而美国纽约现在是2020-08-02 20:51:29,若DatePicker组件设置的时区是America/New_York,那么组件中则需要置灰3号以及之后的日期了(如图2)。

ed76090c1ff1d6b127f76672e9fbf18c.png图1

6c53f05dee73ca453ec6d7c0bc0eedfa.png

图2

那么现在来看看我是怎么实现这个需求的吧^_^(就这?)

看我

我不能直接修改node_modules\element-ui下的DatePicker组件代码呀,因为若是项目挪到其他环境,运行npm install,拿到的DatePicker代码还是它原来的代码,并不是你修改过的代码。

于是,我找到node_modules\element-ui\packages\date-picker这个文件夹,右键点击date-picker选择copy,然后来到项目名\src\components(这里选择你放组件的目录,不一定跟我的一样),右键点击components选择paste,这样就把DatePicker的组件代码拷贝到我们的组件目录下了。

我们可以在DatePicker组件的基础上实现一个自己的DatePicker,这样你就可以想怎么改就怎么改,简直就是为所欲为了哈哈。

对了,涉及到时区数据和时区转换,我用了moment-timezone包,所以你需要预先装好这个包:npm install moment-timezone -S

Step1 自定义DatePicker组件的引入和使用

  1. 打开\src\components\date-picker\src\picker\date-picker.js
//省略若干代码...
export default {
  mixins: [Picker],
  name: 'MyDatePicker', // 这里原来是ElDatePicker,现在修改为MyDatePicker
  //省略若干代码...
}
  1. 打开\src\main.js
//省略若干代码...
import MyDatePicker from '@/components/date-picker'
Vue.use(MyDatePicker)
  1. 组件中可以这样用(test.vue)
<template>
  <my-date-pickerv-model="dates"type="daterange":clearable="false"start-placeholder="Begin Date"end-placeholder="End Date":default-time="['00:00:00', '23:59:59']":timezone="getTimeZone()":picker-options="{disabledDate: time => {return time.getTime() > today.getTime()}}"
  >
  my-date-picker>
template>


Step2 超过“今天”的日期都置灰

我们是通过:picker-options="{disabledDate: time => {return time.getTime() > today.getTime()}}"这一行代码来实现这个功能的。
关键在于today这个Date对象,若是time > today则置灰。比如按照America/New_York时区,现在应该是2020-08-02 20:51:29,也就是说只要大于2020-08-02 23:59:59的时间,都要置灰。于是

<my-date-pickerv-model="dates"type="daterange":clearable="false"start-placeholder="Begin Date"end-placeholder="End Date":default-time="['00:00:00', '23:59:59']":timezone="getTimeZone()":picker-options="{disabledDate: time => {return time.getTime() > today.getTime()}}"
  >my-date-picker>template><script>import moment from 'moment-timezone'export default {name: 'MyCompo',
  data () {return {today: ''
    }
  },
  mounted () {// this.getTimeZone() 获取你想要使用的时区,这里我获取到的是`America/New_York`let str = moment().tz(this.getTimeZone()).set({'hour': 23, 'minute': 59, 'second': 59}).format('YYYY/MM/DD HH:mm:ss')this.today = new Date(str)
  }
}script>

效果如图:

3f9d0ed584eb899908ac897110b8bed9.png

Emmm,置灰没问题了,但是好像还有点不OK。3被高亮了(“今天”会高亮显示),按照America/New_York时区,“今天”应该是2号才对。继续……

Step3 “今天”高亮

我们右键点击“3”选择检查,看一下dom元素

708610416ccdc9c1e3c15bdfbf76c937.png

可以看到,它之所以会高亮,就是因为它使用了today类。
接下来我们康康代码中在哪里添加的today类,组件目录下搜索today

d2e1832e6ae5c848b8afa0120f6f9dc1.png

57582a7240092f0df41a455fcf2a5ba4.png

搜出来有3个文件,分别对应于日面板月面板年面板,由于时区只会影响到,不会影响到,所以我们只需要看date-table.vue就可以了。
我把关键的几行代码摘出来:

const now = getDateTimestamp(new Date());
const isToday = time === now;
if (isToday) {
  cell.type = 'today';
}

if ((cell.type === 'normal' || cell.type === 'today') && !cell.disabled) {
  classes.push('available');
  if (cell.type === 'today') {
    classes.push('today');
  }
} else {
  classes.push(cell.type);
}

可以看到关键在于now,若是time === now,则isTodaytrue,则cell.type的值为today,那么classes.push(cell.type)等价于classes.push('today'),即添加了today类。

也就是说,now要和时区相关。按照America/New_York时区,now应该是2020-08-02,这样才会高亮2号,而不是3号。
注意,date-table.vue是组件内部代码,所以代码里用到的时区信息应该是在使用组件的时候由timezone属性传入,这样才能使组件和外部代码的耦合度最低。

OK,那么我们来看下,date-table.vue文件里的代码要如何拿到这里传进来的timezone属性值。

Step4 传递timezone属性值

重点来了,到这步我们不得不稍微读一下源码了。

  1. 从入口文件开始:\src\components\date-picker\index.js
import DatePicker from './src/picker/date-picker';

/* istanbul ignore next */
DatePicker.install = function install(Vue) {
  Vue.component(DatePicker.name, DatePicker);
};

export default DatePicker;

可以看到入口文件主要就是加载了DatePicker模块,为它加了一个安装函数install之后把它暴露出去。所以重点是DatePicker模块。

  1. \src\components\date-picker\src\picker\date-picker.js
import Picker from '../picker';
import DatePanel from '../panel/date';
import DateRangePanel from '../panel/date-range';
import MonthRangePanel from '../panel/month-range';

const getPanel = function(type) {...}
export default {
  mixins: [Picker],
  name: 'MyDatePicker',
  props: {...},
  watch: {
    type(type) {
      if (this.picker) {
        this.unmountPicker();
        this.panel = getPanel(type);
        this.mountPicker();
      } else {
        this.panel = getPanel(type);
      }
    }
  },

  created() {
    this.panel = getPanel(this.type);
  }
}

可以看到这个模块mixinsPicker,我们再接着看Picker

  1. \src\components\date-picker\src\picker.vue

date-picker.jsmixins 了picker.vue,两者合起来可看成是一个组件,这个组件也就是我们暴露出去的MyDatePicker组件,也就是说,我们通过传进来的timezone属性值可以在picker.vueprops接收到。于是picker.vue修改后的代码如下:

<template>
...
template>
<script>// 省略若干importimport moment from 'moment-timezone'// 省略若干代码export default {props: {// 省略若干代码
    timezone: {type: String,default: moment.tz.guess() // 没有传则使用本地的时区
    }
  },// 省略若干代码
}script>

MyDatePicker组件根据不同的type选择不同的子组件(DatePanelDateRangePanelMonthRangePanel等)进行挂载,我们可以在它挂载的时候把timezone传给子组件:

// picker.vue
// ...
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值