VUE VUEX VUE-ROUTE学习项目

Vue 2.0已经正式发布好长时间了。想找一个Vue.js Vuex vue-route的学习项目来练手。做个电商App吧,上gitHub搜索了一下搜到一大堆,不过基本上都不是使用单文件组件开发的,更不用说基于Vue.js全家桶了。本项目不一样的地方在于使用vue-cli + webpack template人开发模式,还要求Web和移动端一体化,也就是响应式Web,而且不能Mock数据,额外需要有一个提供restful web api的后端应用。哈哈,就是搞全栈呀。

一、后端服务

采用的是Express + mLab + Mongoose的技术栈。http模块加上Express自带路由利用中间件思想可以很方便地基于Node开发提供restful web api的Web应用。考虑到方便在线演示部署,数据库选用了MongoDB的云服务mLab。当然,提交数据到数据库时一般要选用便捷操作的对象模型工具(ORM)。在node.js和MongoDB数据库环境下,Mongoose作为就是不二之选了。具体实现请看https://github.com/szriafan/vue-shop-api。另外,我将node.js代码免费托管到了https://heroku.com/(主机数据库都免费,爽呀)。现在直接在浏览器访问https://vue-shop-api.herokuapp.com/v1/products就可以返回商品列表所需要的数据了,当然更好的选择是使用Postman之类的HTTP请求调试工具。如果我们不了解后端和mLab,只要在ations.js手动将axios的baseURL改为https://vue-shop-api.herokuapp.com/v1就可以了。或者对数据API足够了解,也可以不写Node.js应用的。为了方便大家全面学习测试,建议大家最好访问本地的restful应用。注意,访问不同端口的本地服务或不同域名的远程服务都有跨域问题,使用CORS可以很好解决这个问题。app.all('/*', function(req, res, next) {  res.header('Access-Control-Allow-Origin', '*');  res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');  res.header('Access-Control-Allow-Headers', 'Content-type,Accept,X-Access-Token,X-Key');  if (req.method == 'OPTIONS') {    res.status(200).end();  } else {    next();  }});好了,接下来集中精力开发前端。

二、前端

1. 运行vue-cli + webpack template就得到了一个Vue.js Vuex vue-route全家桶脚手架项目。我们要完成两个部分:前台展示和后台管理。

2. 前台展示有两个功能:展示商品列表和详情的功能、添加商品到购物车的功能。商品列表和详情页面都能添加商品到购物车,商品列表页只能通过点击按钮一次添加一件商品,但详情页面可以通过+-按钮或文本框输入来改变商品数量(不能大于库存),再通过点击添加按钮一次性添加多件商品。购物车列表页也可以可以通过+-按钮或文本框输入来改变商品数量,与详情页面操作不一样的是购物车列表页改变商品数量时会同步保存数据,即使重新刷新页面或关闭浏览器,都会显示已保存的数据。而但详情页面如果改变数量后没有按添加按钮就不会添加商品到购物车。

3. 后台管理有的功能就是实现商品及品牌的CRUD操作。在新增修改商品时,会通过下拉框选择品牌,而下拉框用品牌数据来填充的。因此商品数据是依赖品牌数据的,因此后台管理时先应该添加商品数据。

4. 明确了上述需求后,先看到一下最终效果吧。

5. 我们来说一说具体实现。SPA一般都有路由,复杂Vue.js应用页面之间的导航都要用到vue-route。vue-rout使用JavaScript动态初始化配置全局对象,将组件(components)映射到路由(routes),然后告诉vue-router在哪里渲染它们。通过注入路由器,我们还可以在任何组件内通过this.$router访问路由器,也可以通过 this.$route访问当前路由。比如说当添加或修改商品成功后我们就是通过this.$router回到商品列表页的。模板中的组件让用户在具有路由功能的应用中(点击)导航,其中to表示目标路由的链接,这个值可以是一个字符串或者是描述目标位置的对象,对应路由配置对象的path属性值或name对象。比如说App模板中的组件to属性设置为{name: 'Home'},通过路由映射会导航到Home组件所在的页面。建议设置to的属性值为name对象,因为这个对象一般很少改动,而首页链接设置成'/',同样是因为这个值很少改动。另外首页链接还得添加exact属性来精确匹配链接,大家都知道,其它path值肯定包含/,不设置该属性会造成导航链接样式都添加激活链接类名。

6. 如下面的文件路径树所示,本项目使用了大量的嵌套单文件组件,下面的项目components和pages文件夹包含了大量的单文件组件。嵌套单文件组件提高了代码复用性,让分模块团队开发变得容易,这对于开发大型Vue.js应用尤为重要。不过Vue组件使用单向数据流向下进行组件数据通信,大量的会让代码难以维护,此时我们就应该考虑用Vuex来实现多个组件共享状态。

├─components

│ ├─cart

│ │ CartControl.vue

│ │ CartItem.vue

│ ├─common

