weex入门实践(前端视角)

转载 2017年01月03日 16:28:00

https://segmentfault.com/a/1190000007844330#articleHeader3

功能介绍

如上图所示,本次weex实践将订单展示页面进行了weex化,这个界面交互简单,用weex完全可以实现,同时也使用了weex提供的大部分基础能力。包括三端共同实现component<a>、moduleshopBase、抽离we文件组件、a链接跳转、list组件使用、开发以及三端调试等。

源码管理以及web拓展

在weex里我们谈到组件component以及模块module跟一般的前端框架谈论的组件不太一样。比如在vue中我们会把一些比较通用的UI抽离出来单独引用,我们把这些抽离出来的逻辑UI对象称为组件component。但是weex需要保证三端一致,三端共同实现的公共逻辑UI我们称之为组件。为了保证三端一致,一样的效果需要在三端各自实现一个版本,然后通过weex提供的能力将组件各自注册进各自的sdk中。我姑且称这种类型的组件为下层组件(自创)

三端一同实现并且注册好下层组件之后,上层的.we中就能抽离不同的下层组件组合成新的组件进行复用,姑且称这类组件为上层组件。官方提供的上层组件

weex官方已经封装实现了大部分实用的下层组件,比如image/input/text等,但在业务中我们会需要定制一些component和module,在本次实践中,我们配合webpack单独管理weex源码weex-html5以及定制的component和module。

weex-extend目录

[weex-extend]
  | -- .babelrc
  | -- .eslintrc
  | -- .gitignore
  | -- LICENSE
  | -- README.md
  | -- [bin]
  |     | -- dist-browser.sh
  | -- [demo]
  |     | -- [build]
  |     |     | -- index.js
  |     |     | -- test.js
  |     | -- demo.png
  |     | -- index.we
  | -- [dist]
  |     | -- weex.js
  |     | -- weex.min.js
  | -- index.html
  | -- package.json
  | -- postcss.config.js
  | -- [src]
  |     | -- [components]
  |     |     | -- [a]
  |     |     |     | -- a.js
  |     | -- main.js
  |     | -- [modules]
  |     |     | -- [shop-base]
  |     |     |     | -- README.md
  |     |     |     | -- index.js
  |     |     |     | -- package.json
  |     |     |     | -- style.less
  |     |     | -- [shop-modal]
  |     |     |     | -- index.js
  |     |     |     | -- style.less
  | -- webpack.config.js
  | -- webpack.transform.config.js

其中main.js为主入口文件,用来注册components和modules。

// import the original weex-html5.
import weex from 'weex-html5'

import shopBase from './modules/shop-base/index.js';
import a from './components/a/a.js';
import shopModal from './modules/shop-modal/index.js';
// install the component.

// base module

weex.install(shopBase)

weex.install(a)

weex.install(shopModal)

[demo]在此处的作用是测试编写的component和module

在这个项目中就可以更新管理官方提供的weex-html5和定制的component。webpack打包生成的[dist]文件夹中weex.js和weex.min.js分别用在测试环境和生产环境。

注意0.4.1版本的weex-html5不包含<a>组件,需要手动注册一下。

三端<a>组件跳转约定

在官方提供的playground-demo中打开一个新页面提供了navigation模块的push方法,但是打开页面的url做了诸多判断,目的在于根据平台的不同对url设置不同的值,在H5端url对应的是页面地址,在native端则是weex页面对应的jsbundle文件。

如果在实际业务中也这样处理是不妥的,我们的方案是在.we文件中全部使用<a>组件,且<a>组件中的href的值都统一写成前端熟悉的页面地址。比如http://m.showjoy.com。对于前端而言,<a>组件的逻辑就是在页面中生成一个a链接,点击跳转相应页面。而在native端,要运行weex是要执行对应的jsbundle文件的,所以在native端需要通过在线参数的方式维护一份配置文件。

[
   {

       "page":"order",

       "url":"https://xxx/order.js",

       "md5":"323827382huwhdjshdjs",

       "h5":"http://order.html"

       "v":"1.5.0"

    },
    {

       "page":"detail",

       "url":"https://xxx/detail.js",

       "md5":"323827382huwhdjshdjs",

       "h5":"http://detail.html"

       "v":"1.5.0"
    }
]

