当前位置: 首页 > article >正文

第4章 封装组件中级篇

1.导航菜单

2.进度条(progress)

--components/progress
	--src/index.vue
	--index.ts

src/index.vue

<template>
  <el-progress :percentage="p" v-bind="$attrs"></el-progress>
</template>

<script lang='ts' setup>
import { onMounted, ref } from 'vue'

// 标识动画加载过程中改变的值
let num = ref<number>(0)

let props = defineProps({
  // 进度条进度
  percentage: {
    type: Number,
    required: true
  },
  // 是否有动画效果
  isAnimate: {
    type: Boolean,
    default: false
  },
  // 动画时长(毫秒)
  time: {
    type: Number,
    default: 3000
  },
})

let p = ref(0)

onMounted(() => {
  if (props.isAnimate) {
    // 规定时间内加载完成
    let t = Math.ceil(props.time / props.percentage)
    let timer = setInterval(() => {
      p.value += 1
      if (p.value >= props.percentage) {
        p.value = props.percentage
        clearInterval(timer)
      }
    }, t)
  }
})
</script>

<style lang='scss' scoped>
</style>

index.ts

import { App } from 'vue'
import progress from './src/index.vue'

// 让这个组件可以通过use的形式使用
export default {
  install(app: App) {
    app.component('m-progress', progress)
  }
}

修改components/index.ts中的文件

import { App } from 'vue'
import progress from './progress'

const components = [
  progress
]

export default {
  install(app: App) {
    components.map(item => {
      app.use(item)
    })
  }
}

在vieew/progress/index.vue中使用
vieew/progress/index.vue

<template>
  <div>
    <m-progress isAnimate :percentage="60"></m-progress>
    <br />
    <m-progress isAnimate status="success" :stroke-width="20" :percentage="60"></m-progress>
    <br />
    <m-progress :time="5000" type="circle" isAnimate :percentage="60"></m-progress>
  </div>
</template>

<script lang='ts' setup>
</script>

<style lang='scss' scoped>
</style>

3.时间选择器(chooseTime)

-- components/chooseTime
	--src/index.vue
	--index.ts

src/index.vue

<template>
  <div style="display: flex;">
    <div style="margin-right: 20px;">
      <el-time-select
        v-model="startTime"
        :placeholder="startPlaceholder"
        :start="startTimeStart"
        :step="startStep"
        :end="startTimeEnd"
        v-bind="$attrs.startOptions"
      ></el-time-select>
    </div>
    <div>
      <el-time-select
        v-model="endTime"
        :min-time="startTime"
        :placeholder="endPlaceholder"
        :start="endTimeStart"
        :step="endStep"
        :end="endTimeEnd"
        :disabled="endTimeDisabled"
        v-bind="$attrs.endOptions"
      ></el-time-select>
    </div>
  </div>
</template>

<script lang='ts' setup>
import {ref, watch} from 'vue'

let props = defineProps({
  // 开始时间的占位符
  startPlaceholder: {
    type: String,
    default: '请选择开始时间'
  },
  // 结束时间的占位符
  endPlaceholder: {
    type: String,
    default: '请选择结束时间'
  },
  // 开始时间的开始选择
  startTimeStart: {
    type: String,
    default: "08:00"
  },
  // 开始时间的步进
  startStep: {
    type: String,
    default: "00:30"
  },
  // 开始时间的结束选择
  startTimeEnd: {
    type: String,
    default: "24:00"
  },
  // 结束时间的开始选择
  endTimeStart: {
    type: String,
    default: "08:00"
  },
  // 结束时间的步进
  endStep: {
    type: String,
    default: "00:30"
  },
  // 结束时间的结束选择
  endTimeEnd: {
    type: String,
    default: "24:00"
  },
})

let emits = defineEmits(['startChange', 'endChange'])

// 开始时间
let startTime = ref<string>('')
// 结束时间
let endTime = ref<string>('')
// 是否禁用结束时间
let endTimeDisabled = ref<boolean>(true)

// 监听开始时间的变化
watch(() => startTime.value, val => {
  if (val === '') {
    endTime.value = ''
    endTimeDisabled.value = true
  }
  else {
    endTimeDisabled.value = false
    // 给父组件分发事件
    emits('startChange', val)
  }
})

// 监听结束时间的变化
watch(() => endTime.value, val => {
  if (val !== '') {
    emits('endChange', {
      startTime: startTime.value,
      endTime: val
    })
  }
})
</script>

<style lang='scss' scoped>
</style>

index.ts

import { App } from 'vue'
import chooseTime from './src/index.vue'

// 让这个组件可以通过use的形式使用
export default {
  install(app: App) {
    app.component('m-choose-time', chooseTime)
  }
}

修改components/index.ts中的文件

import { App } from 'vue'
import chooseTime from './chooseTime'

const components = [
  chooseTime
]

export default {
  install(app: App) {
    components.map(item => {
      app.use(item)
    })
  }
}

在views/chooseTime/index.vue中使用

<template>
  <div>
    <m-choose-time :startOptions="startOptions" @startChange="startChange" @endChange="endChange"></m-choose-time>
    <br />
    <br />
  </div>
</template>

<script lang='ts' setup>
interface endValue {
  startTime: string,
  endTime: string
}
interface dateEndValue {
  startDate: Date,
  endDate: Date
}
let startChange = (val: string) => {
  console.log('startChange', val)
}
let endChange = (val: endValue) => {
  console.log('endChange', val)
}
let startOptions = {
  // size: 'mini',
  // clearable: false
}
</script>