│ │ Loading.vue

│ ├─manufacturer

│ │ ManufacturerForm.vue

│ └─product

│ AddToCartButton.vue

│ ProductDetails.vue

│ ProductForm.vue

│ ProductItem.vue

│ ProductList.vue

├─pages

│ │ Cart.vue

│ │ Details.vue

│ │ Home.vue

│ └─admin

│ │ Index.vue

│ ├─manufacturer

│ │ Edit.vue

│ │ Manufacturers.vue

│ │ New.vue

│ └─product

│ Edit.vue

│ New.vue

│ Products.vue

如下面的文件路径树所示,本项目Vuex代码集中store文件夹中。Vuex应用的核心store(仓库),包含应用中大部分的状态,如商品、品牌、购物车数组, 我们是在index.js中定义的; Action函数接受一个与store实例具有相同方法和属性的context对象,可以包含任意异步操作,如对后台数据访问商品和品牌数据的异步操作,我们是在action.js中定义的;Vuex中的Mutation非常类似于事件:每个Mutation都有一个字符串的事件类型 (type) 和一个回调函数(handler)。如对异步回调函数和添加商品到购物车时的同步函数,我们是在mutations.js中定义的;Vuex允许定义getter从store中的state中派生出一些状态(计算属性),如从商品和品牌数组状态中派生出根据id查询到的状态,我们是在getters.js中定义的;另外,我们的mutation-types.js中使用常量替代mutation事件类型以方便多人协作。在任意组件中访问store的计算属性时可使用mapStatemapGetters辅助函数,分发Action、Mutation时使用mapActionmapMutation辅助函数。它们本质是都是语法糖,将store中的state、getter映射到局部计算属性,或将mutations和actions映射到局部方法,从而避免使用this.$store的方式来访问相应的函数。当然,并不是所有情况下都能使用辅助函数,如created生命周期钩子函数中或条件语句中。请注意,使用Vuex并不意味着我们需要将所有的状态放入Vuex。如果有些状态严格属于单个组件,最好还是作为组件的局部状态。我们应该根据应用开发需要进行权衡和确定。如CartControl组件中的count状态和每个cart组件绑定不能单例化,因此不需要用放入Vuex来管理。

├─store

│ actions.js

│ getters.js

│ index.js

│ mutation-types.js

│ mutations.js

7. 如下面的文件路径树所示,本项目plugins文件夹中有两个插件。插件会为Vue.js添加全局功能,本质上就是封装更好,复用性更强的组件,Vuex和vue-route就是这样两个优秀的插件。如果我们想在任意组件中弹出模态框和信息提示、控制加载动画等,怎么办?每个组件都加一个布尔控制变量肯定导致代码冗余难以维护。用Vuex集中在根组件中处理也好不到哪里去,因为要写很多代码来判断事件类型。所以我们得自己开发插件,感兴趣的话可参考vue-dialog和vue-toast的代码自行开发一个Loading插件。那样就可以在任意组件中控制加载动画了。├─plugins

│ ├─vue-dialog

│ │ │ index.js

│ │ │ VueDialog.vue

│ │ └─themes

│ │ default.css

│ │ ios.css

│ └─vue-toast

│ │ index.js

│ └─components

│ Notification.vue

│ VueToast.vue

8. 当我们build好代码,在IE或手机自带的Android浏览器上运行时,发现添加商品到购物车的功能用不了。报错:Vuex requires a Promise polyfill in this browser,原来Vuex依赖Promise。如果浏览器并没有实现Promise,那么可以使用一个 polyfill的库,例如babel-polyfill。第一步: 安装npm install --save babel-polyfill第二步:在webpack.config.js文件中,将entry的代码改为如下:entry: {    app: ["babel-polyfill", "./src/main.js"] }或者将下列代码添加到使用Vuex之前的一个地方:import 'babel-polyfill'

三、有待实现和改进功能:

1. 登录注册模块

2. 会员模块

3. 支付模块

4. 列表搜索排序功能

5. 图片列表的懒加载

6. 轮播图效果

7. 加入购物车动画

8. 页面切换动画

Vue.js devtools是一个很好的测试Vue.js应用的工具,对Vuex也支持得很好,值得拥有。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342

推荐阅读更多精彩内容

  • 高中毕业后,我就很少写煽情的文字了,今天突然变得很感性,我很想他。我爱他。他知道,我也知道。我们之间的爱也许和其他...
    小叭_Xiaoba阅读 480评论 4 5
  • 欲话还休思已乱,华灯佳节夜微寒。相携漫漫影渐长,橘灯暖。 几为愁多翻自笑,道是不枉为少年。约得金榜题名后,迎春山。
    记忆围城阅读 331评论 1 6
  • 今天早晨,我来到了心园米罗,我上完了美术课就开始下来上了书法课了,我很喜欢,因为这是一年一次的比字大会,我很...
    卓卓2阅读 158评论 0 0