vue+vue-router+vuex地址管理思路

栏目: JavaScript · 发布时间: 6年前

内容简介:如何精简页面目录,在实现功能要求的同时,提高页面可维护性成为前端发展趋势。收货地址管理是电商交易必不可少模块,本篇我将通过实现地址管理的部分功能分享下构建思路。本篇会涉及到:es6、vuejs、vue-router、vuex基础知识,在讲解思路过程中,我会穿插说明,但是还是希望读者对相关知识有些了解。

一、场景描述

如何精简页面目录,在实现功能要求的同时,提高页面可维护性成为前端发展趋势。收货地址管理是电商交易必不可少模块,本篇我将通过实现地址管理的部分功能分享下构建思路。

本篇会涉及到:es6、vuejs、vue-router、vuex基础知识,在讲解思路过程中,我会穿插说明,但是还是希望读者对相关知识有些了解。

实现功能:

1、个人中心与订单确认页均可以进入地址列表页; 
2、个人中心进入地址列表页,点击地址列表中地址进入地址编辑页,并带出地址相关信息; 
3、订单确认页进入地址列页,点击地址列表中地址,选中地址并返回到订单确认页,并带出选中地址信息; 

二、实现功能图解

vue+vue-router+vuex地址管理思路

三、解决该问题思路及代码

注:该篇思路分析项目Demo是使用vue-cli 3.x版本搭建。

1、Demo目录

  1. 在组件库中创建了appHeader.vue,用于头部的名称展示。
  2. “页面”库中新建了四个“页面”Home.vue(个人中心)、OrderConfirm.vue(订单确认)、AddressList.vue(地址列表)、AddressEdit.vue(地址编辑)。项目初始化时的“页面”About.vue删除。
  3. App.vue中路由链接改造,会在后边页面介绍中说明。
  4. 路由文件:Demo创建中,路由数量有限,且主要目的在功能实现,因此本次路由信息均放在了router.js文件中。
  5. 状态管理器:同路由文件类似,我们将状态、方法均放在store.js文件中。

vue+vue-router+vuex地址管理思路

2、路由匹配

在router.js文件中匹配好所有的路由信息,将本次Demo演示的四个页面的路由信息均匹配好。

import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'
import OrderConfirm from './views/OrderConfirm.vue'
import AddressList from './views/AddressList.vue'
import AddressEdit from './views/AddressEdit.vue'

Vue.use(Router)

export default new Router({
    routes: [{
            path: '/',
            name: 'home',
            component: Home
        },
        {
            path: '/orderConfirm',
            name: 'orderConfirm',
            component: OrderConfirm
        },
        {
            path: '/addressList',
            name: 'addressList',
            component: AddressList
        },
        {
            path: '/addressEdit',
            name: 'addressEdit',
            component: AddressEdit
        }
    ]
})复制代码

3、“页面”创建及对应路由与状态管理说明

App.vue:初始化时的页面,系统入口。此处做了点修改:template内容中路由链接信息。

<template>
    <div id="app">
        <div id="nav">
            <router-link to="/">Home</router-link> ||
            <router-link to="/orderConfirm">OrderConfirm</router-link>
        </div>
        <router-view />
    </div>
</template>复制代码

Home.vue:个人中心页,作为编辑地址列表的入口。

<template>
    <div class="home">
        <router-link to='/addressList'>管理地址</router-link>
    </div>
</template>
<style scoped>
a {
    text-decoration: none;
    color: black;
}
</style>复制代码

说明:

  • Home页面在本次项目Demo就是一个链接跳转的路径,仅仅使用了我们在 router.js 中设置的地址列表路由 /addressList

store.js:状态管理文件,为方便下边“页面”说明,提前将文件内容贴出来,后续涉及到时会进行简要说明。

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
    state: {
        addressList: [{
                id: 1,
                username: "小明",
                phone: '15612345678',
                addressDetail: "某某省 某某市 某某区 110"
            },
            {
                id: 2,
                username: "小红",
                phone: '13812345678',
                addressDetail: "某某省 某某市 某某区 110"
            },
            {
                id: 3,
                username: "小花",
                phone: '18612345678',
                addressDetail: "某某省 某某市 某某区 110"
            }
        ]
    },
    getters: {
        getAddress: (state, getters) => (id) => {
            return state.addressList.find(address => address.id === id)
        }
    },
    mutations: {
        addAddress(state, address) {
            return state.addressList.push(address)
        }
    }
})复制代码

