2018.3.1更:
有赞·微商城(base杭州)部门招前端啦,最近的前端hc有十多个,跪求大佬扔简历,我直接进行内推实时反馈进度,有兴趣的邮件 lvdada#youzan.com,或直接微信勾搭我 wsldd225 了解跟多html
有赞开源组件库·zanUI前端
初次接触vue,刷完了堪称经典的vue官网文档+vue-router文档+vuex文档+vue-cli文档,而后就开始刷项目了。这篇文章总结了项目实践的一些思路。
首先看下项目的总览图(mockplus制做)vue
这个项目我负责的部分是一个控制台的需求,用户能够在这个模块进行佣金、订单等项目的修改设置,能够看到第1张图至关于控制台首页,页面上有一、二、三、四、5个入口,其中1-4入口进入的页面对应4个页面,可是4个页面主要结构相同,中间商品列表样式信息不一样,为了简略4图归为第二张图。入口5对应第三张图。vue-router
这几个页面需求并不复杂,大项目自己也是是基于zepto的,单单把这个模块拿出来抽离成单页形式主要为了两点考虑:vuex
基于以上两点使用vue以及vue大礼包编写了这个单页模块。vue-cli
由入口而知一共有6个页面(包含控制台首页),虽然是单页模块,也是必需要符合经过url地址直接进入对应分页的需求。在切换的过程当中,留下url路由信息也方便用户进行后退操做。json
首先是顶级路由的配置,六个页面(组件)分别设置六个顶级路由。api
// 在App.vue文件中设置<router-view> <template> <div id="app"> <router-view keep-alive :style="{'padding-bottom': paddingBottom + 'rem'}"></router-view> </div> </template>
// 在main.js中配置路由 router.map({ '/': { component: Index, name: 'index' }, '/commission': { name: 'commission', component: Commission }, '/order': { name: 'order', component: Order }, '/inventory': { name: 'inventory', component: Inventory }, '/shop': { name: 'shopList', component: ShopList }, '/qcode': { name: 'qcode', component: Qcode } })
由上图具体的佣金页面(组件)能够看到,这个页面有两个主要操做,一:搜索,根据搜索结果展现商品条目;二:翻页,根据页数展现商品条目。数组
原始的思路是搜索与翻页都在当前页面(组件)操做,将异步获取的数据替换当前页面的items数组。Vue会将变化的数据与view绑定,同步刷新view页面。微信
这样作有个缺陷,任何操做(搜索、翻页)都不会留下可追溯的路径,假设有个场景:
用户翻n页,发现了一款商品点击进入详情页(外链,属于大项目中的页面),用户返回佣金设置页面时发现又从第一页开始浏览了。
基于此类场景结合vue-router的路由查询参数功能能够换一种实现方式。
点击搜索再也不在当前页面(组件)异步请求数据,而是经过$route对象进行路由跳转。
this.$route.router.go({ name: 'index', query: { keyWord: 'searchWorld', page: 1 } })
根据上图,搜索n次,或者是点击翻页n次,都会改变当前的url的查询参数。实际上改变路由查询参数,就至关于从新进入一次当前页面(组件),Vue会识别计算是否重用当前组件,这种状况<router-view>并不会产生切换效果,由于即便查询参数变化,当前页面组件始终都是component: Commission
同一个组件。
这样设计就留下了一系列的路径,可供历史回退。
那么数据该如何获取呢?
vue-router
有一个「切换控制流水线」的概念,即在不一样路由切换的过程当中会有不一样的钩子函数能够调用。
其中data
钩子函数无论组件是否能够重用,在每次路由切换的时候都会触发。
route: { data (transition) { this.$http.get('/api/test/test', { params: { keyword: this.keyWord, page: this.currentPage, pageSize: this.numberPerPage } }).then((response) => { transition.next({ items: response.json().data.item.items, listNumber: response.json().data.item.totalNum }) }, (response) => { // error }) } },
这样实现了数据的获取,参数部分依靠当前组件的$route
对象获取。
上文已经提到的6大分页其实就是6个组件,可是为了在开发环境下区分资源,将这6个组件放在了views文件下内。
| |-src | | | |-components | |-views | | |-Index.vue | | |-Commission.vue | | |-Order.vue | | |-...
由上图可知能够将1.title 2.搜索栏 3.confirm 4.toast 5.分页器 6.loading等待封装成全局组件。在main.js
中进行注册。
import Toast from './components/common/Toast' Vue.component('c-toast', Toast); ... ...
商品列表也能够抽离成组件,可是在每一个分页里的商品列表是不一样的,因此每一个分页里的商品列表都独立抽离成组件,并注册在对应的分页组件里。
import ListCommission from '../components/ListCommission' export default { name: 'commission', components: { ListCommission } }
控制台这个模块状态并不复杂,多数状态的传递都只发生在父组件和子组件这种上下层级的关系之间。
好比Commission组件(佣金分页)中的ListCommission组件(佣金页的商品列表组件)之间的状态传递就只发生在这两级之间。
// Commission.vue <template> <list-commission :visible="listNumber > 0" v-if="!$loadingRouteData" :items="items"></list-commission> </template>
其中items
状态属于父组件,会传递到ListCommission
组件内供其view展现。这种状态称为「组件本地状态」,组件自己管理本身的状态。
可是如今有这么一个功能点,生成二维码模块须要使用一个完整url路径,这个路径须要根据测试、线上环境的不一样对应.net/.com
。这个状态也许还有许多不一样层级的组件须要使用,那么这样的状态就适合用vuex去管理。
1.首先在store中定义状态初始值
const state = { suffix: '.net' }
2.在根组件App.vue中触发action
let suffix = window.location.hostname.indexOf('showjoy.net') > -1 ? '.net' : '.com'; export const setGlobalSuffix = function ({dispatch}, suffix) { dispatch('SET_GLOBAL_SUFFIX', suffix); } this.setGlobalSuffix(suffix);
3.触发dispatch
SET_GLOBAL_SUFFIX (state, suffix) { state.suffix = suffix; }
4.get状态
export function getSuffix (state) { return state.suffix; }
只要在相应组件中定义了getSuffix的getters,就能够在相应的组件中调用这个函数,获取suffix状态。此时suffix状态可称为「应用层级状态」。应用层级状态不属于任何特定的组件,但每一个组件均可以监视其变化并响应式的更新DOM。
suffix
状态只是一个简单的例子,像上图所示,当同级组件之间或者是不一样直系关系的父子组件之间须要进行状态的变动,依赖「组件本地状态」将难以维护。
好比Commission组件
须要改变Order组件
的一个状态,若是不借助vuex,那么须要显示的编写事件将状态分发到上层组件App,Order组件须要监听这个事件。状态变动一多,那维护将是噩梦。
对我以上的理解有疑问和意见的欢迎找我私聊~微博-写前端的暹罗