vue.js实现仿原生ios时间选择组件实例代码

yizhihongxing

下面就是“vue.js实现仿原生ios时间选择组件实例代码”的完整攻略。

一、需求分析

首先,我们需要明确该时间选择组件的需求。该组件应该具有以下几个特点:

  • 类似原生 iOS 的时间选择器的样式;
  • 可以选择小时、分钟;
  • 通过点击取消和确认按钮,可以改变选择的时间;
  • 可以通过外部传入初始时间;
  • 选择时间后,应该将选择的时间通过事件回传给外部。

二、实现思路

经过需求分析,我们可以确定该选择器需要至少两个组件:一个是显示时间的组件,另一个是选择时间的组件。

我们可以先实现一个选择时间的组件,在组件内,使用 Range Slider 实现选择小时和分钟的功能。然后,使用 Vue 的路由功能,在主页上添加一个按钮,点击该按钮,页面跳转到选择器页面,并加载时间选择器组件。

在选择器页面中,将选择器组件和确认、取消按钮放在一个模拟的 iPhone 工具条中,通过该工具条向上滑动时显示。选择器组件接收外部传入的时间参数,并可通过 emit 方法向外部回传选择的时间。

三、代码实现

1. 选择器组件

选择器组件需要有以下功能:

  • 根据外部传入的时间参数初始化显示时间;
  • 使用 Range Slider 组件实现选择小时和分钟的功能;
  • 点击取消和确认按钮时,返回选择的时间。

代码如下:

<template>
  <div class="picker-container">
    <div class="picker-mask"></div>
    <div class="picker">
      <div class="picker-header">
        <button class="cancel-button" @click="cancel">取消</button>
        <button class="confirm-button" @click="confirm">确定</button>
      </div>
      <div class="picker-body">
        <div class="picker-column">
          <div class="picker-label">{{ "0" + hour }}</div>
          <input type="range" min="1" max="24" class="picker-range" @input="setHour" v-model="hour" />
        </div>
        <div class="picker-divider"></div>
        <div class="picker-column">
          <div class="picker-label">{{ "0" + minute }}</div>
          <input type="range" min="0" max="59" class="picker-range" @input="setMinute" v-model="minute" />
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    // 初始化时间
    time: {
      type: String,
      default: "00:00",
    },
  },
  data() {
    const [hour, minute] = this.time.split(":");
    return {
      hour,
      minute,
    };
  },
  methods: {
    // 设置小时
    setHour(event) {
      this.hour = event.target.value.padStart(2, "0");
    },
    // 设置分钟
    setMinute(event) {
      this.minute = event.target.value.padStart(2, "0");
    },
    // 确定按钮点击事件
    confirm() {
      this.$emit("pick", `${this.hour}:${this.minute}`);
    },
    // 取消按钮点击事件
    cancel() {
      this.$emit("cancel");
    },
  },
};
</script>

<style scoped>
.picker-container {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 999;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}
.picker-mask {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
}
.picker {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: 500px;
  height: 200px;
  margin: 0 20px;
  background-color: #f5f5f5;
  border-radius: 5px;
  overflow: hidden;
}
.picker-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 40px;
  padding: 0 10px;
  background-color: #eee;
}
.picker-header button {
  font-size: 16px;
  font-weight: bold;
  color: #007aff;
  background: none;
  border: none;
  outline: none;
  cursor: pointer;
}
.picker-body {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
  padding: 20px;
}
.picker-column {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
.picker-label {
  font-size: 36px;
  font-weight: bold;
}
.picker-range {
  width: 100%;
  margin-top: 10px;
  cursor: pointer;
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
}
.picker-range::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 16px;
  height: 16px;
  background-color: #007aff;
  border-radius: 50%;
  cursor: pointer;
}
.picker-range::-moz-range-thumb {
  -moz-appearance: none;
  width: 16px;
  height: 16px;
  background-color: #007aff;
  border-radius: 50%;
  cursor: pointer;
}
.picker-divider {
  margin: 0 20px;
  border-right: 1px solid #ccc;
}
</style>

2. 主页

在主页中添加一个按钮,点击该按钮,跳转到选择器页面。代码如下:

<template>
  <div>
    <button class="show-picker-button" @click="showPicker">显示时间选择器</button>
  </div>
</template>

<script>
export default {
  methods: {
    showPicker() {
      this.$router.push("/picker");
    },
  },
};
</script>

