vue全家桶上手小项目
实现功能
主要用到的技术:
vue-cli + vue2 + vue-router2 + vuex2 + axios + es6 + sass + eslint
主要实现的功能:
页面的数据通过 axios 模拟请求本地的 json 文件获得;vue-router2 实现各页面的相互跳转;vuex2 全局状态的管理,如头部导航的标题内容,侧栏的显示状态;简易购物车功能,详情页加入购物车的商品,随机生成单价、商品名字;购物车的信息通过localstorage存储在本地;注册登录的信息也是通过localstorage存储在本地。项目目录结构
proj5-shop 目录结构,主要看src目录和static目录的:
│--build|--config|--dist|--src |--assets |--logo.png |--components |--cart 购物车页 |--cate 商品列表页,商品详情页 |--center 个人中心,注册登录 |--com 公共模块 |--header.vue 头部 |--loading.vue 加载 |--sidebar.vue 导航侧栏 |--swiper.vue 轮播 |--jam.js 公共功能函数 |--localDB.js localStorage本地存储 |--page 首页 |--Hello.vue|--static 本地数据模拟请求(需放static目录下) |--data |--cart.json |--cate.json |--index.json | .gitkeep|--test│ .babelrc│ .editorconfig│ .eslintignore│ .eslintrc.js│ .gitignore│ index.html│ package.json│ README.md
vue-cli 初始化及配置修改
vue-cli 脚手架官方安装:
$ npm install -g vue-cli$ vue init webpack proj5-shop$ cd proj5-shop$ npm install$ npm run dev
vue-cli初始化完成后,继续新增安装以下依赖:
cnpm install axios node-sass vuex sass-loader vue-swipe --save-dev
修改 build/webpack.base.conf.js
,使其对import引入的sass支持:
{ test: /\.vue$/, loader: 'vue-loader', options: vueLoaderConfig}// 将上面的修改成下面的:{ test: /\.vue$/, loader: 'vue-loader', options: { loaders: { 'scss': 'vue-style-loader!css-loader!sass-loader', 'sass': 'vue-style-loader!css-loader!sass-loader?indentedSyntax' } }}
关键功能技术点剖析
template 与指令
商品分类页 src/components/cate/cate.vue
的 template:
{ {brand.brand_name}} { {brand.brand_price}}
商品详情页 src/components/cate/detail.vue
的 template:
axios 数据请求
首页的数据请求:
首先在入口文件main.js
引入 axios,并将其挂在到 Vue 全局方法下: // main.jsimport axios from 'axios'Vue.prototype.$http = axios
在首页 page/index.vue
使用 axios:
最终将数据渲染在 template 上:
{ {brand.brand_name}} { {brand.brand_desc}} { {brand.brand_name}} { {brand.brand_desc}}
router 的跳转
router/router.js
路由:
import Vue from 'vue'import VueRouter from 'vue-router'Vue.use(VueRouter)import App from '../App.vue'import Index from '../components/page/index.vue'import Cate from '../components/cate/cate.vue'import Detail from '../components/cate/detail.vue'import Center from '../components/center/center.vue'import Cart from '../components/cart/cart.vue'export default new VueRouter({ routes: [ { path: '/', redirect: '/index', component: App, children: [ {path: 'index', name: 'index', component: Index}, {path: 'cate', name: 'cate', component: Cate}, {path: 'detail', name: 'detail', component: Detail}, {path: 'center', name: 'center', component: Center}, {path: 'cart', name: 'cart', component: Cart} ] } ], linkActiveClass: 'footer-act'})
主要是通过 router-link
来跳转,比如导航栏 com/sidebar.vue
的跳转:
-
首页 > -
分类 > -
我的 > -
购物车 >
当然,在 加入购物车
的时候,采用的编程式导航跳转路由:
加入购物车// 编程式导航,点击时触发路由跳转router.push({ path: 'cart' })
vuex 状态管理
vuex 状态管理主要是头部的显示信息、导航栏的显示隐藏状态:
先来看store/store.js
: import Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)export default new Vuex.Store({ state: { sideBarState: false, //导航侧栏的显示状态 headerTitle: '默认的头部标题' //不同页面头部标题的变更 }, mutations: { changeSideBarState (state, boolean) { state.sideBarState = boolean }, changeHeaderTitle (state, str) { state.headerTitle = str } }, actions: { // changeSideBarState (context, status) { // context.commit('changeSideBarState', status) // } // es6解构写法 changeSideBarState ({commit}, status) { commit('changeSideBarState', status) }, changeHeaderTitle ({commit}, str) { commit('changeHeaderTitle', str) } }, getters: { getSideBarState (state) { return state.sideBarState }, getHeaderTitle (state) { return state.headerTitle } }})
例如,在进入分类页 cate/cate.vue
时,会在 created
的时候触发头部标题的变更;
导航
时,又会触发导航侧栏的显示状态的变更: created () { this.$store.dispatch('changeHeaderTitle', '分类')},methods: { showSideBar () { return this.$store.dispatch('changeSideBarState', true) // return this.$store.commit('changeSideBarState', true) }, hideSideBar () { return this.$store.dispatch('changeSideBarState', false) }}
购物车
在进入商品详情页的时,会随机生成商品的名称和价格,使得 加入购物车
时能在购物车页面区分开个商品(主要是还没做后端node+mongodb的数据):
// cate/detail.vuedata () { return { detailData: { id: 100048, type: 'type_man', isSelect: true, cart_img: 'http://ohe5avf3y.bkt.clouddn.com/pro/vue/vue-shop/vue-proj-goods.jpg', cart_name: '商品名字' + this.getRandom(10, 100), cart_num: 1, cart_price: this.getRandom(10, 100) } }}
点击 加入购物车
,实际就是将该商品的 data 信息加入到 localStorage 的本地存储中;这里主要用到一个自己定义的 localDB.js
:
export default class todoDb { constructor (name) { this.name = name if (JSON.stringify(this.get(this.name)) === '{}') { this.set([]) } } set (val) { window.localStorage.setItem(this.name, JSON.stringify(val)) } get () { return JSON.parse(window.localStorage.getItem(this.name)) || {} }}
购物车 cart/cart.vue
主要思路就是:读取本地存储购物车中的localStorage 所有产品信息并显示出来;根据用户增删操作、来更新本地购物车存储的产品信息。
注册登录
注册登录的用户中心页面 center/center.vue
,主要是控制三种状态的显示与隐藏:登录、注册、登录成功后的用户中心,主要是data里面的 showState ;
详情看github源码中的 center/center.vue
。
新手的小坑总结
build 后需在服务器打开访问
执行npm run build
后生成的dist,直接在浏览器以本地文件 file:// ... 打开里面的index.html 、是访问不了的;需要放在服务器上才能访问;或者自己在本地开启一个服务器。 引入的component,外层要有容器
如下面的 <comHeader></comHeader> ,它外层一定要有容器、把它包裹着:v-for key
component lists rendered with v-for should have explicit keys:// ...
详见:
原生html报waring
当我们引入的component命名成原生的html时,会报warning,于是把// 报 warning import comHeader from './components/com/header.vue'components: { // hearder: hearder comHeader: comHeader}
判断对象为空
if (typeof myObj == "undefined") { var myObj = {};}
webstorm卡顿
webstorm 需要把 node_models 文件夹排除掉(exclued),不然很卡顿。目前正学习node+mongodb,准备以此取代该项目中模拟的本地数据请求和localStorage,项目代码: