前言
每次写文章时,总会觉得比写代码难多了,可能这就是我表述方面的不足吧,然而写文章也是可以复盘一下自己的开发过程,对自己还是受益良多的。在这里简单叙述一下我仿某鱼部分布局以及功能实现的过程,仅做学习用途。
Vue是一套用于构建用户界面的渐进式框架,Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的SPA单页面应用提供驱动。
技术栈以及组件库
vuex: 解决组件数据共享问题,加强组件数据持久化。
vue-router: 主要实现spa单页面开发。
axios: 异步请求数据。
easymock: 假数据模拟接口。
mint-ui: 一款移动端开发的框架。Mint UI
stylus: css预处理器
better-scroll: 一个移动端滚动的解决方案
swiper: 一个强大的滑动特效插件
lrz: 图片压缩插件
实现效果
搜索
分类
登录
购买
发布
代码目录结构
┣━ src # 开发目录 ┣━ api //axios获取假数据的统一js ┣━ data.js ┣━ assets //静态文件资源 ┣━ images //图片 ┣━ utils //通用js方法函数 ┣━ common //通用的文件资源 ┣━ stylus //stylus文件夹 ┣━ component //可复用的组件 ┣━... ┣━... ┣━... ┣━... ┣━... ┣━... ┣━ pages //页面(页面组件) ┣━... ┣━... ┣━... ┣━... ┣━... ┣━... ┣━ router //路由 ┣━ index.js ┣━ store //vuex数据状态管理 ┣━ index.js ┣━ state.js ┣━ mutations.js ┣━ actions.js ┣━ getters.js ┣━ App.vue //根组件 ┗━ main.js
实现主要的几个功能
登录退出
用户在已登录状态和未登录状态的界面是不同的,有些功能指定要在登录状态下才会有,因此会产生状态的切换,我们可以通过浏览器自带的window.localStorage来存储数据,也可以用vuex,如果状态多的情况下建议采用vuex
搜索功能
这个没什么好说的,利用indexOf这个方法来验证假数据中是否有这个key,相应输出它的value,没有那就切换另一个找不到的UI界面
分类功能
这个也没有什么难度,取到假数据中的数据来for in循环输出,然后用better-scroll插件来实现滚动对应的高度效果
购买
如果是在未登录的状态下,那么进行一个router-link路由跳转到登录login页面,如果是已登录的状态下,会进入到一个商品详情页,点击我想要会进入到一个与卖家聊天交互的一个界面,这里面的卖家的数据都是模拟出来的假数据,因此它不能像真的卖家一样。其中每一个表情emoji就是一个图片,用code的方式把它编译出来再进行一个swiper轮播来包裹他们的遍历循环。
接着点击立即购买则会跳到付款页面,如果填过地址等信息的,那么可以选择,如果未填的,则会引导至输入相关信息页面,再点击购买就成功了,这个时候数据就会利用vuex保存到我的个人页面中的我买到的页面中。可以进行确认收货后删除订单。发布
一样,只有在已登录的状态下才可以进入到发布的界面,发布就是充当着一个卖家的身份,需要填写商品详情的相关信息包括图片,价格等。通过验证才可发布成功,同样利用了vuex来保存发布的商品信息,再跳至我的页面中的我发布的页面进行数据输出。
设备适配
我是用rem来实现的,也建议用rem来自适应布局,先自己封装一个自适应html的 font-size的js,再将其导入到main.js中
/** * Created by zhaolele on 2018/7/25. */ (function(doc, win) { var docEl = doc.documentElement, resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize', recalc = function() { var clientWidth = docEl.clientWidth; if (!clientWidth) return; docEl.style.fontSize = 32 * (clientWidth / 320) + 'px'; }; if (!doc.addEventListener) return; win.addEventListener(resizeEvt, recalc, false); doc.addEventListener('DOMContentLoaded', recalc, false); })(document, window); //10rem
移动端一像素
众所周知,移动端因不同的设备的分辨率导致一像素并不是真正的统一的一像素,因此我们需要封装一个stylus的mixin来引入
border-1px($color) position: relative &:after display: block position: absolute left: 0 bottom: 0 width: 100% border-top: 1px solid $color content: ' ' @media (-webkit-min-device-pixel-ratio: 1.5),(min-device-pixel-ratio: 1.5) .border-1px &::after -webkit-transform: scaleY(0.7) transform: scaleY(0.7) @media (-webkit-min-device-pixel-ratio: 2),(min-device-pixel-ratio: 2) .border-1px &::after -webkit-transform: scaleY(0.5) transform: scaleY(0.5)
图片上传
可以使用input中type的file属性,然后用html5的新属性hidden来隐藏掉这个节点,通过点击其他的节点来触发这个input type=file的点击事件,再利用lrz的图片压缩将图片优美的输出到也页面中。拿里面的上传头像的代码贴一下。
html: <div class="avatar" @click="addPic"> <img :src="url" alt=""> <span class="upavatar">上传帅照</span> <input type="file" hidden accept="image/jpeg,image/jpg,image/png" capture="camera" @change="fileInput" ref="file"> </div> js 方法: addPic() { this.$refs.file.click() }, //点击触发fileInput事件 fileInput(e) { let files = e.target.files console.log(files) if(!files.length) return this.createImage(files, e) }, createImage(files, e) { lrz(files[0], { width: 480 }).then(rst=> { this.url = rst.base64 }).catch(err=> { console.log(err) }).always(()=> { e.tartget.value = null }) },
结语
**很多东西细节想聊出来,比如嵌套路由所踩的坑..等,但是最近忙于找工作,时间问题就写到这里,有兴趣或者正在学习vue的同学可以查看我的github源码。fallow-fish
如果对你有帮助,可以star我的项目给我一点点的鼓励,也希望有志同道和的可以加入一起讨论,我也会第一时间帮你解答。**