保持VueJS片段DRY

时间:2017-04-25 20:18:15

标签: javascript vue.js vuejs2

我有以下Vue HTML。我知道这可以用其他模块完成,但除非需要,否则我不想使用。我在客户填写的表单中有一个选择,其中每天的开始和结束时间为select。显然这可能是多余的,因为我将列出所有小时(在我的情况下每15分钟)作为option s每天2次和所有日子7次。它最终只有几百行代码...一小时select ...有没有更好的方法来保持这种干燥?我宁愿把它留在Vue土地上。或JS方法等...

<div class="col-xs-4">
  <select class="form-control" v-model="newPost.hours.sunday.opens">
    <option value="" selected>Opens:</option>
    <option value="12:00am">12:00am</option>
    <option value="12:15am">12:15am</option>
    <option value="12:30am">12:30am</option>
    <option value="12:45am">12:45am</option

...etc...etc x7

2 个答案:

答案 0 :(得分:6)

将所有时间的属性添加到组件中:

data() {
  return {
    times: ['12:00am', '12:15am', ...],
  }
}

然后在模板中使用v-for生成选项:

<select class="form-control" v-model="newPost.hours.sunday.opens">
  <option value="" selected>Opens:</option>
  <option v-for="time in times" :value="time">{{ time }}</option>
</select>

答案 1 :(得分:0)

将其作为数据属性传递是可能的,但我认为根据您传递给时间选择器组件的开始时间来计算时间范围会更好。您可以使用moment.js轻松创建15分钟的时间。组件内的步骤。所以不需要手动创建它。

然后你也可以修改关闭下拉菜单,这样它只显示开始时间之后的时间。动态更新。

使用['Monday', 'Tuesday', ...]创建两个时间选择器组件循环遍历v-for天。

在app组件中,我动态创建了空数据模型,因此您可以为每天准备对象。

请查看下面的演示或此fiddle

moment.locale('en');

const timePickerComponent = {
	props: {
  	day: String,
    caption: String,
    options: Object
  },
  template: `
  	<div>
    	<select class="form-control" v-model="timeSelected" @change="timeChanged">
        <option value="">{{caption}}</option>
        <option v-for="time in times">{{ time }}</option>
      </select>
    </div>
  `,
  data() {
  	return {
    	times: this.createTimes(),
      timeSelected: ''
    }
  },
  watch: {
  	'options.start'() {
    	this.times = this.createTimes(); // re-create times
    }
  },
  methods: {
  	timeChanged() {
    	console.log('changed', this.timeSelected)
    	this.$emit('changed', {day: this.day, selected: this.timeSelected});
    },
  	createTimes() {
    	// 0:00am to 0:00pm
      const formatStr = 'hh:mm a';
      let start = moment(this.options.start, formatStr);
      let range = this.options.hours; // 8 hours
      
      let times = new Array(range*4+1).fill(start);
      console.log(start, times);
    	return times.map((item, index) => {
      	return (index > 0 ? item.add(15, 'm') : item).format(formatStr);
      });
    }
  }
};

new Vue({
	el: '#app',
  data() {
  	return {
    	days: [
      'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'
      ],
    	openOptions: {
      	start: "12:00 am",
        hours: 24
      },
      closeOptions: {
      	start: "12:00 am",
        hours: 8
      },
      newPost: undefined
    }
  },
  created() {
  	this.newPost = this.createEmptyPost();
  },
  methods: {
  	createEmptyPost() {
    	let newPost = {};
      this.days.forEach((day) => {
        newPost[day] = {
        	openingTime: undefined,
          closingTime: undefined
        };
      });
      return newPost;
    },
  	closingChanged(val) {
    	this.newPost[val.day].closingTime = val.selected;
    },
  	openingChanged(val) {
    	console.log(val);
    	this.newPost[val.day].openingTime = val.selected;
      console.log(moment(val.selected, 'hh:mm a').hour());
      this.closeOptions.start = moment(val.selected, 'hh:mm a');
    }
  },
  components: {
  	timePicker: timePickerComponent
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.6/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.js"></script>
<div id="app">
  <div v-for="day in days">
    {{day}}:
    <time-picker :day="day" caption="Opens" :options="openOptions" @changed="openingChanged"></time-picker>
    <time-picker :day="day" caption="Closes" :options="closeOptions" @changed="closingChanged"></time-picker>
    <hr/>
  </div>
  
  <pre>
{{newPost}}
  </pre>
</div>