vue3仿美团项目(6)-生成订单及地址编辑

该文详细描述了一个Vue.js应用中生成订单和地址管理的功能实现过程,包括点击结算跳转至订单页面、计算总价格、管理用户地址、编辑和新增地址的步骤。同时,文章提供了相关组件的代码示例,如CreateOrder.vue、MyOrder.vue、AddressEdit.vue等,展示了如何使用Vuex管理和传递数据,以及利用VueRouter进行页面跳转。
摘要由CSDN通过智能技术生成

一、主要实现的功能

1.点击结算,出现生成订单页面;

2.点击生成订单按钮,跳转到订单页面;

3.点击地址导航栏,进行地址管理;

4.可以进行地址编辑和新增地址;

二、生成订单步骤

    1.新建生成订单这个组件,路由配置,在购物车页面中点击结算测试能否跳转路由

    2.页面展示的数据,通过vuex传入 订单列表数组

    3.计算总价格(问题:在控制台能计算出总价格,但是在页面不展示总价格)

    4.初始化用户信息,找到购物车CartDetails.vue组件,路由中需要传递选中商品的数据

    5.订单生成成功后跳转到我的订单界面,订单数据也需要在此页面展示,需要在vuex添加一个已经完成后订单的数组(生成订单应该在vuex管理,并且是追加的)

    6.生成成功有弹窗提示,在购物车组件点击结算按钮跳转到订单页面时将需要进行结算的商品传过去;

    7.生成订单之后,跳转到订单页面,并且把购物车中的内容给过滤一遍(留下没有生成订单的数据)

三、地址编辑步骤

1.地址管理

    1.配置路由

    2.从vant中引入,搭建页面

    3.跳转路由到地址编辑

    4.修改路由传递参数(携带数据),用来判断是编辑地址还是新增地址

2.地址编辑或添加

   1.从vant中引入搭建页面

    2.判断一下是编辑地址还是新增地址

    3.保存和删除方法实现

    4.在vuex中统一创建地址增加、编辑、删除方法

四、完整代码

1.createOrder->CreateOrder.vue

<template>
  <div class="create_order">
    <Header title="生成订单" />

    <van-contact-card
      type="edit"
      :tel="currentContact.tel"
      :name="currentContact.name"
      @click="onEdit"
    />
    <div class="content">
      <div v-for="(item, index) in store.state.orderList" :key="index">
        <van-card
          :num="item.num"
          :price="item.price"
          :title="item.title"
          :thumb="item.pic"
        />
      </div>
    </div>
    <van-submit-bar
      :price="initPrice() * 100"
      button-text="生成订单"
      @submit="onSubmit"
      button-color="#ffc400"
    />

    <Footer />
  </div>
</template>
<script>
import { defineComponent, reactive, toRefs, onMounted } from "vue";
import Header from "../../components/Header.vue";
import Footer from "../../components/Footer.vue";
import { useRouter, useRoute } from "vue-router";
import { useStore } from "vuex";
import { Dialog } from "vant";
export default defineComponent({
  name: "App",
  components: { Header, Footer },
  setup() {
    const store = useStore();
    const router = useRouter();
    const route = useRoute();
    const data = reactive({
      currentContact: {
        name: "Mike",
        tel: 12345678896,
      },
      //   initPrice: 0,
    });
    // 初始化用户数据
    const initUser = () => {
      store.state.userAddress.forEach((item) => {
        if (item.isDefault) {
          data.currentContact.name = item.name;
          data.currentContact.tel = item.tel;
        }
      });
    };
    // 地址编辑
    const onEdit = () => {
      router.push("/address");
    };
    const initPrice = () => {
      let price = 0;
      if (store.state.orderList.length) {
        store.state.orderList.forEach((item) => {
          return (price += item.price * item.num);
        });
      }
      //   data.initPrice = price;
      return price;
    };
    onMounted(() => {
      initPrice();
      initUser();
    });
    // console.log("initPrice",data.initPrice);
    // console.log("initPrice", initPrice());
    // console.log("store", store.state.orderList);
    // 生成订单
    const onSubmit = () => {
      Dialog.alert({
        title: "提示",
        message: "恭喜您的订单已生成!",
      }).then(() => {
        // 在购物车中的数据清除
        // newList中存储的是为生成订单的数据
        let newList = store.state.cartList.filter((item) => {
          return !route.query.list.includes(item.id + "");
        });
        // 告诉vuex更新一下数据
        store.commit("DELETE", newList);
        store.commit("UPDATEORDER");
        router.push("/order");
      });
    };

    return {
      ...toRefs(data),
      onEdit,
      store,
      onSubmit,
      initPrice,
      router,
      route,
    };
  },
});
</script>
<style lang="less" scoped>
.create_order {
  flex: 1;
  position: relative;
  overflow-y: auto;
  height: 100%;
  display: flex;
  flex-flow: column;
  .content {
    flex: 1;
    overflow-y: auto;
  }
}
.van-submit-bar {
  position: fixed;
  bottom: 52px;
  border-radius: 20px;
  //   font-size: 20px;
}

