Vue3电商项目实战-结算支付 2【03-结算-对话框组件封装、04-结算-收货地址-切换】

news2025/7/18 21:19:34

文章目录

    • 03-结算-对话框组件封装
    • 04-结算-收货地址-切换


03-结算-对话框组件封装

目的:实现一个对话框组件可设置标题,动态插入内容,动态插入底部操作按钮,打开关闭功能。

在这里插入图片描述

大致步骤:

  • 参照xtx-confirm定义一个基础布局
  • 实现设置标题
  • 实现插入内容
  • 实现插入底部操作按钮
  • 实现打开关闭功能

落的代码:

1.参照xtx-confirm定义一个基础布局
src/components/library/xtx-dialog.vue 定义组件

<template>
  <div class="xtx-dialog" :class="{fade}">
    <div class="wrapper" :class="{fade}">
      <div class="header">
        <h3>切换收货地址</h3>
        <a href="JavaScript:;" class="iconfont icon-close-new"></a>
      </div>
      <div class="body">
        对话框内容
      </div>
      <div class="footer">
        <XtxButton type="gray" style="margin-right:20px">取消</XtxButton>
        <XtxButton type="primary">确认</XtxButton>
      </div>
    </div>
  </div>
</template>
<script>
import { ref, onMounted } from 'vue'
export default {
  name: 'XtxDialog',
  setup () {
    const fade = ref(false)
    onMounted(() => {
      // 结构和样式同时加上无过度效果,需要些延时。
      setTimeout(() => {
        fade.value = true
      }, 0)
    })
    return { fade }
  }
}
</script>
<style scoped lang="less">
.xtx-dialog {
  position: fixed;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  z-index: 8887;
  background: rgba(0,0,0,0);
  &.fade {
    transition: all 0.4s;
    background: rgba(0,0,0,.5);
  }
  .wrapper {
    width: 600px;
    background: #fff;
    border-radius: 4px;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%,-60%);
    opacity: 0;
    &.fade {
      transition: all 0.4s;
      transform: translate(-50%,-50%);
      opacity: 1;
    }
    .body {
      padding: 20px 40px;
      font-size: 16px;
      .icon-warning {
        color: @priceColor;
        margin-right: 3px;
        font-size: 16px;
      }
    }
    .footer {
      text-align: center;
      padding: 10px 0 30px 0;
    }
    .header {
      position: relative;
      height: 70px;
      line-height: 70px;
      padding: 0 20px;
      border-bottom: 1px solid #f5f5f5;
      h3 {
        font-weight: normal;
        font-size: 18px;
      }
      a {
        position: absolute;
        right: 25px;
        top: 25px;
        font-size: 24px;
        width: 20px;
        height: 20px;
        line-height: 20px;
        text-align: center;
        color: #999;
        &:hover {
          color: #666;
        }
      }
    }
  }
}
</style>

src/views/member/pay/components/checkout-address.vue 使用组件

<XtxDialog />

2.实现设置标题
src/components/library/xtx-dialog.vue 定义组件

  props: {
    title: {
      type: String,
      default: ''
    }
  },
      <div class="header">
        <h3>{{title}}</h3>
        <a href="JavaScript:;" class="iconfont icon-close-new"></a>
      </div>

src/views/member/pay/components/checkout-address.vue 使用组件

<XtxDialog title="切换收货地址" />

3.实现插入内容
src/components/library/xtx-dialog.vue 定义组件

      <div class="body">
+        <slot />
      </div>

src/views/member/pay/components/checkout-address.vue 使用组件

<XtxDialog title="切换收货地址" >
  对话框内容
</XtxDialog>

4.实现插入底部操作按钮
src/components/library/xtx-dialog.vue 定义组件

      <div class="footer">
+        <slot name="footer" />
      </div>

src/views/member/pay/components/checkout-address.vue 使用组件

    <XtxDialog title="切换收货地址">
      对话框内容
      <!-- vue3.0 仅支持v-slot+template写法 -->  
      <template v-slot:footer>
        <XtxButton type="gray" style="margin-right:20px">取消</XtxButton>
        <XtxButton type="primary">确认</XtxButton>
      </template>
    </XtxDialog>

5.实现打开关闭功能

  • 1.打开关闭通过v-model来实现
  • 2.动画根据打开关闭状态来控制

