基于wexplus开发app是来新公司才接触的,以前只是用过weex体验过写demo,当时就被用vue技术栈来开发app的开发体验惊艳到了,这个开发体验比react native要好不少,对于我这个纯web前端来讲简直不要太好!html
weexplus是基于weex官方的二次开发版本,旨在解决weex官方配置麻烦、性能很差、开发体验很差等问题。weexplus框架是这边同事根据实际的项目抽离出来的开源框架,已经帮咱们趟过不少坑了,具体组件用法在此再也不赘述,link-放出文档。本文仅为本人视角开发一个吉他学习app的踩坑之路记录,记下以避免后面再踩坑。前端
文章可能会很长,在此分几篇文章来写,先占个坑:vue
app的ui界面与h五、小程序公用一套,因此作出来的界面也是基本同样,这里感谢如下杨伯伯提供的设计稿。node
$ npm install weex-toolkit -g // -g表示全局安装,下同
$ npm install weexplus -g
$ 浏览器访问 https://github.com/weexplus/boilerplate,下载压缩包获得文件boilerplate-master.zip; $ 解压boilerplate-master.zip获得文件夹boilerplate-master; $ cd到跟boilerplate-master平级的目录; $ weexplus rename loveguitar com.loveguitar.23jt loveguitar; $ cd loveguitar $ npm install //安装依赖包 $ npm run dev $ weexplus start //运行改命令须要另外开一个终端,运行成功后谷歌浏览器会跳出一个新页面,必须安装谷歌浏览器 $ 下载安卓apk调试包(真机扫码调试)地址 https://pan.baidu.com/s/16kJfMuyXX-Y_yhm5fHt79Q
至此,weexplus开发环境基本搭建完毕,若是须要打包安卓、ios的话,与原生开发同样,自行百度便可解决。react
如图为weexplus脚手架项目目录结构图,咱们日常开发主要在src
目录里写代码,能够看到该目录与vue项目目录结构基本差很少。ios
在写代码前能够把脚手架里无用的代码删除掉,留下component
文件夹便可。先作的第一件事我的建议是依照原型或者设计稿的业务逻辑在src/busi
文件夹中按照业务模块建好文件夹(以爱尚吉他为例):git
map:琴行地图功能模块,里面分为琴行地图首页、琴行详情、琴行导航 news:文章模块,里面分为文章列表、文章详情、标签列表 search:文章搜索模块 video:视频教程模块,里面分为视频模块首页,视频列表、视频详情
子曰:“工欲善其事,必先利其器。”在写首页的代码前在此安利一款切图标注工具--蓝湖, 大大提升设计师和开发的工做效率,具体使用参见官网介绍便可http://sos.lanhuapp.com/#/。github
以上为首页的设计图,先来分析一下页面结构,看看哪些能够复而且能够封装为公共组件。如图所示能够分为以下几个模块:web
1(banner模块),在componet文件夹下新建my-banner.vue文件 2(模块标题),在componet文件夹下新建my-title.vue文件 3(菜单模块),在componet文件夹下新建my-nav.vue文件 4(文章列表模块两个类型)在componet文件夹下新建news-item.vue文件
按照vue的规范分别在componet文件夹下新建my-banner.vue
、my-title.vue
·my-nav.vue
、news-item.vue
四个文件。数据库
//src/component/my-banner.vue <template> <div class="banner-box"> <slider class="slider" :style="{'height':height,'width':width}" interval="1500" @change="onchange"> <div class="frame" :style="{'height':height,'width':width}" v-for="(item,index) in bannerList" :key="index"> <image :style="{'height':height,'width':width}" class="image" resize="cover" :src="item.pic" /> </div> <indicator class="indicator"></indicator> </slider> </div> </template>
这里用到了weex官方的slider
和indicator
组件,具体的属性用法参见weex文档slider用法。考虑到轮播图的尺寸不固定,在组件中暴露height(图片高度)
和width(图片宽度)
两个属性提供给父组件传入。
在此注意几个问题: 1.注意图片标签的写法与web中使用vue稍有不一样,web中是img,在weex中用image; 2.weex中不支持padding、margin、border属性值的简写,如不支持padding:10px 和border:1px solid #dcdcdc这样的写法。
//component/my-title.vue <template> <div class="about-title"> <text class="title-text">{{title}}</text> <div v-if="url!=null&&url!=''" @click="goto(url)" class="more"> <text>更多</text> <image src="http://hurely.u.qiniudn.com/20180601152782173548498.png" class="form-icon-r"/> </div> </div> </template>
样式方面没什么好说的,考虑到有些标题是没有跳转更多的,须要作一下判断为空的状况。
在此注意几个问题: 1.注意在weex中文字须要使用text标签,考虑到后续可能会移植为web或者小程序, text标签最好用class来控制样式; 2.weex默认支持flex布局,考虑到后续可能会移植为web或者小程序,在须要 用到flex布局的地方写上display:flex属性。
//componet/my-nav.vue <template> <div class="nav"> <div class="nav-item" @click="goto(item.url)" v-for="(item,index) in navList" :key="index"> <image class="nav-icon" :style="{'width':width,'height':height}" :src="item.src" /> <text class="nav-text">{{item.text}}</text> </div> </div> </template>
样式方面没什么说的,考虑到会跳转不一样的页面,注意在跳转方法里作判断便可。
//componet/news-item.vue <template> <div v-if="type==1"> <div class="item-box" @click="click"> <div class="item-left"> <text class="left-text">{{item.title}}</text> <div class="left-line"></div> <text class="left-time">{{item.pubdate}}</text> </div> <div class="item-right"> <image :src="item.pic.src" mode="aspectFill" class="litpic" /> </div> </div> </div> <div class="item-box2" v-else-if="type==2" @click="click"> <image :src="item.pic.src" mode="aspectFill" class="litpic2" /> <text class="box2-text">{{item.title}}</text> </div> </template>
能够看到我标记4的地方有两处,在组件里加一个type
做为判断便可,列表点击事件经过this.$emit
传递到父组件调用。至此首页四个公共组件封装完毕,下面开始编写首页代码。
//busi/home.vue <template> <div class="app"> <scroller> <banner-item :bannerList=bannerList></banner-item> <div class="home-nav border"> <title-item title="热门栏目" url=""></title-item> <div class="nav-items"> <div class="nav-item" v-for="(item,index) in navList" :key="index" @click="goto(item.url)"> <image mode="aspectFit" :src="item.pic" class="nav-icon"/> <text class="nav-text">{{item.title}}</text> </div> </div> </div> <div class="home-news border"> <title-item title="热门文章" url="../news/list"></title-item> <div v-for="(item,index) in newsItems" :key="index"> <homenews-item type=1 @click="gotonews(item.id)" :item="item" ></homenews-item> </div> </div> <title-item title="热门专辑" more="../video/index"></title-item> <div class="hot-box"> <video-item v-for="(ite,index) in videoitems" :key="index" @click="gotovideo(ite)" :item="ite" type=2 ></video-item> </div> <support-item></support-item> </scroller> </div> </template>
样式方面无需说明,这里说一下数据请求的封装。分别在busi/util文件夹新建文件request.js
和api.js
(非必须),其中request.js基于fly库封装(考虑到weex官方的数据请求库有点坑,在此弃用),便于管理后端接口建议在api.js
文件中统一管理。
如下为fly.js
库的封装,具体使用参照fly.js
官方文档,若是须要增长登陆拦截什么的,能够在fly.interceptors.request.use
中增长便可。
//request.js var Fly = require("flyio/dist/npm/weex"); var fly = new Fly; //bmob云数据库的配置,非必须 const bmobConfig = { applicationId:'applicationId', restApiKey:'restApiKey', secretKey:'secretKey', masterKey:'masterKey' } var progress = weex.requireModule("progress") var modal = weex.requireModule("modal") //添加请求拦截器 fly.interceptors.request.use((request)=>{ progress.show(); //给全部请求添加自定义header request.headers["X-Tag"]="flyio"; request.headers['X-Bmob-Application-Id'] = bmobConfig.applicationId; request.headers['X-Bmob-REST-API-Key'] = bmobConfig.restApiKey; request.headers['Content-Type'] = 'application/json'; //能够显式返回request, 也能够不返回,没有返回值时拦截器中默认返回request return request; }) //添加响应拦截器,响应拦截器会在then/catch处理以前执行 fly.interceptors.response.use( (response) => { //只将请求结果的data字段返回 progress.dismiss(); return response.data }, (err) => { //发生网络错误后会走到这里 progress.dismiss(); //return Promise.resolve("ssss") } ) module.exports = fly;
如下为后端接口统一管理文件api.js
/** * @description 请求地址 */ const baseUrl = 'http://baidu.com/'; const urls = { videoList:'videoList', videoContent:'videoContent', amapGetaddress:'amapGetaddress',//高德地图经纬度转地址 home: baseUrl + 'home',//首页 categoryIndex:baseUrl+'categoryIndex',//菜单分类 type=list显示 categoryList:baseUrl+'categoryList',//参数cid经过categoryIndex得到 page为分页 tagList:baseUrl+'tagList',//标签列表&id=7656&page=1 articleDetails:baseUrl+'articleDetails',//文章详情 about:'about',//关于 search:baseUrl+'search',//&q=周杰伦&page=1 }; export default urls
数据请求实例,用过axios库的应该很熟悉这种写法
getData() { const that = this; fly.get(apis.home, {}) .then(res => { let bannerList = []; JSON.parse(res).article_hot.data.map((item,index)=>{ item.pic = item.pic.src; bannerList.push(item) }) that.bannerList = bannerList; that.newsItems = JSON.parse(res).article_list; }) .catch(error => {}); }
基于同一套ui开发出来的爱尚吉他微信小程序版已经上线喜欢弹吉他的小伙伴能够关注一波