<style scoped>
.show-picker-button {
  background-color: #007aff;
  color: #fff;
  font-size: 16px;
  padding: 10px 20px;
  border: none;
  border-radius: 5px;
  cursor: pointer;
}
</style>

3. 选择器页面

在选择器页面中,将选择器组件、确认、取消按钮放在一个模拟的 iPhone 工具条中。代码如下:

<template>
  <div class="picker-page">
    <comp-iphonetoolbar>
      <h1 slot="title">时间选择器</h1>
      <span slot="left" @click="cancel">取消</span>
      <span slot="right" @click="confirm">确定</span>
    </comp-iphonetoolbar>
    <picker :time="time" @pick="pick" @cancel="cancel" />
  </div>
</template>

<script>
import CompIphoneToolbar from "@/components/CompIphoneToolbar";
import Picker from "@/components/Picker";

export default {
  components: {
    CompIphoneToolbar,
    Picker,
  },
  data() {
    return {
      time: "12:00",
    };
  },
  methods: {
    // 确定按钮点击事件,将选择的时间保存
    confirm(time) {
      this.time = time;
      this.$router.go(-1);
    },
    // 取消按钮点击事件,返回上一页
    cancel() {
      this.$router.go(-1);
    },
    // 接收选择器组件发出的时间事件
    pick(time) {
      this.time = time;
    },
  },
};
</script>

<style scoped>
.picker-page {
  height: 100%;
  display: flex;
  flex-direction: column;
}
</style>

到这里,可以启动项目,点击主页上的按钮,跳转到选择器页面,并显示时间选择器。选择时间后,点击确认按钮,返回主页,显示选择的时间。

4. 示例说明

示例1:在主页上添加两个按钮

在主页上,添加一个按钮,点击该按钮显示时间选择器,并将选择的时间保存。再添加一个按钮,点击该按钮显示上次保存的时间。

代码如下:

<template>
  <div>
    <button @click="showPickerAndSave">选择时间并保存</button>
    <button @click="showPickerWithLastSavedTime">显示上次保存的时间</button>
    <div v-if="!!lastSavedTime">上次保存的时间是{{ lastSavedTime }}</div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      lastSavedTime: "",
    };
  },
  methods: {
    async showPickerAndSave() {
      const { default: Picker } = await import("../components/Picker");

      const time = await new Promise((resolve) => {
        const PickerView = Vue.extend(Picker);
        const vm = new PickerView({
          propsData: {
            time: this.lastSavedTime || "12:00",
          },
          methods: {
            pick(time) {
              resolve(time);
            },
            cancel() {
              resolve(false);
            },
          },
        }).$mount();

        document.querySelector("body").appendChild(vm.$el);
      });

      if (time !== false) {
        this.lastSavedTime = time;
      }
    },
    async showPickerWithLastSavedTime() {
      const { default: Picker } = await import("../components/Picker");

      await new Promise((resolve) => {
        const PickerView = Vue.extend(Picker);
        const vm = new PickerView({
          propsData: {
            time: this.lastSavedTime || "12:00",
          },
          methods: {
            pick(time) {
              resolve(time);
            },
            cancel() {
              resolve(false);
            },
          },
        }).$mount();

        document.querySelector("body").appendChild(vm.$el);
      });
    },
  },
};
</script>

示例2:支持多个时间选择器

该示例需要在主页添加一个按钮,点击该按钮可以添加一个时间选择器组件。每个时间选择器组件都可以选择不同的时间,并可以通过事件回传选择的时间。

代码如下:

<template>
  <div>
    <button @click="addPicker">添加时间选择器</button>
    <comp-iphonetoolbar v-if="pickers.length">
      <h1 slot="title">选择时间</h1>
      <span slot="left" @click="cancel">取消</span>
      <span slot="right" @click="confirm">确定</span>
    </comp-iphonetoolbar>
    <picker v-for="(picker, index) in pickers" :key="index" :time="picker" @pick="pick(index)" />
  </div>
</template>

<script>
import CompIphoneToolbar from "@/components/CompIphoneToolbar";
import Picker from "@/components/Picker";

export default {
  components: {
    CompIphoneToolbar,
    Picker,
  },
  data() {
    return {
      pickers: ["12:00"],
    };
  },
  methods: {
    // 添加时间选择器
    addPicker() {
      this.pickers.push("12:00");
    },
    // 接收选择器组件发出的时间事件
    pick(index) {
      return (time) => {
        this.$set(this.pickers, index, time);
      };
    },
    // 确定按钮点击事件,将选择的时间保存
    confirm() {
      console.log(this.pickers);
      this.$router.go(-1);
    },
    // 取消按钮点击事件,返回上一页
    cancel() {
      this.$router.go(-1);
    },
  },
};
</script>