src/components/library/xtx-dialog.vue 定义组件

<div class="xtx-dialog" :class="{fade}" v-show="visible">
import { ref, watch } from 'vue'
export default {
  name: 'XtxDialog',
  props: {
    title: {
      type: String,
      default: ''
    },
    visible: {
      type: Boolean,
      default: false
    }
  },
  setup (props, { emit }) {
    const fade = ref(true)
    // 改造动画执行时机
    watch(() => props.visible, () => {
      setTimeout(() => {
        fade.value = props.visible
      }, 0)
    }, { immediate: true })
    // 关闭的时候通知父组件
    const close = () => {
      emit('update:visible', false)
    }
    return { fade, close }
  }
}

src/views/member/pay/components/checkout-address.vue 使用组件

    <div class="action">
+      <XtxButton @click="dialogVisible=true" class="btn">切换地址</XtxButton>
      <XtxButton class="btn">添加地址</XtxButton>
    </div>
+    <XtxDialog title="切换收货地址" v-model:visible="dialogVisible">
      对话框内容
      <template v-slot:footer>
+        <XtxButton @click="dialogVisible=false" type="gray" style="margin-right:20px">取消</XtxButton>
+        <XtxButton @click="dialogVisible=false" type="primary">确认</XtxButton>
      </template>
    </XtxDialog>
    // 对话框显示隐藏
    const dialogVisible = ref(false)
    return { dialogVisible }

04-结算-收货地址-切换

目的:能够切换当前显示的地址,且通知结算组件当前地址ID用于提交订单使用。

在这里插入图片描述

大致步骤:

  • 组件初始化的时候需要得到一个默认的地址ID通知给结算组件
  • 对话框中渲染一个地址列表
  • 实现可以选中的效果,点击确认后变更显示地址,通知结算组件地址ID

落地代码:

1.组件初始化的时候需要得到一个默认的地址ID通知给结算组件
地址组件 components/checkout-address.vue

   // 对话框显示隐藏
    const dialogVisible = ref(false)
+    // 默认通知一个地址ID给父
+    emit('change', showAddress.value?.id)
    return { showAddress, dialogVisible }
  // 1. 在拥有根元素的组件中,触发自定义事件,有没有emits选项无所谓
  // 2. 如果你的组件渲染的代码片段,vue3.0规范,需要在emits中申明你所触发的自定义事件
  // 3. 提倡:你发了自定义事件,需要在emits选项申明下,代码可读性很高
  emits: ['change'],

结算组件 checkout.vue

    // 需要提交的字段
    const requestParams = reactive({
      addressId: null
    })
    // 切换地址
    const changeAddress = (id) => {
      requestParams.addressId = id
    }
    return { checkoutInfo, changeAddress }
<CheckoutAddress @change="changeAddress" :list="checkoutInfo.userAddresses" />

2.对话框中渲染一个地址列表
地址组件 components/checkout-address.vue

    <XtxDialog title="切换收货地址" v-model:visible="dialogVisible">
+      <div class="text item" v-for="item in list" :key="item.id">
+        <ul>
+          <li><span><i/><i/>人:</span>{{item.receiver}}</li>
+          <li><span>联系方式:</span>{{item.contact}}</li>
+          <li><span>收货地址:</span>{{item.fullLocation.replace(/ /g,'')+item.address}}</li>
+        </ul>
+      </div>
      <template v-slot:footer>
.xtx-dialog {
  .text {
    flex: 1;
    min-height: 90px;
    display: flex;
    align-items: center;
    &.item {
      border: 1px solid #f5f5f5;
      margin-bottom: 10px;
      cursor: pointer;
      &.active,&:hover {
        border-color: @xtxColor;
        background: lighten(@xtxColor,50%);
      }
      > ul {
        padding: 10px;
        font-size: 14px;
        line-height: 30px;
      }
    }
  }
}

3.实现可以选中的效果,点击确认后变更显示地址,通知结算组件地址ID
地址组件 components/checkout-address.vue

  // 对话框显示隐藏
    const dialogVisible = ref(false)
    // 打开对话框
    const openDialog = () => {
      dialogVisible.value = true
      selectedAddress.value = null
    }
    // 确认地址
    const confirmAddress = () => {
      dialogVisible.value = false
      showAddress.value = selectedAddress.value
      // 默认通知一个地址ID给父
      emit('change', showAddress.value?.id)
    }
    // 选择的地址
    const selectedAddress = ref(null)
    return { showAddress, dialogVisible, selectedAddress, openDialog, confirmAddress }
    <XtxDialog title="切换收货地址" v-model:visible="dialogVisible">
      <div
        class="text item"