OrderConfirm.vue:订单确认页,是选择收货地址入口,正是由于存在跟Home两个入口, AddressList.vue 中地址列表对于地址进行同一个操作,存在不同的反馈。

<template>
    <div>
        <router-link to='/addressList'>
            <div v-if='isAddress' class="address">
                <div><span>姓名:{{username}}</span></div>
                <div><span>电话:{{phone}}</span></div>
                <div><span>地址:{{addressDetail}}</span></div>
            </div>
            <div v-else>
                <span>选择地址</span>
            </div>
        </router-link>
    </div>
</template>
<script>
export default {
    name: "orderConfirm",
    data() {
        return {
            isAddress: false,
            username: "",
            phone: "",
            addressDetail: ""
        }
    },
    created() {
        if (this.$route.query.id) {
            let userAddress = this.$store.getters.getAddress(this.$route.query.id)
            this.isAddress = true
            this.username = userAddress.username;
            this.phone = userAddress.phone;
            this.addressDetail = userAddress.addressDetail;
        }
    }
}
</script>
<style>
a {
    text-decoration: none;
    color: black;
}

.address {
    text-align: left;
    margin-left: 20PX;
}
</style>复制代码

说明:

  • 使用 isAddress 确认是否有地址,默认为 false 。当地址不存在时,显示为“选择地址”,当地址存在时,或者选择地址后,显示选中地址信息。
  • this.$route.query.id 是vue-router中 query 参数,该使用是组件中获取参数 query.id 方式,通过这个字段值去判断是否存在地址信息。如果存在显示地址信息,并设置 isAddresstrue ,如果不存在则显示为选择地址。
  • getters 是vuex中计算属性,类似于vue中的 computed ,我们可以通过getters获取vuex经过“计算”的数据。
  • 视角转向store.js文件, getters 中使用 es6 的箭头函数,通过输入值,获取state中经过“计算”的数据。
  • this.$store.getters.getAddress(this.$route.query.id) 是为获取vuex中传参的getters数据。在返回选中地址时,通过向 getters 传递 this.$route.query.id 获取选中的数据,将返回结果赋值到初始设置字段即可。

AddressList.vue:地址列表页。该页面需要通过判别路由后初始化页面。

<template>
    <div>
        <app-header headTitle="地址列表"></app-header>
        <ul>
            <li v-for="address in addressList" :key="address.id">
                <router-link :id='address.id' :to="{path:url,query:{id:address.id}}">
                    <div>
                        <div>
                            <span>姓名:{{address.username}}</span>
                        </div>
                        <div>
                            <span>电话:{{address.phone}}</span>
                        </div>
                        <div>
                            <span>地址:{{address.addressDetail}}</span>
                        </div>
                    </div>
                </router-link>
            </li>
        </ul>
        <div>
            <router-link to='/addressEdit'><button>新增地址</button></router-link>
        </div>
    </div>
</template>
<script>
import appHeader from '@/components/appHeader.vue'
import { mapState } from 'vuex'
export default {
    name: "addressList",
    components: {
        appHeader: appHeader,
    },
    data() {
        return {
            url: ""
        }
    },
    computed: {
        ...mapState(["addressList"])
    },
    beforeRouteEnter(to, from, next) {
        if (from.name == 'orderConfirm') {
            next(vm => {
                vm.url = "/orderConfirm"
            })
        } else {
            next(vm => {
                vm.url = "/addressEdit"
            })
        }

    }
}
</script>
<style scoped>
ul li {
    list-style: none;
    text-align: left;
    margin-bottom: 10px;
    padding: 20px;
}

ul li:nth-child(even) {
    background-color: lightgrey;
}

a {
    text-decoration: none;
    color: black;
}

button {
    outline: none;
    border: none;
    width: 100px;
    height: 40px;
    border-radius: 10px;
    background-color: green;
    color: white;
}
</style>复制代码

说明:

  • 页面初始化时,地址列表通过vuex辅助函数 mapState 获取state中地址列表数据,并通过 v-for 指令进行列表渲染。
  • 该页面进行初始渲染的关键是获取路由导航来源,通过组件内路由导航守卫 beforeRouteEnter 实现,因为无法获取组件实例 this ,因此在 next 方法中进行实例获取。
  • 动态绑定 url ,可根据路由导航来源决定导航跳转去向,另外在 url 中动态绑定 query 参数。
  • 在跳转过程中,带着 query.id 参数,即在本次Demo中很多‘页面’中均存在 this.$route.query.id 验证。
  • 另外,本页中使用了组件 app-header ,对于页面头进行简单设计。
  • 最后,在页面底部添加了一个新增地址按钮,是为在演示如何在一个页面实现新增与修改地址功能。

