跟其他数字交易平台相比,VUEX这个平台有什么特色?

初学vue时曾在网上搜索vue的实战项目源码,无奈大部分都是简单的demo,对于深究vue没有太大的帮助,剩下的一些大部分都是像音乐播放器之类的展示型项目,交互没有预期那么复杂。但我们实际在工作中,经常会遇到有购物车的项目,这类项目因为涉及到money,所以对逻辑严谨度要求高,页面之间交互复杂,又会伴随着登陆、注册、用户信息等等,常常会让我们很头疼。既然还没人用vue写过这样的项目,那不如我来写,开源出来对能看到的人也会有帮助。
这种功能性的项目很实用但是往往也很枯燥,没有音乐播放器那么看起来绚丽,思来想去发现饿了么是一个不错的素材,一来它足够复杂,开放的外卖平台比一般的公司独有商店更加复杂。二来 见到那么多美食,大家也不会感觉到厌烦。
为啥是饿了么,而不是百度,美团?原因很简单,三个外卖大佬里,饿了么的色调和布局是最漂亮的,看起来最舒服。
此项目大大小小共 45 个页面,涉及注册、登陆、商品展示、购物车、下单等等,是一个完整的流程。一般公司即便是官网的单页面项目都没这么复杂,如果这个项目能驾驭的了,相信大部分公司的其他单页面应用也就不在话下,即便更复杂,也不会比这个高到哪里去。
因为利用业余时间来做,年前就开始写,又跨个年,周期有点长,项目从零布局到完成共用了2个多月的时间,目前项目已经完成,正在进行一些性能的优化,增加详细的注释。
另外,这个项目和慕课网视频的那个饿了么没有任何关系,慕课网的项目只有一个页面,我在看完vue的官方文档后直接写了这个项目,没有参照任何人的代码,请大家不要混为一谈。
注:此项目纯属个人瞎搞,正常下单请选择饿了么官方客户端。
源码地址:
vue2 + vuex + vue-router + webpack + ES6/7 + fetch + sass + flex + svg
注意:由于涉及大量的 ES6/7 等新属性,nodejs 必须是 6.0 以上版本 ,node 7 是测试版,有可能会出问题,建议使用 node 6 稳定版 ?
git clone https://github.com/bailicangdu/vue2-elm.git &
cd vue2-elm
npm install
npm run dev
访问 http://localhost:8088
npm run build
生成的elm文件夹放在服务器即可正常访问
本项目主要用于熟悉如何用 vue2 架构一个大型项目
如果对您有帮助,您可以点右上角 "Star" 支持一下 谢谢! ^_^
或者您可以 "follow" 一下,我会不断开源更多的有趣的项目
开发环境 macOS 10.12.3 Chrome 55
特别感谢辰妹子,在百忙之中抽出时间和我一起完成了这个项目,辛苦了?
如有问题请直接在 Issues 中提,或者您发现问题并有非常好的解决方案,欢迎 PR ?
推荐一个 react + redux 开源项目,对react感兴趣的朋友赶紧去看看。
另外一个 vue2 + vuex 的入门项目,比当前的项目简单很多,非常适合入门练习。
关于 demo 与 数据 的说明?
1、下载代码运行后,因为开启了反向代理,可以获取真实的官方数据,最终可以进行下单(真实的下单,而不是模拟,下单后可以在官方App中查看并付款,亲自试过,且成功付款点餐),但是为了安全起见,登陆的帐号为固定的帐号,以免泄露个人信息,不过照样可以点餐。
2、demo的数据为模拟的固定数据,只做为效果演示,因为反向代理必须在PC端运行代码才行。
(demo使用的是模拟数据,数据是固定的,只做为样式的演示,要获取真实的数据,请clone代码并运行);
(请用chrome手机模式预览)
移动端扫描下方二维码
[x] 定位功能 -- 完成
[x] 选择城市 -- 完成
[x] 搜索地址 -- 完成
[x] 展示所选地址附近商家列表 -- 完成
[x] 搜索美食,餐馆 -- 完成
[x] 根据距离、销量、评分、特色菜、配送方式等进行排序和筛选 -- 完成
[x] 餐馆食品列表页 -- 完成
[x] 购物车功能 -- 完成
[x] 店铺评价页面 -- 完成
[x] 单个食品详情页面 -- 完成
[x] 商家详情页 -- 完成
[x] 登陆、注册 -- 完成
[x] 修改密码 -- 完成
[x] 个人中心 -- 完成
[x] 发送短信、语音验证 -- 完成
[x] 下单功能 -- 完成 ????
[x] 订单列表 -- 完成
[x] 订单详情 -- 完成
[x] 下载App -- 完成
[x] 添加、删除、修改收货地址 -- 完成
[x] 帐户信息 -- 完成
[x] 服务中心 -- 完成
[x] 红包 -- 完成
[x] 上传头像 -- 完成
[x] 付款 -- 臣妾做不到啊~~
1、因为并不是elm官方,而且因为要开代理,必须在pc端打开,最多只能做到下单这一步,下单成功后可以在手机客户端查看并付款。
2、一般涉及到money的网页逻辑都比较复杂,尤其像饿了么这样一个开放的平台,商家和食品种类繁多,页面与页面之间交互复杂,在写到 购物车 和 下单 功能时众多的数据和逻辑一度让人很头疼,又没有设计和接口api文档,只能一步步摸索。
3、vue因其轻量级的框架在中小型项目中表现亮眼,在大型单页面应用中因为vuex的存在,表现依然出色,在处理复杂交互逻辑的时候,vuex的存在是不可或缺的。所以说利用 vue + vuex 完全可以去做大型的单页面项目。
4、项目写到现在,从 登陆注册到、首页、搜索、商家列表、购物车、下单、订单列表、个人中心 一个流程走完之后、不但对vue的理解更深一层,而且对以后掌控大型项目的时候也有非常多的帮助,做一个实际的项目才能对自己有很大的提升。
5、曾一度怀疑,花几个月的时间做这样一个项目到底有没有意义,本来只是想做一个小项目练练手,没想到后来越写越多,不过坚持下来后我相信一切都是值得的。
6、项目已经完成,共45个页面。
1、用node.js构建一个模拟外卖平台的后台系统。(已经开始制作)
2、利用 react-native 写出跨 Android 和 IOS 的原生APP版本。
3、如果时间来的及,会出一个pc端的网页版。
所以我的目的是构建一个横跨前后端,移动IOS、Android的完整生态圈。
。。。敬请期待
商铺列表页
商铺筛选页
餐馆食品列表与购物车
确认订单页
订单列表页
阅读(...) 评论() &高仿掘金,项目中整合 vue + nuxt + axios + vuex + vue-router (nuxt 自带 vuex 和 vue-router)
高仿掘金,项目中整合 vue + nuxt + axios + vuex + vue-router (nuxt 自带 vuex 和 vue-router),一个基于 Nuxt 的服务器端渲染 Demo
,现在我们来看下初始化好的项目目录
├── assets
css,图片等资源都在这
├── components
├── layouts
├── middleware
├── pages
├── static
├── pages
├── store
├── nuxt.config.js
nuxt 相关配置
├── package.json
├── README.md
接触过 vue 的小伙伴,看着这个目前可能会有点小疑问,为什么没有 router 路由相关的文件?莫慌,Nuxt 会帮你将 pages 下面的文件自动解析成路由。所以在接下来的开发中,记得别瞎在 pages 下面新增文件,pages 下面的每一个 vue 文件就是一个路由。
2、引入 axios
i. 安装依赖
npm i axios -S
ii. 封装 axios
为了项目之后更加方便的开发,我们有必要对 axios 进行一层封装,我们要时刻养成这样一种好习惯。
首先在根目录下面新建 service 目录,在其下面建立 config.js 和 index.js 两个文件,下面的代码仅供参考,如果你的项目还需要做额外的一些配置,可自行进行拓展
在 config.js 中写入:
import http from 'http'
import https from 'https'
export default {
// 自定义的请求头
headers: {
'Content-Type': 'application/x-www-form-charset=UTF-8'
'X-Requested-With': 'XMLHttpRequest'
// 超时设置
timeout: 10000,
// 跨域是否带Token
withCredentials: true,
// 响应的数据格式 json / blob /document /arraybuffer / text / stream
responseType: 'json',
// 用于node.js
httpAgent: new http.Agent({
keepAlive: true
httpsAgent: new https.Agent({
keepAlive: true
在 index.js 中写入:
import axios from 'axios'
import qs from 'qs'
import config from './config'
const service = axios.create(config)
// POST 传参序列化
service.interceptors.request.use(
config =& {
if (config.method === 'post') config.data = qs.stringify(config.data)
return config
error =& {
return Promise.reject(error)
// 返回结果处理
service.interceptors.response.use(
return res.data
error =& {
return Promise.reject(error)
export default {
// post 方法
post (url, data) {
console.log('post request url', url)
return service({
method: 'post',
params: data
// get 方法
get (url, data) {
console.log('get request url', url)
return service({
method: 'get',
params: data
// delete 方法
delete (url, data) {
console.log('delete request url', url)
return service({
methods: 'delete',
params: data
iii. 跨域处理
使用过 vue 的同学,肯定知道对于项目中的跨域,vue-cli 对 webpack 中的 proxy 选项进行了一层封装。它暴露出来的是一个叫 proxyTable 的选项,是对 webpack 中的 proxy 和其三方插件 http-proxy-middleware 的一个整合。
不幸的 Nuxt 中没有 proxyTable 这么一个配置项来进行跨域的配置。当然幸运的是,在 Nuxt 中你可以直接通过配置 http-proxy-middleware 来处理跨域。更幸运的是 Nuxt 官方提供了两个包来处理 axios 跨域问题。
首先,进行安装
npm i @nuxtjs/axios @nuxtjs/proxy -D
然后在 nuxt.config.js 文件里进行配置
modules: [
'@nuxtjs/axios'
proxy: true
target: 'xxx.target.com',
pathRewrite: { '^/api': '' }
这里需要注意,因为是服务器端渲染,我们得时刻明确当前地址是属于路由跳转还是属于 axios 请求。所以我们需要在 service/index.js 写入以下判断
// 判断是路由跳转还是 axios 请求
if (process.server) {
config.baseURL = `http://${process.env.HOST || 'localhost'}:${process.env.PORT || 3000}`
然后你就可以安心使用你的 axios 进行跨域请求了
3、管理 vuex
先看下我们 store 目录下需要的一些文件
├── actions.js
axios 请求相关
├── index.js
主入口文件
├── mutations.js
同步状态操作相关
├── state.js
初始状态相关
接下来我们以此看看每个文件的内容
i. actions.js
import request from '~/service'
const api = '/api'
export const banner = async (store, params) =& {
return await request.get(`${api}/v1/get_banner`, params)
ii. state.js
export default {
counter: 1,
isPhone: false
iii. mutations.js
export function INCREMENT (state) {
state.counter++
export function PCORPHONE (state, bool) {
state.isPhone = bool
iv. index.js
import Vue from 'vue'
import Vuex from 'vuex'
import state from './state'
import * as mutations from './mutations'
import * as actions from './actions'
Vue.use(Vuex)
const store = () =& new Vuex.Store({
mutations,
export default store
然后你就可以在页面中进行使用了
&template&
&div class="page"&
&button @click="handleClick"&{{ counter }}&/button&
&p&{{ banner.name }}&/p&
&/template&
import { mapState, mapMutations } from 'vuex'
export default {
async asyncData ({ store, error }) {
// 对 axios 进行批量处理
let [ res ] = await Promise.all([
store.dispatch('banner')
]).catch((e) =& {
error({ statusCode: 404, message: 'Post not found' })
banner: res.banner
computed: {
...mapState({
counter: state =& state.counter
methods: {
...mapMutations([
'INCREMENT'
handleClick () {
this.INCREMENT()
4、全局组件管理
Nuxt 的项目不比 vue 的项目,提供了主入口文件供我们对全局组件进行配置。但要做到这个点也比较简单,我们只需要按照 Nuxt 官网给出的规范来,将组件引入的相关配置写入到 plugins 目录下即可
比如,我需要引入三方组件库
,我们只需在 plugins 目录下新建一个 element-ui.js 文件,并写入
import Vue from 'vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)
然后在 nuxt.config.js 文件中引入
plugins: [
'~/plugins/element-ui'
最后你就可以在你的项目中使用 element-ui 组件库里面的组件了。
当然,你想配置自己本地的全局组件,也是一样的做法。先在 plugins 目录下新建一个 js 文件,然后引入你的文件,最后再在 nuxt.config.js 文件中引入即可。
5、全局样式管理
和组件管理同理,不同的就是,css 需要存放在 assets 目录下。比如,现在我需要有一个 main.css 文件对路由跳转进行动态切换。
首选,你得在 assets/main.css 中写入重置样式吧
.page-enter-active, .page-leave-active {
transition: opacity .2s;
.page-enter, .page-leave-active {
opacity: 0;
然后,你只要在 nuxt.config.js 进入引入即可
'~/assets/stylus/main.styl'
关于 Nuxt 更多的用法,我就不一一介绍了,详细请参考:
然后关于项目的具体开发,也是家常便饭了,这里我也不展开描述了。如果想了解的,可以去
自行查阅。有问题的话可以加老司机群
,然后在群里问我即可。
接下来的篇幅,我将讲一下项目部署的一些点
三、项目部署
到这一步的同学,你得先确保你拥有一个自己的服务器。如果没有的话,感觉去买一个,现在阿里云和腾讯云都在搞活动,巨便宜哦 ~
OK,文章继续。在进行部署讲解前,我们先看一下 Nuxt 提供的几个命令
启动一个热加载的 Web 服务器(开发模式)
nuxt build
利用 webpack 编译应用,压缩 JS 和 CSS 资源(发布用)
nuxt start
以生成模式启动一个 Web 服务器 (nuxt build 会先被执行)
nuxt generate
编译应用,并依据路由配置生成对应的 HTML 文件 (用于静态站点的部署)
1、静态化页面部署
我们从官网给出的文档可以看出,部署静态化页面需要用到的命令是 nuxt generate ,执行的时候会在根目录下面生成 dist 目录,里面的文件都是静态化页面需要的打包好的文件。
这里需要特别注意的一点是,如果你的项目中存在 axios 请求的话,记得在你本地开启一个本地服务哦 ~ 不然打包的时候执行到 axios 请求的时候会报错。因为前面我们通过使用 node 的 process 对运行环境进行了是跳转还是请求的判定,而打包进行请求的时候是不依赖 node 环境的
i. 使用 gh-pages
这里,我先假设小伙伴们都可以正常执行 nuxt generate 并生成对应的 dist 目录。
为了项目的并行开发,我们一般会在 .gitignore 文件里面将打包文件给忽略掉,但我们静态化页面的部署有需要用到 dist 目录下的所有打包文件。所以这里我们将使用
将打包文件发布到我们的 git 仓库
# 安装 gh-pages
npm i gh-pages -D
然后在 package.json 写入配置(当然你也可以新建文件执行发布)
"scripts": {
"deploy": "gh-pages -d dist"
执行 npm run deploy ,然后你的 dist 目录就会发到你们仓库的 gh-pages 分支了
ii. 开始部署
打包文件上传好之后,你需要做的第一件事就是连接好你的服务器。然后在 cd 到服务器根目录下面,在 data/www 目录下面将你的项目 git clone 下来。然后切换到 gh-pages 分支
接下来,开始配置你的 nginx (还没下载 nginx 的同学请自行解决)
# 端口,默认是 80
listen 81;
# 服务名(写域名或者 ip 地址都可以)
server_name 123.12.123.12;
# server 根目录
/data/www/nuxt-ssr-
# 主入口文件
# 反向代理
location /api/ {
proxy_pass https://xxx.target.com/;
然后重启 nginx
sudo service nginx restart
然后你就能在
访问到你部署好的静态化页面了
2、服务器端渲染部署
看到上面静态化页面部署,详细有同学会问。进行静态化页面部署,岂不是没有了服务器端渲染的优势了。
对的,如果你的项目只是静态页面的话,做静态化部署是完全 OJBK 的。但如果牵扯到请求,还是乖乖的进行服务器端的部署吧 ~
开始前,请确保你的服务器上已经搭建好了 node 环境。没有的同学,我建议使用
安装 node 。接下来,开始部署
i. 进行服务代理
第一步,将之前 clone 下面的 git 项目切换到主开发分支,然后为了之后的方便修改一下你的 package.json
"scripts": {
"build": "npm run lint && nuxt build && npm start",
"start": "nuxt start"
第二步,启动服务
npm run build
第三步,配置你的 nginx 文件
# 通过 upstream nodejs 可以配置多台 nodejs 节点,做负载均衡
# keepalive 设置存活时间。如果不设置可能会产生大量的 timewait
# proxy_pass 反向代理转发 http://nodejs
upstream nodenuxt {
server 127.0.0.1:3000; # nuxt 项目监听端口
keepalive 64;
listen 80;
server_name www.qiangdada.
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Nginx-Proxy true;
proxy_cache_bypass $http_upgrade;
proxy_pass http:// # 反向代理
最后,重新启动 nginx 服务
sudo service nginx restart
ii. 使用 pm2 做进程守护
如果我们按照上面的步骤进行部署的话,服务器会经常断掉连接,那我们的服务也就断了。所以为了守护好我们的 nodejs 进程,这里我将使用 pm2 对进程进行守护
首先全局安装 pm2
npm i pm2 -g
然后进入到项目目录,执行
pm2 start npm --name "nuxt-ssr-demo" -- run build
然后,妈妈再也不用担心我的 nodejs 进程说断就断啦 ~
对于 pm2 用法,请小伙伴们输入 pm2 --help 然后自行查阅
项目构建步骤
# 安装依赖
$ npm install # Or yarn install
# 启动服务,访问 localhost:3000
$ npm run dev
# 生成环境打包
$ npm run build
$ npm start
# 打包需要部署的静态页面
$ npm run generate
文章到这就要结束了,这里我做一个小总结。在一周的学习和实战中,产出一个高仿掘金的 SSR Demo 的同时,也踩了一些坑。
对于 Nuxt,在使用层面,是比较简单、好上手的。相对 vue-ssr 来说,它大大的简化了开发的配置,让开发人员可以只需思考业务的开发,而不用太去担心文件的配置。其中 Nuxt 通过监听 pages 目录文件变更并自动生成路由更是直接省去了我们平常对于路由的配置。
但是,目前 Nuxt 整体还是有待提高的,目前社区相关的三方插件比较有限,市面上相关的参考资料也相对比较少。
不管如何,希望 Nuxt 社区可以越来越好吧 ~
最后,如果觉得这个项目有点意思,欢迎 star。当然,如果你想和我一起玩这个项目,先进群,然后我们一起探讨思路 ~
@Brickies @0067ED @Meituan-Dianping本文出自汗血宝马,转载时请注明出处及相应链接。
本文永久链接: http://www.caotama.com/102925.html
Ɣ回顶部浅谈vuex之mutation和action的基本使用
转载 &更新时间:日 10:07:33 & 作者:Ethan''s
本篇文章主要介绍了浅谈vuex之mutation和action的基本使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
我们要实现的很简单,就是点击+1的count加一,点击-1的时候count-1
一、mutation
在vue 中,只有mutation 才能改变state.& mutation 类似事件,每一个mutation都有一个类型和一个处理函数,因为只有mutation 才能改变state, 所以处理函数自动会获得一个默认参数 state. 所谓的类型其实就是名字,action去commit 一个mutation, 它要指定去commit哪个mutation, 所以mutation至少需要一个名字,commit mutation 之后, 要做什么事情,那就需要给它指定一个处理函数, 类型(名字) + 处理函数就构成了mutation. 现在test.js添加mutation.
const store = new Vuex.Store({
mutations: {
increment(state) {
state.count++;
decrement(state) {
state.count--
Vue 建议我们mutation 类型用大写常量表示,修改一下,把mutation 类型改为大写
mutations: {
INCREMENT(state) {
state.count++;
DECREMENT(state) {
state.count--
二、action
action去commit mutations, 所以还要定义action. test.js 里面添加actions.
const store = new Vuex.Store({
mutations: {
INCREMENT(state) {
state.count++;
DECREMENT(state) {
state.count--
actions: {
increment(context) {
context.commit("INCREMENT");
decrement(context) {
context.commit("DECREMENT");
action 和mutions 的定义方法是类似的,我们要dispatch 一个action, 所以actions 肯定有一个名字,dispatch action 之后它要做事情,就是commit mutation, 所以还要给它指定一个函数。因为要commit mutation ,所以 函数也会自动获得一个默认参数context,& 它是一个store 实例,通过它可以获取到store 实例的属性和方法,如 context.state 就会获取到 state 属性, context.commit 就会执行commit命令。
其实actions 还可以简写一下, 因为函数的参数是一个对象,函数中用的是对象中一个方法,我们可以通过对象的解构赋值直接获取到该方法。修改一下 actions
actions: {
increment({commit}){
commit("INCREMENT")
decrement({commit}){
commit("DECREMENT")
三、dispatch& action
现在就剩下dispatch action 了。什么时候dispatch action 呢? 只有当我们点击按钮的时候. 给按钮添加click 事件,在click 事件处理函数的中dispatch action.
这个时候我们需要新建一个操作组件,我们暂且命名为test.vue
&template&
&button @click="add"&+1&/button&
&button @click="decrement"&-1&/button&
&/template&
然后,我们在methods里面获取这两个操作事件
export default {
methods: {
increment(){
this.$store.dispatch("increment");
decrement() {
this.$store.dispatch("decrement")
当然上面这种写法比较麻烦,vuex还给我我们提供了mapActions这个函数,它和mapState 是一样的,把我们的 action 直接映射到store 里面的action中。
    import {mapActions} from 'vuex'
export default {
methods: {
...mapActions(['increment', 'decrement'])
如果事件处理函数名字和action的名字不同,给mapActions
提供一个对象,对象的属性是事件处理函数名字, 属性值是 对应的dispatch 的action 的名字。
import {mapActions} from 'vuex'
export default {
methods: {
// 这中写法虽然可行,但是比较麻烦
// 这时vue 提供了mapAction 函数,
// 它和mapState 是一样的,把我们的 action 直接映射到store 里面的action中。
// increment () {
this.$store.dispatch('increment')
// decrement () {
this.$store.dispatch('decrement')
// 下面我们使用一种比较简洁的写法
// ...mapActions(['increment', 'decrement'])
如果事件处理函数名字和action的名字不同,给mapActions
提供一个对象,对象的属性是事件处理函数名字, 属性值是 对应的dispatch 的action 的名字。
// 这里实际是为了改变事件的名字
...mapActions(['decrement']),
...mapActions({
add: 'increment'
这时候我们单击按钮,就可以看到count 发生变化。
最后附一张简单的图形解析,看起来应该能更直观一点
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具

我要回帖

更多关于 华硕灵耀X 的文章

 

随机推荐