+        :class="{active:selectedAddress&&item.id===selectedAddress.id}"
+        @click="selectedAddress=item"
        v-for="item in list"
        :key="item.id">
        <ul>
<XtxButton @click="openDialog()" class="btn">切换地址</XtxButton>
<XtxButton @click="confirmAddress()" type="primary">确认</XtxButton>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/404788.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MFC常用控件使用(文本框、编辑框、下拉框、列表控件、树控件)

简介 本文章主要介绍下MFC常用控件的使用&#xff0c;包括静态文本框(Static Text)、编辑框(Edit Control)、下拉框(Combo Box)、列表控件(List Control)、树控件(Tree Control)的使用。 创建项目 我们选择 文件->新建->新建项目&#xff0c;选择MFC程序 选择基于对话…

二叉树的三种遍历

二叉树的遍历可以有&#xff1a;先序遍历、中序遍历、后序遍历先序遍历&#xff1a;根、左子树&#xff0c;右子树中序遍历&#xff1a;左子树、根、右子树后序遍历&#xff1a;左子树、右子树、根下面是我画图理解三种遍历&#xff1a;二叉树里都是分为左子树和右子树。分治思…

Linux文件基础I/O

文件IO文件的常识基础IO为什么要学习操作系统的文件操作C语言对于函数接口的使用接口函数介绍如何理解文件文件描述符重定向更新给模拟实现的shell增加重定向功能为什么linux下一切皆文件&#xff1f;缓冲区为什么要有缓冲区缓冲区对应的刷新策略缓冲区的位置在哪里文件的常识 …

VSCode:添加SSH远程连接

有的时候我们的代码保存于远程服务器&#xff0c;通过VSCode可以通过SSH进行连接&#xff0c;完成远程的编辑。在VSCode的扩展中安装Remote - SSH点击左侧工具栏的远程资源管理器&#xff0c;然后点加号输入ssh的机器及用户名选择一个用于保存ssh配置文件的路径&#xff0c;默认…

Tabs Studio 5.3.0 多功能标签 Crack

在 Visual Studio 2022 和 SQL Server Management Studio 中轻松处理任意数量和类型的文档 你爱写代码&#xff0c;不会好好扫描文档找到你需要切换到的文件名&#xff0c;然后扫描文件菜单下拉列表&#xff0c;然后求助于解决方案资源管理器或搜索。只有在您需要切换到另一个…

javascript入门基础

目录 前言 引入&#xff1a;html中嵌入javascript有三种方式 0. 变量&#xff08;var、let&#xff09; 1. 函数 1.1 普通函数 和 箭头函数 1.1.2 普通函数中的this 1.1.3 箭头函数没有自己的this 1.1.4 普通函数有arguments方法&#xff0c;箭头函数没有 1.1.5 箭头函…

MS python学习(9)

开始学习第二辑 more python for beginners talking about formating https://learn.microsoft.com/en-us/shows/more-python-for-beginners/formatting-and-linting–more-python-for-beginners-2-of-20 Formating 代码格式化&#xff1a;使用pylint工具来帮助遵循PEP8(pyt…

conda创建一个地理开发环境

conda创建一个地理开发环境1. 环境内包说明2. 创建yml文件3. 创建地理开发环境使用conda安装包的时候&#xff0c;经常遇到包之间相互冲突。为了方便配置环境&#xff0c;测试了常用的地理开发所需要的各种包&#xff0c;生成了yml文件方便一键安装。 Linux下pip基本可以成功安…

手敲Mybatis(七)-细化xml语句解析和构建

前言为什么这一章节要细分之前的解析xml处理逻辑&#xff0c;原因是违反了单一原则设计&#xff0c;职责并不明确&#xff0c;将Sql语句、参数、返回值等等一切都进行解析&#xff0c;那么这种的需要拆开&#xff0c;为了后面可维护可扩展&#xff0c;例如Mapper级别的有mapper…

k8s client-go源码解析之informer三