当在native的页面中请求到order.html页面时,native会检查本地是否有对应的jsbundle文件,有则使用,否则从json中对应的线上地址下载再进行渲染。

这样处理的好处显而易见,在编写业务代码的时候对于请求的新页面的书写方式与传统前端开发无异,另外在native维护这样一份数据还可以进行jsbundle热更新以及提前下载的作用。

测试环境与线上环境不同

在传统前端H5环境下不管a链接跳转还是api异步请求,我们一般都会用相对地址,浏览器会自动添加主域名信息,比如<a href="/shop/commission"></a>,最终的访问路径会是http://xxx.com/shop/commission或者测试环境下的http://xxx.net/shop/commission。但是在native中原生是没有这样的能力的。所以在编写业务时需要编写完整的地址。<a href="http://xxx.com/shop/commission"></a>

开始我们的设想方案是在三端共同实现一个isOnline的module方法,前端在编写代码的时候根据这个方法返回的值动态设置com或者net,以此区分测试环境还是生产环境。

created: function () {
    let self = this;
    // shopBase 为定制的module
    shopBase.isOnline(function (json) {
        if (json.result) {
            self.suffix = '.com'
        }
    })
}

//template
<a href="http://xxx{{suffix}}/shop/commission"></a>

这样是能完成需求的,但是在回调中得到想要的值总是会遇到不爽的地方,而且这样不好维护,每个页面都要有这样的逻辑,后来通过native端的配合,在native端也实现了填写相对地址就能访问对应地址的能力,完美的解决了这个问题。

自定义弹框

项目初期我们根据weex官网推荐的方式抽离成上层组件如何实现一个模态框,但是在部分低端安卓机上native的弹框表现比较糟糕,点击按钮需要等待大约0.7s左右弹框才会出现,用户等待感知时间太长。这是其一,其二是类似modal这样高频使用场景都要在页面中引入一个component太过麻烦。

// template

<confirm message="{{confirmObj.message}}" visibility={{confirmObj.visibility}} param-obj={{confirmObj.paramObj}}></confirm>

所以我们尝试使用module进行弹框的编写,三端各自实现一遍弹框。在之前提到的管理源码的项目里添加一个shop-modal项目,按照module教程编写好弹框逻辑,最后注册到weex-html5中即可。

'use strict'
import modal from 'modals'

// 因为是webpack参与构建,任何资源包括css都可以在此引用
require('./style.less');


const shopModal = {

  
  confirm: function (options, callbackId) {
    const sender = this.sender
    let cancelTitle = options.cancelTitle || '取消';
    let okTitle = options.okTitle || '确定';
    let message = options.message || '标题';
    
    // test
    
  },

  
  toast: function (options) {
    modal.toast(options.message, options.duration)
  }

}

const meta = {
  shopModal: [{
    name: 'confirm',
    args: ['object', 'function']
  }, {
    name: 'toast',
    args: ['object']
  }]
}

export default {
  init: function (Weex) {
    Weex.registerApiModule('shopModal', shopModal, meta)
  }
}

tab切换

官方抽离出了相应的tab切换组件wxc-tabbar,但在H5端这个组件的表现形式与需求并不太符合,wxc-tabbar组件点击不同的tab,并不会重新刷新页面,而是在当前页面又实例化了一个weex对象,对于我们的业务场景来说,如果点击了第二个tab,在第二个tab中点击了一个a链接,返回后又会重新进入到第一个tab的界面。

我们想要的效果是点击两个tab,在H5端的展现形式跟点击两个a链接跳转一样,而在native端来回点击两个tab,不会重复渲染页面。针对这种业务场景,三端协定在基础module中实现一个loadUrl方法,H5端的实现方法就是跳转一个urlwindow.location.href = xxx,native端的逻辑在native端自行实现。

H5端获取服务端同步渲染的数据

因为历史原因,这个订单管理页面需要用到服务端同步渲染的一个数据字段,但是在weex中无法取到真实dom,即使通过在weex中手动判断web环境,也取不到document.querySelector方法。

