开发

整个开发体验力求接近web开发,因此保留了和vue官方项目相同的项目结构
也许你并不需要支持web端,那为啥还要按web的习惯来调,因为浏览器的调试工具远比weex devtool好用

路由

src/router.js为路由文件,暂不支持多个路由文件
写法和web版vue的完全一致,不过不支持name只支持path
router.js中的/entry请不要删除,redirect也请不要改变,要想改变首页地址请参考下一节

设置首页

首先介绍下src/entry.vue
此页面加载时页面会被启动图覆盖,因此这个不是真正的首页
你应该新建一个真正的首页,例如登录页,然后再entry.vue的onLoad事件中写跳转逻辑,跳转到真正的首页
这样给人的感觉就是,从启动图直接到达了真正的首页

内置对象

一共有6个内置对象,掌握它们90%的业务需求都可以搞定了

此对象用于控制导航
主要功能

1.页面跳转

/**
   * @param url 目标页面地址,在router中定义的path(必传)
   * @param type (动画方式:'push'(默认,从右往左的动画),'present' (从底部弹出的动画) )(非必传)
   * @param param (传到下一页面的参数)(非必传)
   * @param animate (是否有动画效果(暂时没有实现无动画的效果))(非必传)
   * @param callback (如果下一页面带回了参数,可以在这个回调中接受到)(非必传)
   * @param preload (是否启用预加载,默认:true)(非必传)
   */
  this.$navigator.push({url:'/index',type:'push',param:{name:'111'},animate:true,preload:true},(res)=>{
       //下一个页面回来时触发
   })) 

2.页面返回

/**
    *
    * @param param (回调给上一个页面callback的参数,无参数回传可不传)(非必传)
    * @param pageId (跨越页面回到指定pageId的页面,实现夸页面返回)(非必传)
    * @param animate (是否有动画效果(暂时没有实现无动画的效果))(非必传)
    * @param type type (如果push方法type传present,那么这里一定要传dismiss,其它时候可以不传)(非必传)
    */
   this.$navigator.back({param:{name:11},pageId:'111',animate:true,'pop'})

3.获取上一个页面传来的参数

let param=this.$navigator.param()

4.设置页面id(跨页面返回时要用)

 this.$navigator.setPageId('pageA')
  在后面的页面中像这样直接返回到A
 this.$navigator.back({pageId:'pageA'})

$http(网络请求)

http请求

   /**
     * http 请求的方法,包含post,get,json三种
     * @param url 地址
     * @param param 参数
     * @param method 方法(post,get,json)
     * @param header 请求头
     * @param start  请求开始事件
     * @param success 请求成功事件
     * @param compelete 请求完成事件
     * @param exception 请求异常事件
     */
    let p={}
    p.url='http:xxx/login.do'
    p.param={name:'',pass:''}
    p.method='post'
    p.header={token:'xxxx'}
    p.start=()=>{
    //请求开始,可以在这展示loading框
    }
    p.compelete=()=>{
    //请求结束,可以在这隐藏loading框
    }
    p.exception=()=>{
    //请求异常,可以在做异常处理
    }
    this.$http.fetch(p,(res)=>{
     //请求成功
    })

文件上传

/**
     *  上传文件,web中无法使用
     * @param url 上传地址
     * @param param  //非文件类的参数
     * @param header //请求头
     * @param path  //文件的磁盘地址,sdcard:打头的路径,拍照或者从相册选择后都会返回
     * @param start //请求开始事件
     * @param success 请求成功事件
     * @param compelete 请求完成事件
     * @param exception  请请求异常事件
     */
    let p={}
    p.url='http:xxx/upload.do'
    p.param={name:'',pass:''}
    p.path={file1:'xxxx.png',file2:'xxxx.png'}
    p.method='post'
    p.header={token:'xxxx'}
    this.$http.upload(p,(res)=>{
     
    })

$sessionStorage(内存存储)

将键值对存在内存中,app关闭后或者网站关闭后自动清除

let value=''//可以是任意类型,存进去是什么类型,取出来就是什么类型无需转换
this.$sessionStorage.set('key1',value)
let v= this.$sessionStorage.get('key1')
//清除键值对
this.$sessionStorage.remove('key1')

$localStorage(磁盘存储)

let value=''//可以是任意类型,存进去是什么类型,取出来就是什么类型无需转换
this.$localStorage.set('key1',value)
let v= this.$localStorage.get('key1')
//清除键值对
this.$localStorage.remove('key1')

$eventBus(跨页面通信)

此模块用于跨页面通信,在A页面注册这样一个事件,在其它任何页面均可触发,例如登录之后,触发相关页面的数据刷新

//  注册
this.$eventBus.regist('key1',(params)=>{
      //do something
})
// 触发
this.$eventBus.send('key1',{name:'123'})
     

$photo(相机相册)

相机相册最常用的一个原生模块,用于获取照片,视频,从相册选或者用相机拍

 /**
     *
     * @param action:camera 相机 ;choose:相册
     * @param type:video 视频 ;photo:图片
     * @param aspX:裁剪宽度(非必传)
     * @param aspY:裁剪高度 (非必传)
     * @param maxSize:压缩大小,单位byte
     * @param callback 回调
     */
    let p={}
    // p.action='choose' //相册
    p.action='camera' //相机
    p.type='photo'
  
    //这两个值不传则不会出现裁剪框
    p.aspX=500 
    p.aspY=500

    p.maxSize=1023*1024 //单位byte
    this.$photo.open(p,(res)=>{
         let ary=res.res
          ary.forEach((item)=>{
              let path=  item.path //图片路径
          })
    })