Informer&#xff08;三&#xff09; 注意&#xff1a;本文内容为学习笔记&#xff0c;内容为个人见解&#xff0c;不保证准确性&#xff0c;但欢迎大家讨论何指教。 觉得文章不错请关注跟博客及github 本篇介绍DeltaFIFO及indexer。 informer大致工作流程如下&#xff1a; …

顺序表来喏!!!

前言&#xff1a;还记得前面的文章&#xff1a;《通讯录的实现》吗&#xff1f;通讯录的完成就借助了顺序表这种数据结构&#xff01;&#xff01;&#xff01;那么今天我们就来介绍我们的顺序表介绍顺序表前&#xff0c;我们来了解一下线性表的概念线性表&#xff1a;线性表&a…

mysql笔试题18道

部门表、员工表、薪水等级表 1.取得每个部门最高薪水人员名称 第一步&#xff1a;取得每个部门最高薪水作为临时表t select deptno,max(sal) as maxSal from emp group by deptno 第二步&#xff1a;临时表t与emp表连接条件 e.deptnot.deptno and e.salt.maxSal select …

Spring - Spring IoC 容器相关面试题总结

文章目录01. Spring IoC 和依赖注入是什么&#xff1f;02. Spring IoC 的优点和缺点分别是什么&#xff1f;03. Spring IoC 有什么作用和功能&#xff1f;04. Spring 依赖注入的方式&#xff1f;05. Spring 构造器注入和 setter 方法注入的区别&#xff1f;06. Spring 依赖注入…

嵌入式系统实验——【玄武F103开发板】按key1熄灭两个LED灯、松开恢复点亮

这里写目录标题一、任务目标&#xff08;一&#xff09;分析二、设计思路&#xff08;一&#xff09;开启KEY1对应的GPIOx时钟1.找到KEY1&#xff08;PE3&#xff09;所在的GPIOx端口2.开启GPIOE端口时钟3.清空PE3的端口位4.设置PE3的端口位为输出模式的上拉模式5.一个易错点&a…

二分——力扣篇

二分——力扣篇搜索旋转排序数组搜索旋转排序数组II寻找旋转排序数组中的最小值寻找旋转排序数组中的最小值II搜索旋转排序数组 定理一&#xff1a;只有在顺序区间内才可以通过区间两端的数值判断target是否在其中。 定理二&#xff1a;判断顺序区间还是乱序区间&#xff0c;只…

案例学习20之内存长期占用导致系统缓慢

前言&#xff1a; 发现问题&#xff0c;解决问题&#xff0c;是贯穿整个项目开发过程的事情&#xff0c;能够处理更多的问题&#xff0c;随着经验的丰富&#xff0c;提前预知更多的问题&#xff0c;让问题不出现是最好的解决问题方式。 问题背景&#xff1a; 项目运行过程中出现…

基于redis实现点赞数,点击数,排行榜

使用场景 对于某些视频或者文章有点赞数和点击数, 通过这些数据就可以进行排行榜的功能了 使用异步队列 redis的集合 A.php //点击数 $redis->zIncrBy(click.:.date(Ymd),1,$videoId); //点赞数 $redis->zIncrBy(love.:.$videoId,1,$$user); //获取当前video的播放数…

PMP项目管理项目范围管理

目录1 项目范围管理概述2 规划范围管理3 收集需求4 定义范围5 创建 WBS6 确认范围7 控制范围1 项目范围管理概述 项目范围管理包括确保项目做且只做所需的全部工作&#xff0c;以成功完成项目的各 个过程。管理项目范围主要在于定义和控制哪些工作应在项目内&#xff0c;哪些工…

界面原型设计

引用锤子科技视觉设计总监——罗子雄在重庆TEDx活动上说的一小段话: 每当我们看到一些美妙的设计的时候,很多人心里面会有一种冲动,这种冲动会让你们想去创造一些新的东西,创造一些美妙的事物。 我们常说用户体验用户体验,用户使用你的软件,第一个会接触的是什么?没错,…

读WiscKey: Separating Keys from Values in SSD-conscious Storage

在我看来本论文的主要贡献在于相对减轻了传统LSM compact所带来的写放大问题。其核心设计在于使key、value分离以及gc只保持有效数据 key、value分离 作者对于key、value分离策略的观察主要来自于排序是以往LSM性能消耗最大的地方&#xff0c;但是真正影响排序的与占用大储存…