<style lang='scss' scoped>
</style>

4.日期选择器(chooseDate)

--components/chooseDate
	--src/index.vue
	--index.js

src/index.vue

<template>
  <div style="display: flex;">
    <div style="margin-right: 20px;">
      <el-date-picker
        v-model="startDate"
        type="date"
        :placeholder="startPlaceholder"
        :disabledDate="startDisabledDate"
        v-bind="$attrs.startOptions"
      ></el-date-picker>
    </div>
    <div>
      <el-date-picker
        v-model="endDate"
        type="date"
        :placeholder="endPlaceholder"
        :disabled="endDateDisabled"
        :disabledDate="endDisabledDate"
        v-bind="$attrs.endOptions"
      ></el-date-picker>
    </div>
  </div>
</template>

<script lang='ts' setup>
import { ref, watch } from 'vue'

let props = defineProps({
  // 开始日期的占位符
  startPlaceholder: {
    type: String,
    default: '请选择开始日期'
  },
  // 结束日期的占位符
  endPlaceholder: {
    type: String,
    default: '请选择结束日期'
  },
  // 是否禁用选择今天之前的日期
  disableToday: {
    type: Boolean,
    default: true
  }
})

let emits = defineEmits(['startChange', 'endChange'])

// 开始日期
let startDate = ref<Date | null>(null)
// 结束日期
let endDate = ref<Date | null>(null)
// 控制结束日期的禁用状态
let endDateDisabled = ref<boolean>(true)

// 禁用开始日期的函数
let startDisabledDate = (time: Date) => {
  if (props.disableToday) return time.getTime() < Date.now() - 1000 * 60 * 60 * 24
}
// 禁用结束日期的函数
let endDisabledDate = (time: Date) => {
  if (startDate.value) {
    return time.getTime() < startDate.value.getTime() + 1000 * 60 * 60 * 24
  }
}

// 监听开始的日期
watch(() => startDate.value, val => {
  if (!val) {
    endDateDisabled.value = true
    endDate.value = null
  } else {
    emits('startChange', val)
    endDateDisabled.value = false
  }
})
// 监听结束的日期
watch(() => endDate.value, val => {
  if (val) {
    emits('endChange', {
      startDate: startDate.value,
      endDate: val
    })
  }
})
</script>

<style lang='scss' scoped>
</style>

index.ts

import { App } from 'vue'
import chooseDate from './src/index.vue'

// 让这个组件可以通过use的形式使用
export default {
  install(app: App) {
    app.component('m-choose-date', chooseDate)
  }
}

修改components/index.ts中的文件

import { App } from 'vue'
import chooseDate from './chooseDate'

const components = [
  chooseDate
]

export default {
  install(app: App) {
    components.map(item => {
      app.use(item)
    })
  }
}

在项目中使用:views/chooseDate


<template>
  <div>
    <m-choose-date :disableToday="false" :startOptions="startOptions" @startChange="dateStartChange" @endChange="dateEndChange"></m-choose-date>
  </div>
</template>

<script lang='ts' setup>
interface endValue {
  startTime: string,
  endTime: string
}
interface dateEndValue {
  startDate: Date,
  endDate: Date
}
let dateStartChange = (val: Date) => {
  console.log(val)
}
let dateEndChange = (val: dateEndValue) => {
  console.log(val)
}
let startOptions = {
  // size: 'mini',
  // clearable: false
}
</script>

<style lang='scss' scoped>
</style>

5.城市选择器(chooseCity)

6.总结

导航菜单
需求分析
数据设计
二级菜单如何实现
集成更多属性
tsx 的使用
递归的使用
无限层级菜单如何实现
进度条
改变进度实现动态进度条
时间选择器
开始时间和结束时间设置
开始时间和结束时间联动
分发事件
日期选择器
开始日期和结束日期设置
开始日期和结束日期联动
分发事件
城市选择器
需求分析
获取城市数据
组件组合式使用
按城市选择逻辑
按省份选择逻辑
点击跳转位置
分发事件

http://www.kler.cn/a/6718.html

相关文章:

  • uniapp 自定义加载组件,全屏加载,局部加载 (微信小程序)
  • 定长滑动窗口基础模板题:LeetCode——2379.得到K个黑块的最少涂色次数和643.子数组最大平均数 1
  • 【大模型】prompt实践总结
  • Jmeter 如何导入证书并调用https请求
  • 01_MinIO部署(Windows单节点部署/Docker化部署)
  • 每日一练 | 包过滤防火墙的工作原理
  • Vue项目笔记
  • 如何防止服务器数据轻易泄露
  • React+Typescript+Electron 开发跨平台桌面应用教程
  • HarmonyOS/OpenHarmony应用开发-Stage模型ArkTS语言AbilityConstant
  • 保姆式教学-实现天空盒旋转
  • ShellBrowser .NET Components released
  • 【数据结构】七种常见的排序
  • 【Redis学习】Redis管道
  • Leetcode.112 路径总和
  • 什么是编码和解码
  • GC 日志
  • 【面试】MySQL面试题
  • 分布式事务·入门与解决·壹
  • 【UML建模】用例图(Use Case Diagram)
  • CUDA编程(二):核函数与线程层级
  • 【AUTOSAR】【Lin通信】LinIf
  • 【OpenCV-Python】cvui 之 复选框
  • 浪潮信息:2025年,实现数据中心风冷、液冷同价
  • vue中 使用假的进度条数字插件:fake-progress
  • QT完善登录界面Ⅱ