</style>

2.myOrder->MyOrder.vue

<template>
  <div class="order">
    <Header title="订单" />
    <div class="content">
      <van-tabs color="#ffc400">
        <van-tab v-for="(item, index) in navData" :key="index" :title="item">
          <div
            v-for="(i, ind) in store.state.orderListed"
            :key="ind"
            v-if="item == '全部' && store.state.orderListed.length"
          >
            <van-card
              :num="i.num"
              :price="i.price"
              :title="i.title"
              :thumb="i.pic"
            />
          </div>
          <Blank v-else />
        </van-tab>
      </van-tabs>
    </div>
    <Footer />
  </div>
</template>
<script>
import { defineComponent, reactive, toRefs } from "vue";
import Footer from "../../components/Footer.vue";
import Header from "../../components/Header.vue";
import Blank from "../../components/Blank.vue";
import { useStore } from "vuex";
export default defineComponent({
  name: "App",
  components: { Footer, Header, Blank },
  setup() {
    const store = useStore();
    let data = reactive({
      navData: ["全部", "已完成交易", "待付款", "待发货", "已发货"],
    });
    // console.log();
    return {
      ...toRefs(data),
      store,
    };
  },
});
</script>
<style lang="less" scoped>
.order {
  display: flex;
  flex-flow: column;
  height: 100%;
  .content {
    flex: 1;
    overflow-y: auto;
  }
}
</style>

3.addressEdit->AddressEdit.vue

<template>
  <div class="address_edit">
    <Header :title="addTitle" />
    <van-address-edit
      :area-list="areaList"
      :address-info="addressInfo"
      show-delete
      show-set-default
      :area-columns-placeholder="['请选择', '请选择', '请选择']"
      @save="onSave"
      @delete="onDelete"
    />
  </div>
</template>
<script>
import { defineComponent, reactive, toRefs, computed, onMounted } from "vue";
import { useRouter, useRoute } from "vue-router";
import { useStore } from "vuex";
import { Toast } from "vant";
import Header from "../../components/Header.vue";
export default defineComponent({
  name: "App",
  components: { Header },
  setup() {
    let store = useStore();
    let router = useRouter();
    let route = useRoute();
    let data = reactive({
      areaList: {
        // 110000:省,加100:市,加1:区
        province_list: {
          110000: "黑龙江省",
          120000: "辽宁省",
        },
        city_list: {
          110100: "哈尔滨市",
          110200: "大庆市",
          120100: "沈阳市",
          120200: "大连市",
        },
        county_list: {
          110101: "南岗区",
          110102: "香坊区",
          120102: "铁西区",
          120202: "旅顺口区",
        },
      },
      addressInfo: {}, //地址初始化
    });
    const addTitle = computed(() => {
      return route.query.type == "add" ? "添加地址" : "编辑地址";
    });
    const init = () => {
      store.state.userAddress.forEach((item) => {
        if (item.id == Number(route.query.id)) {
          data.addressInfo = item;
        }
      });
    };
    onMounted(() => {
      init();
      //   console.log("编辑中的地址addressInfo", data.addressInfo);
    });
    const onSave = (content) => {
      if (route.query.type == "add") {
        // 添加id方法一
        if (store.state.userAddress.length) {
          content.id =
            Number(
              store.state.userAddress[store.state.userAddress.length - 1].id
            ) + 1;

          //添加id方法二
          // content.id =
          //   store.state.userAddress[0].id+
          //   store.state.userAddress.length;
          // store.commit("ADDADDRESS", content);
        } else {
          content.id = 1001;
        }
        Toast("恭喜,地址保存成功!");
      } else {
        store.commit("CHANGEADDRESS", content);
        Toast("恭喜,地址修改成功!");
      }
      setTimeout(() => {
        router.back();
      }, 1000);
    };
    const onDelete = (content) => {
      store.commit("DELETEADDRESS", content);
      Toast("地址信息已成功删除!");
      setTimeout(() => {
        router.back();
      }, 1000);
    };
    return {
      ...toRefs(data),
      onSave,
      onDelete,
      addTitle,
    };
  },
});
</script>
<style lang="less" scoped>
/deep/ .van-switch--on {
  background-color: #ffc400;
}
/deep/.van-button--danger {
  background-color: #ffc400;
  border-color: #ffc400;
}
</style>

 4.address->Address.vue

<template>
  <div class="address">
    <Header title="地址管理" />
    <van-address-list
      :list="list"
      default-tag-text="默认"
      @add="onAdd"
      @edit="onEdit"
    />
  </div>
