# vue_system **Repository Path**: VCS/vue_system ## Basic Information - **Project Name**: vue_system - **Description**: No description available - **Primary Language**: JavaScript - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 4 - **Created**: 2018-11-29 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README #vue_system ## 项目基本结构搭建和环境配置 1. 安装依赖模块 npm install 2. 配置webpack.config.js 3. 配置项目入口文件main.js 4. 配置vue项目根组件App.vue ## 实现根组件头部和底部样式 1. mint-ui实现头部 2. router-view占位 3. mui实现底部tabbar ## 首页轮播图 1. main.js中更改路由规则 2. Home.vue中使用mt-swipe组件 3. 使用假数据填充图片 ## 使用vue-resource请求轮播图数据 1. npm 安装vue-resource npm install vue-resource --save 2. main.js中导入vue-resource 3. 在vue的生命周期created方法中使用$http请求数据 ## 使用MUI布局首页九宫格导航 1. 使用MUI九宫格组件布局导航 2. 替换导航中的默认图片 3. 更改a标签为router-link实现路由跳转 ## 使用MUI实现新闻列表界面 1. 在main.js中添加路由规则 {path:'/news/newslist',component:newslist} 2. 利用MUI图文列表组件实现新闻列表布局 3. 使用vue-resource请求新闻列表真实数据 4. 使用v-for循环渲染界面 5. 添加样式美化列表 ## 使用全局过滤器和moment.js实现日期格式化 1. main.js中注册全局过滤器 Vue.filter('datefmt',function(input,fmtstring){} 2. 安装moment npm install moment --save 3. 使用moment格式化时间 Vue.filter('datefmt',function(input,fmtstring){ // 使用momentjs这个日期格式化类库实现日期的格式化功能 return moment(input).format(fmtstring); }) 4. newslist.vue中使用日期过滤器 发表时间:{{item.add_time | datefmt('YYYY-MM-DD HH:mm:ss')}} ## 实现跳转新闻资讯详情页面及传参 1. 在main.js中添加路由规则 {path:'/news/newsinfo/:id',component:newsinfo} 2. 修改新闻列表界面中的a标签为router-link 3. 配置跳转参数 4. 实现页面传参 created() { // 获取URL传入的参数id赋值给data中的id属性 this.id = this.$route.params.id; } ## 实现详情页面界面布局和真实数据 1. 使用css完成基本布局 2. 请求真实数据 3. 使用vue指令赋值真实数据 ## 公共功能提取-API根域名提取 1. 将根域名存放到common.js中 export default{ apidomain:'http://webhm.top:8899', // 所有数据请求的根域名地址 } 2. 导入common.js使用 ## 评论组件-提交评论功能 1. 父组件向子组件传值 - 父组件中注册组件 components: { comment, // II. 注册评论组件 }, - 父组件中使用子组件时属性传值 - 子组件中props接收传值 props: ['id'],//用来接收父组件传递过来的值 2. 实现评论提交界面样式 3. 发送post请求提交数据 - 数据为空时提示用户不能提交 - 提交成功清空文本框数据 ## 评论组件-列表数据展示功能 1. 使用MUI列表组件实现基本样式布局 2. 请求真实数据赋值给list 3. v-for渲染数据到界面 ## 评论组件-点击加载更多功能 1. 定义全局变量pageindex,点击加载更多时pageindex++ 2. 传入pageindex重新发送数据请求 3. 进行数据拼接:将新数据和旧数据拼接到一个数组中 this.list = this.list.concat(res.body.message); ## 优化-默认显示home及最新评论在前功能 1. 添加路由规则重定向根目录为home页面 {path:'/',redirect:'/home'},// 默认进入home页面(将跟页面重定向到首页home) 2. 将最新添加的数据追加到数组最前面 this.list = [{ "user_name": "匿名用户", "add_time": new Date(), "content": this.postcontent }].concat(this.list); ## 图片分享列表-跳转及页面样式 1. `router-link`设置跳转路径 2. main.js中设置路径规则 - 导入photolist组件 import photolist from './components/photo/photolist.vue' - 设置路由规则 {path:'/photo/photolist',component:photolist} 3. 布局及书写分类样式 ## 图片分享列表-请求分类真实数据 1. `v-for`循环渲染
  • {{item.title}}
  • 2. 请求真实数据存放到`cates`数组中 3. 根据`cates`长度及每一个li的宽度动态计算ul的宽度 ## 图片分享列表-图片列表样式及真实数据 1. 使用`mint-ui`的`lazy-load`控件实现图片懒加载功能 2. 布局图片及文字样式 3. 请求真实图片数据 4. 给分类选项绑定点击事件 ## 图片分享详情-点击图片跳转到详情 1. 使用`router-link`包装图片 2. 设置跳转的路由规则 - 建立`photoinfo.vue`组件 - 导入`photoinfo.vue` import photoinfo from './components/photo/photoinfo.vue'; - 配置路由规则 {path:'/photo/photoinfo/:id',component:photoinfo} 3. 获取路由传递的id值 this.id = this.$route.params.id; ## 图片分享详情-基本页面布局 1. 使用九宫格组件布局缩略图界面 2. 使用封装的评论组件布局评论模块 3. 请求图片详情数据 ## 图片分享详情-vue-preview实现缩略图预览 1. 安装`vue-preview` npm install vue-preview --save 2. `main.js`中注册`vue-preview`到vue对象中 import VuePreview from 'vue-preview'; Vue.use(VuePreview); 3. `webpack.config.js`中添加`babel`转码 { test: /vue-preview.src.*?js$/, // vue-preivew组件专用 loader: 'babel' } 4. `url-loader`添加`svg`文件格式支持 { test: /\.(png|jpg|gif|ttf|svg)$/, loader:'url-loader?limit=20000' } 5. 更改图片配置 6. 在`list`中添加数据 ## 图片分享详情-请求真实数据 1. 将`v-for`放到li标签上适配样式
  • 2. 请求真实数据 3. 重新组装数据格式(添加图片的宽高属性) // 图片对象必须有宽高属性才能预览大图,所以需要对请求回来的数据添加w h属性 { src: 'https://placekitten.com/1200/900', w: 600, h: 400 } ## 商品购买路由跳转及静态结构 1. `Home.vue`中设置跳转路径 2. `main.js`中设置路由规则 {path:'/goods/goodslist',component:goodslist} 3. 利用mui中的图文表格组件实现: http://www.dcloud.io/hellomui/examples/slider-table-default.html ## 商品购买请求动态数据 this.$http.get(url).then(function(res){ // res.body即为请求回来的数据 }); ## 商品详情-路由跳转 1. `goodlist.vue`中配置跳转路径 2. `main.js`中配置路由规则 {path:'/goods/goodsinfo/:id',component:goodsinfo}, ## 商品详情-轮播图组件的提取 1. 抽取组件: - 将`Home.vue`中的轮播图结构代码和样式代码抽取到单独的`silder.vue`文件中 - 定义一个用于接收父组件传递过来参数的imgs属性 2. 使用组件 - 需要使用`siler`组件的父组件中先注册组件 import silder from '../components/subcom/silder.vue'; ... ... components:{ silder } - 使用组件并传递参数 ## 商品详情-详情页面静态结构布局 1. 根据页面模块书写`HTML`结构 2. 书写`CSS`样式 ## 商品详情-请求动态数据 1. 根据`API`请求真实数据 2. 完善请求中的判断数据状态 ## 商品详情-图文详情页面 1. `goodsinfo.vue`中设置路由跳转路径 图文详情 2. `main.js`中配置路由规则 // 导入组件 import goodsdesc from './components/goods/goodsdesc.vue'; // 设置路由规则 {path:'/goods/goodsdesc/:id',component:goodsdesc}, 3. 根据`API`请求数据 ## 商品详情-商品评论组件集成 1. `goodsinfo.vue`中设置路由跳转路径 商品评论 2. `main.js`中配置路由规则 // 导入组件 import goodscomment from './components/goods/goodscomment.vue'; // 设置路由规则 {path:'/goods/goodscomment/:id',component:goodscomment}, 3. `goodscomment.vue`中集成`comment.vue`组件 // 注册子组件 components:{ comment } // 使用子组件 ## 商品详情-定制inputNumber组件 1. 创建`inputNumber.vue`文件实现组件布局和增减逻辑 2. 子组件向父组件传值 - 子组件inputNumber中定义方法使用this.$emit传值 sendmessage(){ this.$emit('dataobj',this.count); } - 子组件中数据发生变化时调用sendmessage方法 this.sendmessage(); - 父组件使用子组件时绑定子组件传值时属性名相同的方法`dataobj` - 父组件定义getcount方法,参数即为子组件传递过来的值 getcount(count){ // count 即为子组件传递过来的数据 this.inputNumberCount = count; }, 3. 父组件中使用子组件 - 注册子组件 components:{silder,inputnumber} - 使用子组件 ## 商品详情-加入购物车同步角标数字 > 因为购物车数量`inputNumber`在`goodsinfo.vue`组件中,而角标在`App.vue`组件中,两者不是父子组件关系,无法直接传值。父子组件能够传值正是因为共享了同一个`vue`实例对象,所以需要额外定义一个公共的`vue`实例实现子组件向父组件传值的方式将数据传递到`App.vue`中。 1. 定义`vm.js`文件导出一个空的`vue`实例 import Vue from 'Vue'; // 导出一个常量 export const COUNTSTR = 'inputNumberCount'; // 导出空的vue实例 export var vm = new Vue(); 2. `goodsinfo.vue`中定义方法使用该公共实例传递数据 // 导入公共实例 import {vm,COUNTSTR} from './kits/vm.js'; ... toshopcar(){ // 触发事件 COUNTSTR代表事件名 是vm.js中定义的常量 vm.$emit(COUNTSTR,this.inputNumberCount); } 3. `App.vue`中使用该公共实例获取数据 // 导入公共实例 import {vm,COUNTSTR} from './kits/vm.js'; // 利用 vm.$on() 来注册 COUNTSTR这个常量代表的事件 vm.$on(COUNTSTR,function(count){ // 将count值追加到购物车中 var badgeobj = document.querySelector('#badge'); badgeobj.innerText = parseInt(badgeobj.innerText) + count; }); 4. 点击购物车时触发`toshopcar`方法将数据传递到`App.vue` 加入购物车 ## 商品详情-使用localStorage存储购物数量 1. 定义本地存储公共帮助文件 // 实现添加获取删除 export function setItem(value){} export function getItem(){} export function removeItem(){} 2. 点击加入购物车时调用`setItem()`存储数据 ## 商品详情-购物车小球动画效果 1. 书写小球样式 2. 设定需要动画的元素
    3. 使用动画钩子函数实现小球出现动画 // 动画出现前 beforeEnter(el){ // 设定小球的初始位置 el.style.transform = "translate(0px,0px)"; }, // 动画出现 enter(el,done){ // 保证小球出现动画 el.offsetWidth; // 设置小球的结束位置 el.style.transform = "translate(75px,366px)"; //结束动画 done(); }, // 动画结束 afterEnter(el){ //重置小球的初始状态 this.isshow = !this.isshow; } ## 购物车-列表界面静态结构 1. 设置跳转路径和路由规则 {path:'/shopcar/car',component:car} 2. 利用`v-model`绑定开关状态并存储到数组中 ## 购物车-列表界面请求真实数据 1. 将本地存储中`goodsid`相同的多个对象合并成同一个对象 export function getgoodsObject(){ var arr = getItem(); var resObj ={}; for(var i = 0 ; i { if (to.meta.requireAuth) { // 判断该路由是否需要登录权限 if (getCookie('session')) { // 通过cookie获取当前的token是否存在 next(); } else { next({ path: '/login', query: { redirect: to.fullPath } // 将跳转的路由path作为参数,登录成功后跳转到该路由 }) } } else { next(); } } } 2. 进入拦截后的界面login,处理完登录请求后,进入userinfo // 模拟 setTimeout(() => { //登录状态1天后过期 let expireDays = 1000 * 60 * 60 * 24 * 1; // 实际项目中token是由后台返回的加密组合信息,是从接口返回的数据 setCookie('session', 'token', expireDays); this.isLoging = false; //登录成功后 this.$router.push('/userinfo'); }, 1000) ## 集成百度地图 1. 在百度地图开发者网站申请开发者key(选择浏览器端应用) http://lbsyun.baidu.com/apiconsole/key?application=key 2. 在项目中引入百度地图库文件(由于异步加载的问题,在组件中引入方式比较特殊,这里直接在模板文件中引入) 3. 在vue文件中实例化地图(地图需要显示在一个容器div中,实例化地图的方法要写在生命周期mounted中) mounted() { // 创建地图 var map = new BMap.Map("allmap"); // 初始化地理位置 var point = new BMap.Point(116.331398, 39.897445); // 缩放中心和比例 map.centerAndZoom(point, 12); // 定位 var geolocation = new BMap.Geolocation(); geolocation.getCurrentPosition(function (r) { if (this.getStatus() == BMAP_STATUS_SUCCESS) { // 定位成功 标记地理位置 var mk = new BMap.Marker(r.point); map.addOverlay(mk); map.panTo(r.point); console.log('您的位置:' + r.point.lng + ',' + r.point.lat); } else { alert('failed' + this.getStatus()); } }, { enableHighAccuracy: true }) } ## axios集成 // 1. 安装axios核心库(qs是post请求时对参数进行序列化的库) npm install axios qs --save // 2. 将axios制作成Vue插件进行集成(新建一个axios.js文件书写以下代码) import axios from 'axios'; // 设置请求根域名 axios.defaults.baseURL = 'http://www.lovegf.cn:8899'; export default { install:function(Vue){ // 将$axios 绑定到Vue.prototype上 并且该属性为只读 Object.defineProperty(Vue.prototype, '$axios', { value: axios }); } } // 3. main.js中使用Vue.use()安装 import axios from './kits/axios.js' Vue.use(axios); // 4. 使用axios发送get请求 this.$axios.get(url).then(function(res){ // 返回的响应数据在res.data属性中 console.log(res.data); // 回调函数内部的this不是当前数据请求方法的调用者 // 通常内部this是window 在node平台 内部this是undefined }) // 一般使用箭头函数写法 this.$axios.get(url).then((res)=>{ console.log(res.data); }) // 5. 使用axios发送post请求 // post请求(Content-Type:application/x-www-form-urlencoded 时需要配合qs.stringify使用) import qs from 'qs'; this.$axios.post(url,qs.stringify({数据}).then((res)=>{ // 返回的响应数据在res.data属性中 console.log(res.data); }) ## 集成上拉加载更多 1. 使用组件包裹容器 // loadTop 下拉刷新方法 // loadBottom 上拉加载更多方法 // allLoaded 判断数据是否全部加载完毕属性 // autoFill 设置false 解决自动执行上拉操作 2. 下拉一般加载最新数据,就是获取第一页数据,数据请求回来后需要调用 this.$refs.loadmore.onTopLoaded();重置下拉loading位置 3. 上拉加载更多数据,就是分页功能,数据请求回来之后需要调用 this.$refs.loadmore.onBottomLoaded();重置上拉loading位置 4. 上拉所有数据都加载完毕,设置this.allLoaded = true,禁止上拉效果 ## 集成路由过渡动画 1. 使用transition标签包裹router-view,并在data中定义样式类名transitionName 2. 监听路由变化,判断是使用哪种过渡效果 '$route': function(to, from) { // to 表示将要进入的路由(到哪儿去) // from 表示将要离开的路由(从哪儿来) const toDepth = to.path.split('/').length; const fromDepth = from.path.split('/').length; console.log(to.path,from.path,toDepth, fromDepth); // 根据路由深度判断是进入页面还是返回页面 // 例如当前页面 路由地址是 /photo/photolist 路由深度就是 3 // 进入 /photo/photoinfo/37 路由深度就是4 // 进入页面就使用 slide-left 返回页面就是要slide-right this.transitionName = toDepth < fromDepth ? 'slide-right' : 'slide-left' } 3. 定义slide-right和slide-left样式类 .slide-left-enter,.slide-right-leave-active { transition: all 0.2s ease; opacity: 0; -webkit-transform: translate(300px, 0); transform: translate(300px, 0); } .slide-left-leave-active,.slide-right-enter { transition: all 0.2s ease; opacity: 0; -webkit-transform: translate(-300px, 0); transform: translate(-300px, 0); } ## 路由懒加载 > 功能: 当没有访问到某个页面路由时,不去加载对应的组件代码,节约数据请求量,加快首页DOM渲染速度 1. 先将项目升级到webpack2以上,相关包也做升级处理,配置文件需要做一些修改,详见代码 "webpack": "^3.5.6", "webpack-dev-server": "^2.7.1", "extract-text-webpack-plugin": "^3.0.0", 2. 安装路由懒加载语法解析器 `npm install babel-plugin-syntax-dynamic-import --save-dev` 在babel配置文件中加入: "plugins": ["transform-runtime","syntax-dynamic-import"] 3. 改变导入组件的方式 将import home from './components/Home.vue' 这种导入换成 const home = () => import('../components/Home.vue');