console.log(document.querySelector) // undefined
window.weex.init({
    jsonpCallback: JSONP_CALLBACK_NAME,
    appId: location.href,
    loader: loader,
    source: page,
    rootId: 'weex',
    // downgrade: ['root']  // 'root', 'list', 'scroller'
  })

在初始化weex实例的传参中也没有找到可以手动传入数据的入口,所以这里暂时的解决方案是在三端协议的基础moduleshopBase中实现一个getElement方法,这样就可以在we文件中取到web环境中的真实dom。

getElement: function (hook, callbackId) {
    const sender = this.sender;
    var el = document.querySelector(hook);
    sender.performCallback(callbackId, {
      el: el
    })
},

we文件中

shopBase.getElement('.j_IsOpenShop', function (json) {
    if (json.el.value === 'true') {
      self.isVisitor = false;
    }
    cb();
  })

html中的同步数据

<input type="hidden" value="{{type}}" class="j_IsOpenShop">

native调试

weex官方提供了weex-devtool,其中weex bebug xx.we 命令可以将we文件编译成bundle并开启调试,这里要注意的是此处的编译是官方提供的,而很多情况下我们需要自己自定义webpack的编译方式,所以此处调试可以直接使用编译完的bundle文件。weex debug xx.js。若想在自己的app中调试weex页面,需要在ios和andriod app内编写相关代码,提供调试的支持。ios集成调试



jsonp的原理,应用场景,优缺点

在开发测试中,难免会在不同域下进行跨域操作,出于安全性考虑,浏览器中的同源策略阻止从一个域上加载的脚本获取或者操作另一个域下的文档属性,这时需要进行跨域的方式进行解决,如:使用jsonp ,ifram...
  • jian_xi
  • jian_xi
  • 2017年03月26日 13:21
  • 1880

WEEX|简单界面的实现与页面跳转

在了解了初始化工程后,我们开始实现简单界面的搭建与页面跳转
  • zpfvs1
  • zpfvs1
  • 2016年11月14日 15:57
  • 1625

Weex入门与进阶指南

原文地址:https://yq.aliyun.com/articles/57554前言相比较于React Native的“Learn once, write anywhere”,Weex的口号是“Wr...

给初学者的weex教程(一)

前言 随着阿里开源的构建高性能、可扩展的原生应用跨平台开发方案--weex的发布,相信很多人都涌向了这股浪潮中,我也是从RN中抽了一腿出来踏进了这个“坑”中。随着阿里勤奋的开发人员和我们不断踏坑...

Weex快速入门指南

背景: 由于公司项目需要,需求变化频繁,计划总改不上变化,由于app更新版本周期长,不能很好应对这种变化,正在此前提下热修复和热更新技术也有了发展的空间,不管热修复还是热更新,都是对app内容或...

Weex入门教程之1,了解Weex

用意主要是介绍Weex,并未涉及开发方面,好让我们开始开发之前充分地了解Weex到底是个什么。 以下描述主要摘取于: http://mp.weixin.qq.com/mp/homepage?_...

weex项目实战篇(一)

1. 前言通过前面四篇文章的介绍,相信大家对weex基本熟悉了,下面就开始动手做项目,一些细节问题,在项目实战中继续消化。2.开发工具和环境俗话说,工欲善其事必先利器,我选的IDE开发工具为webst...

weex项目实战

weex开源以来,有不少人关注,一起体验weex的三端统一的乐趣吧。写了个简约但完整的weex小案例,仅供参考。需要android顶尖学习资料和VIP视频的可以加我Q:291902259...
  • dzsw0117
  • dzsw0117
  • 2016年07月05日 16:10
  • 11804

weex项目实战篇(二)

1. 前言经常前面的准备,我们终于可以开始上手weex项目了。2.新建weex项目1)新建一个名为hongkong的项目,如图所示: 2 ) 输入项目名称 3)点击【create】则项目则创建成功...

weex服务项目搭建

1. 前言前面介绍了app本地调用js的方式(js文件放在assert目录下面),其实大部分都是调用远程js,本篇介绍app如何调用远程js文件。2.服务项目搭建步骤前提需要安装好weex环境,具体参...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:weex入门实践(前端视角)
举报原因:
原因补充:

(最多只允许输入30个字)