</template>
<script>
import { defineComponent, reactive, toRefs, onMounted } from "vue";
import { useStore } from "vuex";
import Header from "../../components/Header.vue";
import { useRouter} from "vue-router";
export default defineComponent({
  name: "App",
  components: { Header },
  setup() {
    let store = useStore();
    let router = useRouter();
    let data = reactive({
      list: [],
    });
    const init = () => {
      data.list = store.state.userAddress.map((item) => {
        return {
          id: item.id,
          name: item.name,
          tel: item.tel,
          address: `${item.province}${item.city}${item.county}${item.addressDetail}`,
          isDefault: !!item.isDefault, // !!表示强制转换为布尔类型
        };
      });
    };
    onMounted(() => {
      init();
    });
    const onAdd = () => {
      //   router.push("/addressEdit");
      router.push({
        path: "/addressEdit",
        query: {
          type: "add",
        },
      });
    };
    const onEdit = (item) => {
      //   router.push("/addressEdit");
      router.push({
        path: "/addressEdit",
        query: {
          type: "change",
          id:item.id
        },
      });
    };
    return {
      ...toRefs(data),
      onAdd,
      onEdit,
    };
  },
});
</script>
<style lang="less" scoped>
/deep/.van-radio__icon {
  display: none;
}
.van-tag {
  color: #ffc400;
}
/deep/.van-button--danger {
  background-color: #ffc400;
  border-color: #ffc400;
}
</style>

5.router->index.js

import { createRouter, createWebHashHistory } from "vue-router"

const router = createRouter({
    history: createWebHashHistory(),
    routes: [
        {
            path: "/",
            component: () => import("../pages/myHome/MyHome.vue")
        },
        {
            path: "/home",
            component: () => import("../pages/myHome/MyHome.vue")
        },
        {
            path: "/mine",
            component: () => import("../pages/mine/Mine.vue"),
            meta: {
                isAuth: true
            }
        },
        {
            path: "/cart",
            component: () => import("../pages/myCart/MyCart.vue"),
            meta: {
                isAuth: true
            }
        },
        {
            path: "/order",
            component: () => import("../pages/myOrder/MyOrder.vue"),
            meta: {
                isAuth: true
            }
        },
        {
            path: "/store",
            component: () => import("../pages/store/MyStore.vue")
        },
        {
            path: "/createOrder",
            component: () => import("../pages/createOrder/CreateOrder.vue"),
            meta: {
                isAuth: true
            }
        },
        {
            path: "/address",
            component: () => import("../pages/address/Address.vue"),
            meta: {
                isAuth: true
            }
        },
        {
            path: "/addressEdit",
            component: () => import("../pages/addressEdit/AddressEdit.vue"),
            meta: {
                isAuth: true
            }
        },
        {
            path: "/login",
            component: () => import("../pages/login/Login.vue")
        },
        {
            path: "/regist",
            component: () => import("../pages/regist/Regist.vue")
        }


    ]
})

export default router

6.store->index.js

import { createStore } from "vuex";
export default createStore({
    state: {
        cartList: [],// 购物车列表
        orderList: [],//结算列表
        orderListed: [],//已完成订单
        edit: true,  // 默认编辑状态
        // 用户地址数据
        userAddress: [
            {
                id: 1001,
                name: '小明',
                tel: '13123456731',
                province: '黑龙江省',
                city: '哈尔滨市',
                county: '南岗区',
                addressDetail: 'asd',
                isDefault: true,
                areaCode: '110101',
            },
            {
                id: 1002,
                name: '张三',
                tel: '13123456731',
                province: '黑龙江省',
                city: '哈尔滨市',
                county: '香坊区',
                addressDetail: 'asd',
                isDefault: false,
                areaCode: '110101',
            },
        ],

    },
    // 处理数据的逻辑方法
    mutations: {
        ADDCART(state, value) {
            state.cartList = value
        },
        PAY(state, value) {
            state.orderList = value
        },
        DELETE(state, value) {
            state.cartList = value
        },
        EDIT(state, value) {
            if (value == "delete") {
                state.edit = true
            } else {
                state.edit = !state.edit
            }
        },
        //生成订单,追加
        UPDATEORDER(state) {
            state.orderListed = state.orderListed.concat(state.orderList)
        },
        // 添加地址
        ADDADDRESS(state, value) {
            state.userAddress.map(item => {
                // 判断一下是否是默认的,
                if (value.isDefault) {
                    item.isDefault = false
                }
            })
            state.userAddress.push(value)
        },
        // 编辑地址
        CHANGEADDRESS(state, value) {
            state.userAddress = state.userAddress.map(item => {
                // 如果编辑的是默认地址,需要循环遍历将所有的设置为false
                if (value.isDefault) {
                    item.isDefault = false
                }
                return item.id === value.id ? value : item
            })
        },
        // 删除地址
        DELETEADDRESS(state, value) {
            // 将删除之后剩余的数据过滤出来
            state.userAddress = state.userAddress.filter(item => {
                return !(value.id === item.id)
            })
            // 删除的是默认地址并且删除完之后还有别的地址,则第一条为默认的
            if (value.isDefault && state.userAddress.length) {
                // 并没有走到这里
                console.log("11111");
                state.userAddress[0].isDefault = true
            }
        }

    },
    actions: {

    }
})

 五、上传git

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值