<style scoped>
.picker-page {
  height: 100%;
  display: flex;
  flex-direction: column;
}
</style>

注意这个示例采用了响应式 APIpickers数组中的元素改变时需要使用$set方法来更新 DOM。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:vue.js实现仿原生ios时间选择组件实例代码 - Python技术站

(0)
上一篇 2023年5月29日
下一篇 2023年5月29日

相关文章

  • 分享Vue组件传值的几种常用方式(二)

    请听我详细讲解“分享Vue组件传值的几种常用方式(二)”的完整攻略。 一、前言 在Vue组件传值的开发过程中,我们通常会遇到如下问题:如何在不同的组件之间传递数据?如何在父子组件之间通信?如何在没有父子关系的组件之间传递数据?这些问题都可以通过不同的方式来解决。在上一篇文章中,我们分享了“prop与$emit”这种传值方式。而今天,我们来分享“provide…

    Vue 2023年5月27日
    00
  • 详解如何理解vue的key属性

    以下是详解如何理解vue的key属性的完整攻略: 1. 什么是Vue的key属性? Vue中的key属性是在使用v-for指令时用来提高性能和防止数据混乱的重要属性。key属性可以为每个v-for循环中的子元素设定一个唯一的标识符,Vue在渲染虚拟DOM节点时会根据key属性来判断哪些节点需要被更新,从而减少页面重新渲染的量,提高页面性能。 2. 如何理解V…

    Vue 2023年5月28日
    00
  • Vue filter介绍及详细使用

    Vue filter介绍及详细使用攻略 1. 什么是Vue filter Vue filter是Vue的一个功能,在Vue组件模板中使用{{ someData | filterName }}的方式,可以对一些字符串、数字、日期等进行处理,返回新的字符串、数字、日期等内容。可以用于格式化展示数据、处理一些业务逻辑等。 2. 如何定义Vue filter 在Vu…

    Vue 2023年5月28日
    00
  • 详细聊聊vue组件是如何实现组件通讯的

    Vue组件通讯是指在Vue应用中,组件之间通过交互实现信息传递和共享数据的一种方式。Vue提供了多种方式来实现组件通讯,如props、$emit、$parent、$children、eventBus、vuex等。在接下来的篇章中,我们将详细讲解Vue组件通讯的实现方式及其应用场景。 一、Props和$emit 在Vue组件中,子组件可以通过props属性来传…

    Vue 2023年5月29日
    00
  • Vue 日期获取的示例代码

    下面是“Vue日期获取的示例代码”的完整攻略。 示例代码: <template> <div> <p>当前日期:{{ currentDate }}</p> <p>当前时间:{{ currentTime }}</p> </div> </template> <sc…

    Vue 2023年5月28日
    00
  • vue3动态修改打包后的请求路径的操作代码

    要动态修改打包后的请求路径,需要通过修改Vue CLI中的webpack配置实现。下面是具体的步骤: 打开Vue项目所在目录,找到vue.config.js文件。如果该文件不存在则需要手动创建。 使用process.env.BASE_URL获取当前项目的基础路径,然后将该路径保存到变量中,这个变量可以在需要的地方被引用。 javascript const b…

    Vue 2023年5月28日
    00
  • Android面向切面基于AOP实现登录拦截的场景示例

    下面我来为您详细讲解“Android面向切面基于AOP实现登录拦截的场景示例”的完整攻略。 什么是AOP AOP(Aspect Oriented Programming),面向切面编程,是一种编程范式,它旨在解决开发中的横切关注点问题。横切关注点是指在整个应用中有多个不同的模块都需要共同解决的问题,比如日志、事务、缓存等。AOP可以帮助我们把这些横切关注点从…

    Vue 2023年5月28日
    00
  • React DnD如何处理拖拽详解

    React DnD是封装的HTML5拖放API的React组件,可用于构建拖放交互功能。下面详细讲解React DnD如何处理拖拽,在这个过程中,将提供两个示例说明。 1. 拖拽源 拖拽源是可以被拖拽的组件。在React DnD中,拖拽源分为两种:简单的拖拽源和自定义拖拽源。 简单拖拽源 简单的拖拽源指的是一个纯组件,该组件可以设置可以被拖拽的数据类型以及数…

    Vue 2023年5月28日
    00
合作推广
合作推广
分享本页
返回顶部