appHeader.vue:头部样式组件,用在了地址列表页面和地址编辑页面。

<template>
    <div class='header'>
        <span>{{headTitle}}</span>
    </div>
</template>
<script>
export default {
    name: "appHeader",
    props: ['headTitle'],
}
</script>
<style>
.header {
    width: 100%;
    height: 60px;
    text-align: center;
    color: white;
    background-color: lightblue;
    font-size: 20px;
    line-height: 60px;
}
</style>复制代码

说明:

  • 这个组件没有太多难点,仅仅涉及到 props 的使用。

AddressEdit.vue:地址编辑页面。

<template>
    <div>
        <appHeader :headTitle="addressEdit"></appHeader>
        <div class='name'>
            <span>姓名:</span><input type="text" v-model='username'>
        </div>
        <div class='phone'>
            <span>电话:</span><input type="text" v-model='phone'>
        </div>
        <div class='addressDetail'>
            <span>地址:</span><input type="text" v-model='addressDetail'>
        </div>
        <router-link to='/addressList'><button @click='editAddress'>提交</button></router-link>
    </div>
</template>
<script>
import appHeader from '@/components/appHeader.vue'
import { mapGetters } from 'vuex'
export default {
    name: "addressEdit",
    data() {
        return {
            addressEdit: "",
            username: '',
            phone: '',
            addressDetail: ''
        }
    },
    components: {
        appHeader: appHeader
    },
    computed: {
        useraddress() {
            return this.$store.getters.getAddress(this.$route.query.id)
        }
    },
    methods: {
        editAddress() {
            let length = this.$store.state.addressList.length
            let address = {}
            address.id = length + 1
            address.username = this.username
            address.phone = this.phone
            address.addressDetail = this.addressDetail
            this.$store.commit("addAddress", address)
        }
    },
    created() {
        this.$route.query.id ? this.addressEdit = '编辑地址' : this.addressEdit = '新增地址';
        if (this.$route.query.id) {
            let userAddress = this.$store.getters.getAddress(this.$route.query.id)
            this.username = userAddress.username || '';
            this.phone = userAddress.phone || '';
            this.addressDetail = userAddress.addressDetail || '';
        }

    }

}
</script>
<style>
input {
    border: 1px solid lightblue;
    outline: none;
    width: 300px;
    height: 30px;
    border-radius: 5px;
}

.name {
    margin-top: 10px;
}

.phone {
    margin: 10px 0;
}

button {
    margin-top: 20px;
    outline: none;
    border: none;
    width: 100px;
    height: 40px;
    border-radius: 10px;
    background-color: green;
    color: white;
}
</style>复制代码

说明:

  • 头部组件 app-headerprops 动态赋值,点击新增地址按钮,进入地址编辑页,页面头部展示“新增地址”,点击地址列表中地址,进入地址编辑页,页面头部展示为“编辑地址”。
  • 地址修改时,对于输入框内容根据 this.$route.query.id 从vuex中 getters 赋值并展示。
  • mutations 方法类似vue中 methods
  • 信息填写完毕后,通过 mutations 方法向vuex中state中值进行修改。在组件中methods中通过 this.$store.commit("addAddress", address) 提交到mutations。
  • 注意 在本次的Demo展示中,我针对地址修改与新增,均向state中地址列表中新增地址,另外,我们不同入口进行地址列表页面时,新增地址提交返回路径地址也应该不一样, 有兴趣的同学们可以尝试修改的方法。 鉴于是个本地展示,本次展示数据修使用的mutations,真正与后台交互中,建议使用 actions .

四、写在后面

实际我们在做产品时,涉及到用户体验的东西很多,比如页面样式、默认地址、输入验证、验证提示、地址级联选择等等,作为一个功能实现,暂不予考虑。

以上是作为一名喜欢前端技术的产品经理实现该功能的思路及方法,相信大神们会有更简洁便利的方式。

最后,针对文中有不对的地方,或者可以再优化的点,请多多指教。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

RESTful Web Services Cookbook

RESTful Web Services Cookbook

Subbu Allamaraju / Yahoo Press / 2010-3-11 / USD 39.99

While the REST design philosophy has captured the imagination of web and enterprise developers alike, using this approach to develop real web services is no picnic. This cookbook includes more than 10......一起来看看 《RESTful Web Services Cookbook》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

SHA 加密
SHA 加密

SHA 加密工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具