生命周期

onLoad

页面加载完成时触发,只会触发一次
该方法有一个参数 ,是从上一个页面传递过来的参数

onShow

页面重新显示时触发,例如从A跳转到B,在从B回到A,这时会触发A页面的onShow

onHide

页面离开时触发,例如从A跳转到B,这时会触发A页面的onHide

onUnload

页面销毁前触发,请勿执行耗时的操作

<template>
    <page title="页面的生命周期">
    </page>
</template>

<script>
    export default {
        props: {},
        data() {
            return {}
        },
        methods: {
            onLoad(param) {
               //页面加载完成时触发,只会触发一次
               //param 是从上一个页面传递过来的参数
            },
            onShow() {
               //页面重新显示时触发,例如从A到B,在从B回到A,这时会触发A页面的onShow
            },
            onHide() {
                //页面离开时触发
            },
            onUnload() {
                //页面销毁前触发,请勿执行耗时的操作
            }
        },
        created() {

        }
    }
</script>

<style scoped>

</style>

资源访问

请将所有的资源放在assets文件中
默认已有图片img,字体font和文件file的分类
所有assets中的资源均可通过root:写法访问到

图片使用

<image src="root:img/log.png"></image>

字体使用

注册字体

const font = weex.requireModule('font')
font.addFont('nj','root:font/iconfont.ttf')

其它文件类的访问

以web访问本地静态文件为例

<web src="root:file/index.html"></web>

appBoard(全局引入)

weex官方没有提供这样的机制,着实不方便 src/mixin/main.js在此js全局注册组件,全局对象
可以避免所有页面都要单独注册组件的繁琐,也能减少总的js包体积 例如一个button组件有100kb,原来有100个页面都注册了,那么总体积是100x100=10000kb 现在放在appBoard中注册,仅需注册一次,体积减少99x100=9900kb

需要注意的是,以上是针对将包放在本地的情况,如果将js部署在服务端,那么js的总体积将不再重要
反而单个js的体积要越小越好,如果什么都往appboard中注册,则会造成将很多非本页面的代码也打进了这个页面,造成单个页面js过大

所以针对部署情况,需要按以下标准来

  • 部署在服务端,则页面按需引用注册组件
  • 部署在app内部,则将尽可能多的组件在appBoard中注册

WEEXPLUS-UI

weexplus已经为大家内置了一套三端适配的vue组件
创建项目已自带了一套tab模板,方便大家快速开发
以下组件均在src/component下面,大家可以自行改造
并且已在src/mixin/main.js中全局注册,无需每个页面再单独注册

已适配刘海屏

<template>
   <div style="flex: 1;width: 750px">
       <head   title="标题" :hasBackBtn="true" ></head>
       <div style="flex: 1;display: flex;width: 750px">
           
       </div>
   </div>
</template>

<script>

    export default {
        component:{},
        props: {
            
        },
        data() {
            return {}
        },
        methods: {

        },
        created() {

        }
    }
</script>

<style scoped>

</style>

<page>

建议将所有的页面用page做根元素

<template>
    <page title="首页"  :hasBackBtn="false">
        <div class="layout" >
            <image  class="img"   src="root:img/logo.png" ></image>
            <text class="text">欢迎使用weexplus!</text>
        </div>
    </page>

</template>
<script>
    export default{
        data(){
            return {

            }
        },
        props: {},
        methods: {
            onLoad(px){
                //页面加载完成
            },
            onShow(){
                //页面展示
            },
            onUnload(){
                //页面卸载

            },
            onHide(){
                //页面隐藏
            },

        },
        created(){

        }
    }
</script>
<style scoped>
    .layout{
        align-items: center;
        background-color: #ffffff;
        justify-content: center;
        flex: 1;
    }
    .img{
        width: 200px;
        height: 200px;
        margin-top: -100px;

    }
    .text{
        color: black;
        margin-top: 30px;
        font-size: 70px;
        font-weight: bold;
    }
</style>

<tabHost>

最佳的tab组件实践

<template>
    <tabHost :items="items">
    </tabHost>
</template>
<script>
    export default {
        props: {},
        data() {
            return {
                items: [
                    {text: '首页', normalImg: '&#xe970;', selectImg: '&#xe971;',component:require('./tab/tab1.vue')},
                    {text: '新闻', normalImg: '&#xe97e;', selectImg: '&#xe980;',component:require('./tab/tab2.vue')},
                    {text: '我的', normalImg: '&#xe973;', selectImg: '&#xe987;',component:require('./tab/tab3.vue')},
                ],
                index: 0
            }
        },
        methods: {

            onLoad(param) {

            },
            onShow() {

            },
            onHide() {

            },
            onUnload() {

            },
            registFont(){
                const font = weex.requireModule('font')
                font.addFont('nj','root:font/iconfont.ttf')
            }
        },
        mounted(){
            // this.$refs.host.components={tab1,tab2,tab3}

            // debugger

            // this.log(JSON.stringify(this.components))
        },
        created() {
            this.registFont()
        }
    }
</script>

<style scoped>
    .full {
        position: absolute;
        top: 0;
        bottom: 0;
        right: 0;
        left: 0;
        width: 750px;
    }
</style>