# 117080102vueapp **Repository Path**: shhyx007/117080102vueapp ## Basic Information - **Project Name**: 117080102vueapp - **Description**: 这是一个教学用的项目,我们将在这个项目中,实际应用我们之前学习的vue相关基础知识,学习项目实战的过程,希望同学们加油!!! - **Primary Language**: JavaScript - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2019-10-17 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 117080102vueapp #### 介绍 这是一个教学用的项目,我们将在这个项目中,实际应用我们之前学习的vue相关基础知识,学习项目实战的过程,希望同学们加油!!! ## tabbar组件 + 我们用了弹性盒布局 + 简单的接触了一下sass嵌套编写css lang='scss' + 修改了div的标签,router-link to='/xxxx' tag=''div' + 设置路由标签的高亮效果 + css里我们设置了一个类:active + router.js 路由实例中设置了路由高亮 ```vuejs linkActiveClass:'active' ``` ## 创建header组件 + 我们学习了如果安装,引用mint-ui (基于vue.js的移动端的组件集) + 使用了mint-ui 中的header组件 + 改造了header组件,接收三个属性,使header组件可以更灵活的设置样式 ## 创建了四个路由切换的页面组件:home\ shopcart\ search\ member + 在每个组件中引用了header组件,并且给引用的子组件传递了三个必要的属性 + **给子组件传值的时候,如果v-bind要传是字符串,不要使用v-bind,其他任何类型的数据,必须都要使用v-bind** ## 路由跳转时候的过渡效果 + 要给app组件中的router-view标签加transition标签包裹 + 定义过渡的样式 ```vuejs .v-enter{ transform: translateX(100%); } .v-leave-to{ transform: translateX(-100%); } .v-enter-active,.v-leave-active{ position: fixed; width: 100%; transition: all .5s ease; } ``` ## home 组件 + 先写了轮播,用的是mint-ui 中的swipe组件 + 获取数据,使用的是vue-resource + 图标链接 区域 ,使用的是弹性盒布局,自己写的 + 修改了新闻资讯div 为router-link ## newslist组件 + 布局使用了mui的样式,注意:我们只能使用mui的css ,不能使用mui-js + 布局使用了mui-media-list + 给每个li添加了router-link 设置动态的路由:动态的路由就是有动态参数的路由 + 如果你的路由to属性中有变量的时候,需要使用v-bind 指令 + 使用v-bind指令设置to属性的时候,要注意字符串拼接,字符串要用引号引起来,连接变量要用+号连接 ```vuejs ``` ## newsinfo 组件 (新闻详情页) + 获取数据的时候,是根据资讯id来获取的,资讯id是个变量,在写get地址时候,也要注意字符串的拼接 ```vuejs this.$http.get('api/getnew/'+this.id).then(response=>{ ``` + 复习vue过滤器的定制方法,全局的过滤器,要使用Vue.filter(参数1:过滤器名称,字符串,参数2:是设置输出的格式,是function) + 这个function也有一个参数,这个参数是管道符前面的内容,也就是需要我们过滤的数据 + 如果下载,引用,使用momentjs,来设置时间格式 ```vuejs import moment from 'moment' //全局时间过滤器 Vue.filter('dateFormat',function (datestr) { return moment(datestr).format('YYYY-MM-DD HH:mm:ss') }) ``` ## comment 组件(评论组件) + 评论组件需要在调用的时候给它传一个id值,评论组件才能够通过props接收到这个值,从而正确的获取评论数据 + 比较详细的学习了mint-ui中button的用法 + 获取数据,将评论的内容渲染到页面,获取数据时候也要注意字符串拼接 + 在一个字符串中用到多个变量的时候,建议使用模板字符串的方式,引用变量`字符串 ${变量} 字符串` + 加载更多评论功能,改变pageindex的值,然后获取更多的评论 ```vuejs getMore(){ //获取更多评论数据 //1、改变pageindex的数值,2、执行 getComments()获取数据, this.pageindex ++; this.getComments() }, ``` + 发表评论功能,使用vue-resource 中的post方法 ```vuejs postComment(){ //完成提交评论功能 ,post三个参数,参数1:url地址,参数2:是你要提交内容的对象, 参数3:可选,设置一个提交的格式 // console.log(response); // 意味着我已经把数据提交上去了,服务器已经有我这条数据 ,正常是要刷新页面方式,重新获取数据,这样做会给浏览器造成消耗 //我在本地把我这条评论渲染出来, //在提交post请求之前,要做判断,排除空的内容,和空格 //如果是一个值进行判断,只有五个情况是false 数字:0 ,字符串:'',undefined,null ,NaN if (!this.commentContent.trim()){ //判断是否是空的评论, Toast('不能提交空的评论!!'); return } this.$http.post('api/postcomment/'+this.id,{content:this.commentContent}).then(response=>{ let d= new Date(); this.comments.unshift({add_time:d.getTime(),content:this.commentContent,user_name:'匿名用户'}); this.commentContent ='' },error=>{ Toast('提交评论数据失败!!'); }) } ``` ## photolist组件(图片列表页面) + 修改首页的图片分享为router-link,设置路由, + 制作图片导航标签组件,使用的时ly-tab这个插件,这个插件需要npm 安装,然后引用并use + 获取导航标签数据,获取到数据后,添加了全部图片选项,并且给每一项数据添加了一个label的属性,并用title赋值 + 渲染导航 + 分类获取图片数据,是分多次完成的,所以我们用了一个形参来传递id ```vuejs getPhotoLabel(){ //获取图片标签 this.$http.get('api/getimgcategory').then(response=>{ response.body.message.unshift({title:'全部图片',id:0}) response.body.message.forEach(item=>{//item 代表数组中的每一项 item.label = item.title }) // console.log(response) this.items = response.body.message },error=>{ Toast('获取图片导航标签失败!') }) }, handleChange(item){//ly-tab组件自带的change事件,这个事件绑定一个方法,提供给我们两个参数,item\index //item:指的就是我们图片标签链接的每一项,index就是每一项的索引 console.log(item.id); this.getImgList(item.id) }, getImgList(id){ //根据图片分类id,获取相关的图片数据 ,给一个形参id,在调用的时候给他具体的参数(实参) this.$http.get('api/getimages/'+id).then(res=>{//获取成功以后加一个判断,判断一下获取到的图片数量,如果数量为零就给一个提示信息 if (!res.body.message.length){ Toast('暂时没有相关的图片!') } this.imglist = res.body.message },err=>{ Toast('获取图片分类数据失败!') }) } ``` ## imglist组件 (图片列表中显示图片的页面) + 这个组件我们用的是,mint-ui中的lazy-load ,这个组件可以实现图片的懒加载功能 + 这里需要传入一个list数组存放图片,并且,图片的属性名要是:’img_url‘ ## phothinfo 组件 (图片详情页面) + 重复使用了两个之前写的组件,header、comment + 我们学习vue-preview ,这一个vue的实现显示图片缩略图效果的插件,点击缩略图可以浏览大图,实现分享等功能 + 获取数据,渲染页面 + 修改了返回按钮,使用的编程式路由的方式,给按钮添加点击事件,设置$router.go(-1),实现效果 ## 手机上测试项目 + 首先要保证,手机和电脑处在一个wifi下 + 通过 cmd 命令行工具中,执行ipconfig 命令,可以查看你的IP地址,(无线适配器) + 我们要在项目中package.json中的serve下添加 --host 192.168.43.118 + 修改完了package.json后一定要重起服务,npm run serve + 手机上打开浏览器,输入 http://192.168.43.118:8080/ ## goodlist组件 + 学习使用编程式导航来实现路由跳转 + 布局:弹性盒布局,重新复习了一下css相关的基础知识 + 获取数据,渲染页面 ## goodinfo组件 + 学习使用编程式导航来实现路由跳转 + 修改了原来的swipe组件,然后根据组件复用的原则,定义了数据的接口,需要两个属性:swiperlist ,isfull + 还要注意,swipelist中的每一个对象要有img属性,否则不能正确的渲染出图片 ## goodinfo 子组件:goodsbuy 和goodsshow ### goodsbuy组件 + 使用的是mui-card样式作为外包 + 申请数据还是在父组件上申请,然后属性绑定方法传到这个子组件上,子组件props接收 + 逻辑关系还么写 ### goodsshow组件 + 使用的是mui-card样式作为外包 + 使用了mint -ui中的navbar \ tabitem 组件, + 分成三部分:详情\参数\评价 + 评价:引入的是原来的comment组件 + 详情和参数,都是在父组件上申请数据,然后属性绑定方法传到这个子组件上,子组件props接收 + 渲染到页面上 ## shopcart组件 ### 把添加到购物车的商品信息,存储到本地存储中去 + 在添加购物车的时候,要将商品信息传入数组中,传完就将数组写到local storage中去 // localStorage.setItem('存入的名字',‘存储的内容:数组要转为字符串’) + 每次修改这个数组中的商品信息的时候也要重新去存储本地 + 我们是在页面初始的时候读取本地存储,并赋值给数组 ```vuejs var cart = JSON.parse(localStorage.getItem('shopcart0102')||'[]') //从本地存储取值的时候,一定要考虑到没有这个键值的情况,给他添加一个空的数组 console.log(cart); export default new Vuex.Store({ state: { shopcartData:cart }, ``` ## vuex + 是基于vue.js的一个数据状态管理工具,把共享的数据存在state中,方便各个组件调用 + state 专门用来存放共享数据的,调用state的方式:this.$store.state.xxx + mutations 这是vuex专门也是唯一一个正确修改state数据的方法集,默认的方法名大写 + 调用mutation,在组件中可以使用this.$store.commit('mutation_name',payload),只能有一个载荷,可以是对象或者数组 + getters : 也是给组件提供数据,但是,是把state中的数据加工一下再提供给组件 + action:跟mutation一样提供方法修改state,但是他提交的是mutation,再由指定的mutation去修改数据 + module: 当项目复杂到一定程度时候,可以把store分成若干个模块,每一个模块可以有自己的state、mutation。。。 ##shopcart组件 + 添加购物车,把商品相关的数据打包成一个对象,然后把这个对象当成一个参数,传给负责添加数据的mutation + tabbar上购物车数量的更新,使用的是store中的getters,把数组中的商品数量累加起来,return出来 + 完成一个本地存储的功能,存是在添加商品,修改商品属性时候都把商品信息的数组存到localstorage中 + 要在页面加载store的时候把数据读取出来,重新赋值给商品信息数组 + 修改商品选择状态,按钮添加点击事件,调用mutation去修改对应商品的选择状态,修改后存入本地存储 + 完成了购物车商品中增加减少的功能,按钮添加点击事件,调用对应的mutation去修改,修改后存入本地存储 + JavaScript中的some(),这是一个数组的方法,可以查找数组中所有项,是否有符合某些条件的,有返回true,停止查找 + shopcart组件中删除商品功能: + 点击事件时候传入index,来确定具体删除的是那个,然后把index传给 mutation中的deletegoods方法 + 删除后还要重新检查一下,全选按钮的状态,重新赋值给他 ```vuejs DELETEGOODS(state,index){ //删除state中商品数组中的某个商品 state.shopcartData.splice(index,1)//参数1,从第几个开始删除,参数2:删除几个,参数3、4、5就表示要添加的内容 //删除某个商品后还要再检查一下所有商品的选中状态,然后赋值给全选按钮 var flag = state.shopcartData.every(item=>{//数组的every()所有都满足条件才能返回true return item.selected === true }); console.log(flag); if (flag) { state.selectAll = flag }else { state.selectAll = flag } localStorage.setItem('shopcart0102',JSON.stringify(state.shopcartData)) localStorage.setItem('seleteall0102',JSON.stringify(state.selectAll)) } ``` + 改变shopcart组件中商品的选中状态 + 在这个状态按钮上添加事件,点击让对应商品的状态取反,所以也要传递参数id + state。mutation中的CHANGE_STATUS方法中根据id让selected取反 + 修改完状态后,检查一下所有商品的状态,如果所有商品都是选中状态,就让全选按钮选中 ```vuejs CHANGE_STATUS(state,id){//修改state商品数组中某个商品的选中状态 state.shopcartData.some(item=>{ if (id===item.id){ //通过id去查找到对应的商品,然后变更其状态 item.selected = !item.selected } }) //我们可以遍历所有的商品对象,如果发现有一个商品的选中状态为 false ,则让 全选 按钮变成 false // var x = state.shopcartData.some(item=>{ //如果有一个商品是false ,我们这个some方法就会找到他,返回true // return item.selected===false // }) // console.log(x); // if (x){ //如果x是true的话,就表示,有 '没选中的商品',然后我就会让全选按钮变成 false // state.selectAll = false // }else { // state.selectAll = true // } //我们可以遍历所有的商品对象,如果发现有一个商品的选中状态为 false ,则让 全选 按钮变成 false // // 也可以说:只有全部按钮都是选中的时候,全选按钮才能是选中 var flag = state.shopcartData.every(item=>{//数组的every()所有都满足条件才能返回true return item.selected === true }); console.log(flag); if (flag) { state.selectAll = flag }else { state.selectAll = flag } localStorage.setItem('shopcart0102',JSON.stringify(state.shopcartData)) localStorage.setItem('seleteall0102',JSON.stringify(state.selectAll)) } ``` ## account结算组件 功能实现 ### 显示所有选中状态的商品的数量合计,金额合计,使用getters来完成 + 初始时候设置一个对象为空的,然后遍历商品数组中的对象,把选中的商品挑出来,然后把数量和金额累加到我们要返回的对象中, + 调用的时候,可以在组件里,计算属性中,定义一个属性来接收这个getters,要注意这个属性是个对象, ```vuejs goodsTotal(state){ //在购物车结算界面输出所有选中商品的数量和合计 var t = {count:0,total:0} //先赋值一个空的格式对象 //state.shopcartData中满足条件(被选中的)的商品,数量累加到t.count中,把价格x数量放到total中,最后return t state.shopcartData.forEach(item=>{ if (item.selected){ t.count += item.count; t.total += item.count*item.price } }) return t } ``` ### 全选按钮的状态功能 + 点击全选按钮,让它本身状态取反,然后要重新根据全选按钮的状态,赋值给所有商品状态 ```vuejs CHANGE_SELECT_ALL(state){ //修改state中selectall的状态值 state.selectAll = !state.selectAll; //每一次点击都会首先让全选按钮状态取反 state.shopcartData.forEach(item=>{ //遍历我们商品数组中的每一项,让全选按钮状态等于每一项的选中状态 item.selected = state.selectAll }) localStorage.setItem('shopcart0102',JSON.stringify(state.shopcartData)) localStorage.setItem('seleteall0102',JSON.stringify(state.selectAll)) } ``` + 修改后也要存入本地存储,并在页面加载时候读取本地存储中的数据,再赋值给它,注意,取出的是字符串,要判断,赋值 ```vuejs var selectall = localStorage.getItem('seleteall0102')==='false'?false:true //从本地存储取值的时候,一定要考虑到没有这个键值的情况,给他添加一个空的数组 console.log(cart ,selectall); export default new Vuex.Store({ state: { shopcartData:cart, selectAll:selectall ```