weex_weex旋转动画 - CSDN
  • Weex 简介

    2020-06-18 21:08:48
    最近项目在改造,尝试使用weex代替原有的H5 和原生页面,提高系统运行效率。期间遇到了很多坑,后面会仔细讲讲,先来看下weex的基本信息。 一、什么是weex "weex是一个可以使用现代化的 Web 技术开发高性能原生...

    最近项目在改造,尝试使用Weex代替原有的H5 和原生页面,提高系统运行效率。期间遇到了很多坑,后面会仔细讲讲,先来看下Weex的基本信息。

    一、什么是weex

    "Weex是一个可以使用现代化的 Web 技术开发高性能原生应用的框架",这是Weex官网对其的一句很简介明了的定义。Weex是一个可以利用web 前端开发技术来实现Android/ios 原生引用的框架,使用 Vue 作为上层框架,并遵循 W3C 标准实现了统一的 JSEngine 和 DOM API。

    二、整体架构

    本地开发的web 页面,构建形成 Weex 的一个 JS bundle(native);在云端,开发者可以把生成的 JS bundle 部署上去,然后通过网络请求或预下发的方式传递到用户的移动应用客户端;在移动应用客户端里,WeexSDK 会准备好一个 JavaScript 引擎,并且在用户打开一个 Weex 页面时执行相应的 JS bundle,并在执行过程中产生各种命令发送到 native 端进行的界面渲染或数据存储、网络通信、调用设备功能、用户交互响应等移动应用的场景实践。

    1、Weex 的 iOS 和 Android 客户端中都会运行一个 JavaScript 引擎,来执行 JS bundle。

    2、Weex向各端的渲染层发送规范化的指令,调度客户端的native渲染和其它各种能力。

    3、我们在 iOS 下选择了 JavaScriptCore 内核,而在 Android 下选择了 UC 提供的 v8 内核。

    原理:
    1、将XML+CSS+JavaScript代码转换为JSBundle
    2、JSBundle传给JS Framework解析为Json格式的Virtual DOM
    3、客户端通过接收Virtual DOM渲染界面

     

     

    三、技术特点

    1、一次实现,多端适用

        使用Weex框架+ web开发语言和开发经验开发应用,可构建 Android、iOS 和 Web 应用三端统一的应用。

    2、支持的前端框架

        Weex并不强依赖在特定的框架上使用,但官方推荐使用的是vue.jsRax 前端框架,这俩种框架也是Weex 目前功能最全、最稳定的方案。在 WeexSDK v0.10.0 (发布于 2016 年 2 月 17 日)以及后续的版本中,集成了 v2 版本的 Vue.js。

     

    Vue 和 Rax

    •  Vue.js 是一个不断进化中的前端框架。
    • Rax 是提供类 React 语法和兼容性的前端框架。

    3、调试工具

    •  官方推荐使用Playground 来调试,预览weex页面,在 Playground 里,你可以打开各种示例。
    •  访问 Weex online playground. 在这个网站上,你可以浏览、修改、新建各种基于 Vue.js 的单页面例子,并用 WeexPlayground 应用扫码查看实时效果。
    • 同时weex 也提供了weex debug ,需要APP集成 weex sdk。weex debug 启动步骤如下:

           1、执行 weex debug 指令;   执行成功后会提示访问URL、端口等。   

        2、访问URL,会有一个debug 二维码

        3、使用继承了weex sdk 的APP引用扫码,链接APP和网页,就可以在调试网页。

       4、weex debug 支持对单个文件进行调试, 通过 weex debug [folder | file]  命令进行编译。

     

    四、weex和 web的平台差异

        虽然使用weex框架可以实现web , android 、ios 三端统一,但是它与纯web 开发有几点很明显的区别。

    1、weex环境中没有 DOM    

         weex的运行环境以原生应用为主,在 Android 和 iOS 环境中渲染出来的是原生的组件,不是 DOM Element。

    • 不支持 DOM 操作

        原生环境中不支持 Web API,没有 Element 、Event 、File 等对象。不支持选中元素,如 document.getElementById 、 document.querySelector 等;当然也不支持基于 DOM API 的程序库(如 jQuery)。

    • 有限的事件类型

        Weex支持在标签上绑定事件,和在浏览器中的写法一样,但是Weex 中的事件是由原生组件捕获并触发的,行为和浏览器中有所不同,事件中的属性也和 Web 中有差异。支持 Web 中的事件类型,详情请参考《通用事件》。同时,不区分事件的捕获阶段和冒泡阶段,相当于 DOM 0 级事件。

     2、Weex环境中没有BOM

         BOM(Browser Object Model),即浏览器对象模型,是浏览器环境为 javascript 提供的接口。Weex 在原生端并不基于浏览器运行,不支持浏览器提供的 BOM 接口。

    • 没有 window 、screen 对象

         因为没有BOM ,所以不支持供浏览器中的window, screen对象,获取设备的屏幕或环境信息,可以使用 WXEnvironment 变量。

    WXEnvironment 备注
    weexVersion WeexSDK 的版本
    appName 应用的名称
    appVersion 应用的版本
    platform 运行平台,可能的值是 Web 、Android 、iOS 之一
    osName 系统的名称
    osVersion 系统版本
    deviceWidth 设备宽度
    deviceHeight 设备高度
      // 获取屏幕高度
      this.scrollHeight = (750 / weex.config.env.deviceWidth * weex.config.env.deviceHeight-140) ; 
    • 没有doucment 对象

        在浏览器中 document 表示了当前活动的文档模型,在 Android 和 iOS 环境中并没有这个对象,也不支持与其相关的 DOM 操作

    • 没有location,history,navigator 对象

        Weex 也提供了 navigator 模块来操作页面的跳转,使用方法参考《navigator 导航控制

    3、能够调用移动设备原生 API

        Weex 提供了clipboard navigator storage等模块来调用移动设备原生 API。同时,提供了横向扩展的能力,可以扩展原生模块,具体的扩展方法请参考《iOS 扩展》 和《Android 扩展

     

    参考资料

    weex 官网

    展开全文
  • Weex 入门这一篇就够了

    万次阅读 多人点赞 2018-03-10 11:06:09
    一:Vue.js 了解 Vue.js 环境配置 (1) 安装 nodejs (2) 安装 webpack : npm install webpack -g (3)安装 vue-cli 脚手架:npm install vue-cli -g ...(1)vue init webpack vue-hello ( vue-hello 为项目...

    一:Vue.js 了解

    Vue.js 环境配置

    (1) 安装 nodejs

    (2) 安装 webpack : npm install webpack -g

    (3)安装 vue-cli 脚手架:npm install vue-cli -g

    Vue.js 项目创建

    (1)vue init webpack vue-hello ( vue-hello 为项目名称 )

    (2)cd vue-hello

    (3)npm install

    (4)npm run dev 或 npm start

    这里写图片描述

    Vuejs 项目结构

    这里写图片描述

    二:Weex 入门

    Weex 环境配置

    (1)全局安装 weex-toolkit : npm install weex-toolkit -g

    (2)将 weex 安装路径配置至系统环境变量中: C:\Program Files\nodejs\node_cache

    ​ weex - v,显示版本表示安装成功:

    C:\Users\jiuya>weex -v
       v1.2.9
     - weexpack : v1.1.5
     - weex-builder : v0.3.14
     - weex-previewer : v1.4.6

    这里写图片描述

    Weex 创建项目

    (1) 创建 weex 空项目:weex create weex-custom-extends ( weex-custom-extends 为项目名称)

    (2) 进入到项目根目录: cd weex-custom-extends

    (3) 安装依赖的第三方 js 包:npm install

    (4) 启动本地 web 服务,浏览器预览渲染效果:npm start

    这里写图片描述

    (5) 添加 Android 或 iOS 平台:weex platform add android 或 weex platform add ios

    这里写图片描述

    (6)运行:weex run android

    这里写图片描述
    这里写图片描述

    Weex debug 调试

    (1) 命令: weex debug ,浏览器自动打开待调试的页面。

    这里写图片描述

    这里写图片描述

    (2) 使用 weex playground app 扫描二维码,扫描成功后,浏览器自动跳转到下面页面,点击下图框中的二维码,并使用 weex playground app 扫描,即可开始调试待 debug 的页面。

    这里写图片描述

    (3) 扫描框中二位码成功后,即看到下面页面。

    debug app success

    Weex 扩展

    module 扩展

    (1) Android Studio 创建 Android Project ,并添加相关依赖

    (2) 新建 PhoneInfoModule.java , 集成自 WxModule

    
    public class PhoneInfoModule extends WXModule {
    
        /**
        * 获取 Phone 相关信息,并回调给 weex
        */
        @JSMethod(uiThread = false)
        public void getPhoneInfo(JSCallback callback) {   // JSCallback 为 WeexSDK 中的 API
            Map<String, String> infos = new HashMap<>();
            infos.put("board", Build.BOARD);
            infos.put("brand", Build.BRAND);
            infos.put("device", Build.DEVICE);
            infos.put("model", Build.MODEL);
            callback.invoke(infos);
        }
    
        @JSMethod(uiThread = true)
        public void printLog() {
            Toast.makeText(mWXSDKInstance.getContext(), "item clicked", Toast.LENGTH_SHORT).show();
        }
    
    }

    扩展 component

    public class RichText extends WXComponent<TextView> {
    
        public RichText(WXSDKInstance instance, WXDomObject dom, WXVContainer parent) {
            super(instance, dom, parent);
        }
    
        @Override
        protected TextView initComponentHostView(@NonNull Context context) {
            TextView textView = new TextView(context);
            textView.setTextSize(20);
            return textView;
        }
    
        @WXComponentProp(name = "tel")
        public void setTel(String number) {
            SpannableString spannableString = new SpannableString("tel:" + number);
            ImageSpan imageSpan = new ImageSpan(getContext(), R.mipmap.phone);
            spannableString.setSpan(imageSpan, 0, 4, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
            getHostView().setText(spannableString);
        }
    }
    

    (3) 在 Application 中进行注册

    public class WXApplication extends Application {
    
      private static final String TAG = "WXApplication";
    
      @Override
      public void onCreate() {
        super.onCreate();
        InitConfig config = new InitConfig.Builder().setImgAdapter(new ImageAdapter()).build();
        WXSDKEngine.initialize(this, config);
        String packageName = getPackageName();
        Log.d(TAG, "onCreate: packageName  =" + packageName);
        try {
          // 注册扩展 module  
          WXSDKEngine.registerModule("phoneInfo", PhoneInfoModule.class);
          // 注册扩展 component  
          WXSDKEngine.registerComponent("richText", RichText.class, false);
        } catch (WXException e) {
          e.printStackTrace();
        }
      }
    }

    (4) 在 vue 中引用自定义的 module,component

    <template>
        <div class="wrapper">
            <image :src="logo" class="logo" @click="print"/>
            <text class="greeting" @click="getPhoneInfo">The environment is ready!</text>
            <!--扩展component-->
            <richText tel="10086" style="width:200px;height:100px"></richText>
    
            <HelloWorld/>
        </div>
    </template>
    
    <script>
        import HelloWorld from './components/HelloWorld.vue'
    
        const modal = weex.requireModule('modal');
        const phoneInfo = weex.requireModule('phoneInfo');
    
        export default {
            name: 'App',
            components: {
                HelloWorld
            },
            data() {
                return {
                    logo: 'https://gw.alicdn.com/tfs/TB1yopEdgoQMeJjy1XaXXcSsFXa-640-302.png'
                }
            },
            methods: {
                // 调用 PhoneInfoModule 中的 printLog()
                print() {
                    phoneInfo.printLog();
                },
                // 调用 PhoneInfoModule 中的 getPhoneInfo(),并回调给 weex
                getPhoneInfo() {
                    phoneInfo.getPhoneInfo(function (e) {
                        modal.alert({
                            message: JSON.stringify(e),
                            duration: 0.3
                        })
                    });
                }
            }
        }
    </script>
    
    <style scoped>
        .wrapper {
            justify-content: center;
            align-items: center;
        }
    
        .logo {
            width: 424px;
            height: 200px;
        }
    
        .greeting {
            text-align: center;
            margin-top: 70px;
            font-size: 50px;
            color: #41B883;
        }
    
    </style>
    
    

    (5) npm run build 编译 vue ,将生成的 js 拷贝至 Android Studio 的 assets 目录中

    run weex

    运行结果:

    res

    展开全文
  • 先说结论,本人极度非常不推荐weex作为任何商用开发有很多人会说了... 你瞎扯.. 你看别人阿里.. 啊飞猪... 啊那个支付宝... 人家不是用得好好的么...当然这也是我们公司作为技术选型的考量.. 三端通用.. 阿里系的app...

    先说结论,本人极度非常

    不推荐weex作为任何商用开发


    有很多人会说了... 你瞎扯.. 你看别人阿里.. 啊飞猪... 啊那个支付宝... 人家不是用得好好的么...

    当然这也是我们公司作为技术选型的考量.. 三端通用.. 阿里系的app全线在用.. 理论上是可以实现的.. 而且我们在编码过程中.. 可以把IOS工程师,安卓工程师和前端工程师以及部分熟悉一点前端的后端工程师都拉过来贡献一套代码.. 代码质量可以得到保障

    现在想想只能说... 太天真了... 你也不想想人家阿里有多少大牛有多少人在做这个项目.. 再说淘宝都卡成啥样了大家还是愿意用.. 如果你的项目这样卡两下你的app是否还能像淘宝那样拉住顾客??

    这就像你说你想写一篇巨著... 你打算用英文写... 翻译成中文 俄文 日文(ios android web)... 让人看了还能把别人国家的感动得稀里哗啦的.. 本身难度就会不小.. 

    另外你在android中打开布局边界看一下天猫飞猪... 里面weex的界面已经只剩下很少的界面了.. 很多界面已经替换成了原生或者webview的混合界面... 做得那么杂用户体验还过得去.. 我只能说一句.. 阿里牛逼=.= ... 所以很明显的一个信息就是.. 这个技术连他们自己人都不广泛使用了.. 可见还是有很大的局限性的..

    而且随着项目持续增大.. weex项目的编译时间会呈指数型上升.. 这样的编码体验.. 说糟糕都是在侮辱糟糕这个词... 所以也请大家慎重考虑

    如果你们已经决定使用weex.. 或者正准备用它构建三端应用... 那么.. 希望我的踩坑指南可以帮到你.. 从入门到放弃...


    一.开始准备

    搭建开发环境

    首先根据官网的提示安装node.js weex-toolkit  然后就可以开始创建项目了.. 你可以选择RN的rex 或者前端的VUE模式写代码都是可以的.. 但是我们用的是vue.. rex也考虑过.. 只是没人会写RN.. 加上网上weex+RN的例子很少.. 所以就放弃了.. 

    如果是在windows上的话.. 安装的东西都是需要配置环境变量的... 

    D:\nodeJs\npm;D:\nodeJs\node.exe;C:\Users\jupiter\AppData\Roaming\npm;C:\Users\jupiter\AppData\Roaming\npm\node_modules\weex-toolkit\bin\weex.js;C:\Users\jupiter\AppData\Roaming\npm\node_modules\weexpack\bin\weexpack.js;C:\Users\jupiter\AppData\Roaming\npm\node_modules\weex-toolkit\node_modules\weex-previewer\vue-template\template\assets\vue.js


    分享一下我的环境变量里的东西.. node weex npm这些是必须要配置进去的... 如果不配置的都是用不了的.. jupiter是我windows的用户名 其他的大家自己看一下它给安装到什么路径下了.. 尤其是weex和weexpack是默认的一个路径 层级还很深.. 仔细找找配置进去..

    另外推荐个飞猪开源的UI框架 weex-ui 

    weex-ui

    总体来说这个UI框架还是能帮上一些忙的.. 但是里面本身就有些问题.. 比如其中utils中的getPageHeight的高度.. 在web上是对的.. 但是手机上... emmmm... 会少一些高度.. 大约是88px... 原因不明.. 可能是android里面使用的默认的toolbar... 但是他自动帮你减掉了.. 但实际上没有toolbar.. 这个高度就少了..


    二.开始踩坑


    至于如何写vue代码或者简单的helloworld.. 百度上都能查到... 我就不再赘述了.. 这里只说些百度不到的坑或者旧坑解决方法已经无效的问题..  如果你觉得你会写vue到此就万事大吉了要开始构建三端应用了... 那么我得先给你泼一盆冷水了... 大哥.. 你跳个界面给我看下..

    1.界面跳转

    你会说:切 不就跳界面么.. 看我一手startActivi... vi... 

    vi你个头..  

    在这里的跳转需要使用navigator 去实现.. 原理上这个东西是做了各端的特殊处理的.. 在web上比较像vue router.. 也就是单页跳转.. 而在android上则是通过隐式去拦截对应的url类型.. 如果是http和https开头的.. 会用webview去打开.. 如果是files开头的... 呵呵.. 你就发现它没动静了...

    这里再吐槽一手weex不适合商用的原因... 完全没有社区... 这是最骚的... 所以遇到很多问题只能自己去看源码或者百度... 而且百度好多东西都是基于旧版本的.. 你用上就发现.. 写得什么玩意 根本没效果嘛..


    跳转就是我们遇到的第一个大坑.. 百度上都说.. 可以用vue router.. 然后我们试了之后发现.. vue router在移动端上根本不是真的界面跳转.. 只是一个单页面.. 每次都重新加载.. 没有跳转动画.. 这对于app的效果来说是完全不能接受的..

    而另一方面网上说用navigator的实现.. 在跳转本地界面的时候都不生效.. 

    我们编码的地方在src里.. 在使用npm build(npm run 或者weex run android等都会先build)后会生成一套JS文件存在dist里.. 而网上说的只要用navigator打开里面编译生成的js文件就可以实现跳转.. 实际上打开后.. 并不行..

    那么在新版本的weex里要怎么做呢.. 我们试了好久后.. 受到首页的地址是index.html的启发.. 发现使用src对应目录下的vue文件地址把后缀改成html即可实现web跳转... 比如你首页的地址是http://192.168.2.17:8081/index.html... 那么你需要打开components下的home.vue界面  那地址就是 http://192.168.2.17:8081/components/home.html ...
    网页跳转正常了 .. 当我们欢呼雀跃准备继续时.. 发现手机上又跳不了... 

    在项目目录下运行

    weex platform add android

    你的项目就可以用 weex run android运行在安卓手机上了... 

    网上好多说需要找到本地资源文件夹下的地址即可跳转.. 在android中.. 确实发现assets文件夹下有这些界面的js文件.. 


    只要用 file://assets/dist/在安卓中找到这个文件跳转就可以了.. 然后再次发现是无效的.. 但是发现跳转http和https在手机上是有效的.. 那么也就是说隐式调用没有拦截到这file这个请求..


    但是明明在android项目的manifast里是已经在拦截file的.. 最后发现确实file是拦截不到的.. 其他什么关键字都可以.. 那么怎么办呢.. 最后我只能在地址前面加上别的关键字local 但是让隐式拦截local关键字.. 最后再activity里再把local给去掉 用file地址去渲染..


    最终获取三端对应跳转地址的方法 (注意安卓中前面添加了local是为了给拦截)

    getJumpBaseUrl(toUrl) {
    
            var bundleUrl = weex.config.bundleUrl;
    
            var isnav = true
            bundleUrl = new String(bundleUrl);
            var nativeBase;
            var native;
            var isAndroidAssets = bundleUrl.indexOf('file://assets/') >= 0;
            var isiOSAssets = bundleUrl.indexOf('file:///') >= 0 && bundleUrl.indexOf('WeexDemo.app') > 0;
            if (isAndroidAssets) {
                nativeBase = "local://" + 'file://assets/dist/';
                native = nativeBase + toUrl + ".js";
            } else if (isiOSAssets) {
                nativeBase = bundleUrl.substring(0, bundleUrl.lastIndexOf('/') + 1);
                native = nativeBase + toUrl + ".js";
            } else {
                var host = 'localhost:8081';
                var matches = /\/\/([^\/]+?)\//.exec(bundleUrl);
                if (matches && matches.length >= 2) {
                    host = matches[1];
                }
    
                //此处需注意一下,tabbar 用的直接是jsbundle 的路径,但是navigator是直接跳转到新页面上的.
                if (typeof window === 'object') {
                    nativeBase = 'http://' + host + '/';
                } else {
                    nativeBase = 'http://' + host + '/';
                }
    
                native = nativeBase + toUrl + ".html";
            }
            return native;
        }

    android manifest 中拦截local

          <activity
                android:name="com.weex.app.WXPageActivity"
                android:label="@string/app_name"
                android:screenOrientation="portrait"
    			
    			>
                <intent-filter>
                    <action android:name="android.intent.action.VIEW"/>
                    <action android:name="com.alibaba.weex.protocol.openurl"/>
    
                    <category android:name="android.intent.category.DEFAULT"/>
                    <category android:name="com.taobao.android.intent.category.WEEX"/>
    
                    <data android:scheme="http"/>
                    <data android:scheme="https"/>
                    <data android:scheme="local"/>
                </intent-filter>
    
    
    
            </activity>

    android java code中把local头给去掉 拿file地址去渲染


    把local关键字给替换掉.. 然后其他的和原来操作一样

    这样在android上的跳转才算解决了

    如果你看到这个坑就已经准备放弃了.. 我只能说.. 施主 回头是岸.. 如果你觉得还想挑战一下.. 那么继续看后面的坑吧..

    2.控件太少 基本只能实现最基本的效果

    第二个大坑就是控件过于少.. 很多效果在weex中你是没法实现的.. 或者说不是一般人可以实现的... 除非你是真的精通三端的技术大牛.. 不然你要掂量一下自己的项目.. 是不是有地图.. 是不是有其他动画.. 是不是有weex-ui中没有的效果.. 如果有.. 那么是否有替代方案或者对UI的要求高不高..能不能接受替换.. 是否有自己封装控件的经验..


    就算你要自己做.. 还有一个事情你必须知道..

    那就是

    什么意思呢.. 就是说滑动事件获取是不靠谱的.. 甚至在weex-ui的slide-nav(视窗增大)中看到了类似的备注


    之前还考虑过希望封装个类似ios picker的效果... 看到这个之后就放弃了.. 滑动事件的监听都不靠谱的话.. 很多效果就算要自己封装也是不太可能呢..

    3.滚动控件滑不动

    在weex 中提供了好多种滚动控件 包括list scroller 但是一开始使用的时候发现都滑不动... 后来才发现.. 如果不给这些控件指定高度.. 那么它会包裹内容高度.. 那么内容高度和控件高度相同也就不可以滑动了... 控件已经顶出屏幕了你也不知道.. 那么对于这些滚动控件是必须指定高度的... 但是高度怎么拿呢...

    weex的规则是屏幕宽度是750px 而高度是根据宽高比算出来的.. 也就是高度是不固定的.. weex-ui中的utils中有获取屏幕高度的方法.. 但是就是开头提到的问题.. android上回少88px;

    所以只能自己封装个获取高度的方法

    import {Utils} from 'weex-ui'       
    
     const screenHeight = Utils.env.getPageHeight() ;
            const androidNavHeight =  Utils.env.isAndroid() ? 88 : 0;
            return screenHeight +androidNavHeight;

    用这样的方法获取的高度.. 再设置给scroller才可以使用.. 当然如果你的界面里还有其他控件.. 高度还要再减去那些.. 不然scroller会包裹内容高度..

    4.前端代码不是全部可靠的


    在官网上写出了几种不支持的样式, 百分比是不支持的.. 包括我之前用的border 50% 去绘制圆形.. 到app上会变成50px.. 另外用border绘制三角形之类的都是不可靠的.. 在web上可以实现.. 到手机上就雪崩了.. 所以如果你是前端过来的同学.. 不要什么vue的骚操作都往里套.. 它并不是真正意义上的前端代码.. 所以还要对不同系统去调整适配问题... 所以你的团队中最少的需要有三端都懂的人才可以用.. 而不是说你懂前端就闷头写.. 最后web没问题了.. 在android和ios上都运行不起来.. 最后debug都不知道从哪做起... 展开记录一下那些写法是不可以的..

    4.1.dom document对象不可用

    在前端中也许会有类似

             var mo = function(e) {
                e.preventDefault();
             };
             document.body.style.overflow = 'hidden';
             document.addEventListener("touchmove", mo, false); //禁止页面滑动

    的代码来实现禁止页面滑动.. 在网页中如果内容超过了浏览器高度便可以滑动.. 如果你想禁用掉这个滑动便会涉及到以上的代码.. 但是这个代码在手机上会报 render error:-2013

    实际上就是js中找不到这个对象.. 所以这个写法是不可用的

    另外.. 所有的类似空指针的操作.. 在网页上是可以显示的.. 但是在android中.. 会报出上面所说的render error:-2013的错误... 而且不知道如何定位这个错误在哪.. 所以解决报错也是个比较头疼的问题.. 最好拿每天的代码都跑一下手机看看是否有类似报错.. 不然层级太多了都不知道这个错是哪里来的...

    4.2.css代码如百分比不可用

    在前端中画圆你可能会用到 border-width:50% 这样的代码来实现一个节点的圆形... 但是这在手机上也是不可用的... weex官网上有解释.. 类似width这种传数字的无论你传什么单位都会被转成px ... 所以以上代码的实际效果就是50px的圆角了... 如果要实现圆形.. 还是要自己传定死的半径进去..

    具体还有不可用的css写法参考 :   css支持

    4.3.list中必须使用cell标签才可以显示

    在网页中.. list中的布局无论放什么都是可以正常展示的.. 但是在手机中... 不用<cell> 包裹的话.. 内容是不予展示的.. 这样设计的考虑可能是涉及到一个复用机制... 在手机中无论是IOS的TableView还是android的listview Recyclerview中的item都是要复用的.. 不然在手机中反复生成item会导致oom.. 所以cell包裹的内容会被复用.. 没被cell包裹的将不会被复用.. 且在list中不显示.. 主要是防止未复用的item过多导致oom所以强制使用的吧

    4.4.很多标签在手机上不支持部分基础css属性

    现在发现的主要是在android上margin属性在<cell>标签中是无效的.. 所以要使用margin需要在cell中再使用div包裹一层.. 

    讲道理margin这种基础css属性应该在所有标签上都是生效的.. 但是实际却不是.. 文档中也没有相关提示

    5.vue的mvvm控件内部双向绑定问题

    vue对于前端的同学可能不会陌生... 这是一个类似mvvm思想的框架,也就是说.. 视图直接和数据绑定了... 在数据改变时直接改变控件对应的视图状态,如下


    前面也说过weex是用vue完成代码再在手机上去用原生控件渲染的...

    但是vue中会涉及到一个内部控件去改外部参数的问题...如 点击打开链接

    控件内部希望修改props中传进来的参数去控制外部状态时.. 会报出 [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "xxxx"(参数名) 

    然后外部参数并没有改变.. 只是内部的变量改变了..

    那么怎么办呢.. 其实在vue中可以传入对象作为参数... 而props中的参数是不可变的.. 也就是传入的对象是不可被改变的 但是对象中的参数是可变的..


    我的做法就是传入data整个对象.. 里面包含了checkPosition属性... 这样就可以在js中对外部的属性进行修改了

    6.android中picasso版本太旧导致部分https地址图片加载有问题

    在android项目中对image标签中的地址图片.. 实际上是在用picasso加载的.. 但是它的版本已经比较旧了.. 好像是2.5.2的... 之前还以为是服务器上的图片处理有问题..  后来在排错之后发现是picasso旧版本对https支持不太好 ... 只要把旧版本的picasso升级.. 再extend下的ImageAdapter的代码用picasso的新版api加载图片.. 就可以解决这个问题了.. 不过也许你也遇不到这个问题.. 并不是所有的https下的图片都不可加载..

    7.血坑!! 编译速度过慢

    这个是最近才越来越明显感受到的一个问题.. 随着项目变大.. 编译速度会指数型上升.. 前期编译一下几秒.. 后来编译一下半分钟... 现在项目基本没五分钟跑不起来了.. 而且项目是没有布局预览的.. 也就是说你改一下布局想看看效果..就要付出五分钟的代价.. 太痛苦了.. 这个应该作为团队技术选型时的重要考虑点.. 是否真的为了不是很完美的三端通用.. 去浪费茫茫多的编译时间...

    解决:后来发现在安卓手机编译的速度会比较快一些.. 大约30秒左右... 算是可以接受吧... 起码比五分钟好多了..

    三.结论

    暂时遇到的坑就这些 .. 但是还是那句话..

    别拿weex来做商用!! 坑太多!!!

    我这个项目已经入坑了只能硬着头皮做下去.. 后面有新坑我还会回来更新的..

    比较完整的学习项目目前只找到

    网易严选demo

    这个项目是用vue router做的跳转.. 没有用navigator实现真正的多页应用.. 不过里面的vue+js+css代码还是有很多可以参考的地方的...

    四.后记

    最终还是和老大商量用安卓原生重做整个app了... 如大家所见.. 上面茫茫多的问题.. 记录一下我们竭尽所能仍未解决的一些问题吧.. 希望大家引以为戒..

    1.入口如何修改?

    在目录中就一个index文件作为入口.. 但是对于app来说应该会有所判断的.. 如区分有token和没有token的情况... 但是始终没有找到如何修改或能判断入口的地方..

    2.兼容性问题巨大

    在安卓4.4上.. 某些文字在离开界面再返回时直接会不见... 而高度在安卓上也会乱跳... (之前提到的减去88px并不是可靠的).. 因为滚动控件必须要限定边界... 所以逐渐就没有很好的解决方案了..

    3.模板内部的点击和滚动事件失效

    在component内部分点击和滚动事件直接无响应.. scroller中的布局也从水平的变成竖直的了...(在网页中都是正常的)... 现在已经决定放弃这个框架了也就懒得去排错了... 反正就是布局和手势在component中引用会有很大的问题...

    4.没有很好的debug手段

    由于他的代码在手机和网页中并不是都可用的... 所以难免在手机中会报很多错.. 但是错误会直接在界面上写个render error:-2013就停止执行了.. 完全看不到错误提示.. 也没有debug模式.. 在网页中又好端端的... 所以遇到一个小错就是半小时一小时.. 如此时间成本.. 做出来一个项目怕已经到了明年..


    本次weex的探索之旅就到此结束了... 所以不稳定的技术真的不要瞎用.. 代价很大..

    展开全文
  • 阿里巴巴开源前端框架--Weex实践

    万次阅读 2016-07-04 20:09:57
    Weex是最近很火很NB的一个技术产品,因为本篇介绍的是怎样使用Weex的最佳实践,所以就不罗里吧嗦的夸它怎么怎么好了,感兴趣的可以访问Weex HomePage,或加入旺旺群:1330170019。 利器 俗话说,欲要善其事,必先...

    Weex是最近很火很NB的一个技术产品,因为本篇介绍的是怎样使用Weex的最佳实践,所以就不罗里吧嗦的夸它怎么怎么好了,感兴趣的可以访问Weex HomePage,或加入旺旺群:1330170019。

    利器

    俗话说,欲要善其事,必先利其器。对于开发Weex,本人并不推荐裸奔。适合的工具,能让你的工作事半功倍。

    快速尝鲜

    我们在内网环境搭建了一个在线版的编辑器和预览工具,如果你希望快速尝鲜和试错,可以直接访问http://weex.alibaba-inc.com/playground,并按如下操作即可:

    playground

    准备开发环境

    在进行本地开发之前,你需要准备一台能顺利的运行Bash命令的电脑,比如Mac Book Pro。而对于钟情于Windows的同学来说,Weex的一系列工具并没有对Windows环境做特殊的适配,所以考虑Windows上的开发体验,强烈建议下载一个cmder来运行各种命令。

    说完了命令行工具,简单强调下软件环境:Nodejs >= 4.0

    开发单独页面

    Weex的一个优势就是能快速开发并上线一个可以运行于三端的页面,为此效率就很重要。所以,本人要推荐Weex的开发利器weex-toolkit。它可以通过npm安装到你本机的全局环境中(npm i weex-toolkit -g),从此你的开发环境下就多了一个神奇的命令weex

    首先,可以用神奇的weex命令创建一个示例文件:

    weex create helloworld

    然后随便编辑点什么,比如:

    <template>
      <div class="wxc-hellworld">
        <text>Hello Weex</text>
      </div>
    </template>

    紧接着,再运行那个神奇的命令:

    weex helloworld.we

    猛地会出现一个硕大的二维码,面对这个二维码可千万不要懵圈,请和我一起下载另一个神器Weex Playground

    当用这个神奇的扫码功能扫描这个二维码,就能展示Hello Weex的界面。并且,这个二维码支持Live Reload。任何对helloworld.we的改动都会立即更新Playground里所展示的界面。

    搭建完整工程

    不过,对于我们这些苦逼的前端攻城师来说,现在任何一个活动都没法用一个简单页面来搞定了,更不用说复杂的产品。所以,一个大而美的工程才能填补心中的阴影。

    如果你是一位斑马平台的簇拥者,建议你直接访问斑马平台的帮助文档来完成这件事情:Weex for Zebra

    而接下来,我想要详细阐述的是不依赖特定平台的Weex工程搭建。

    脚手架

    Adam,亚当,一切之源。用了它,再也不用担心第一次的尴尬了

    好了,硬广时间结束。如果要搭建工程,脚手架是不可获取的。这里推荐一个叫做adam的脚手架工具,不仅简单易用,还能轻松的创建你自己想要的脚手架。首先,通过tnpm安装。

    tnpm i @ali/adam -g

    然后,添加Weex的脚手架:

    adam tpl add weex

    紧接着,在某个空目录下,运行adam,并根据提示完成初始化。

    脚本

    这个脚手架工程中包含了基本的开发命令,通过npm i安装完依赖后,就可以用这些脚本来进行开发了:

    转换src目录下的所有.we文件,并输出到dist目录下

    npm run build

    监听.we文件的改动,并更新dist目录下的相应文件

    npm run dev

    预览H5版页面

    npm run serve -- -p 3000

    在浏览器中打开:http://localhost:3000/index.html?page=dist/welcome.js

    生成供Playgorund扫描的二维码

    npm run qr -- src/welcome.we

    启动调试工具(下面有章节具体聊这个事)

    npm run debugger

    有了上述这么多利器,开发Weex真是太爽了!

    磨刀不误砍柴工

    有了利器后,先不忙着上手,因为你还要先学会怎么操控它,让它能与你人器合一。

    文件目录结构

    Weex默认的文件结构是要求所有相关的we文件都在同一级目录下,以便能准确的找到依赖的组件,例如:

    bar.we

    <template>
      <div><text>bar</text></div>
    </template>

    foo.we

    <template>
      <div><bar></bar></div>
    </template>

    当需要提取一些公共组件,这些公共组件一般存放在一个公共目录下(自建的目录或通过npm安装到node_modules目录),而这样的文件结构,也往往出现在一些完整的项目工程中,当通过上述的脚手架搭建好示例工程手,可以通过前端习惯的require方式来引用非相同目录下的we文件,例如:

    components/bar.we

    <template>
     <div><text>bar</text></div>
    </template>

    foo.we

    <template>
     <div><bar></bar></div>
    </template>
    
    <script>
    require('./components/bar')
    </script>

    其背后的原理,实际上是整个转换和打包过程借助了webpack以及weex-loader,使得其中的模块化定义遵循标准的The way of CommonJS

    引用标准JS文件

    有了webpack的助力,在we文件中,也能轻松使用一个符合CommonJS规范的JS文件。例如,通过npm安装了业界No.1的工具库lodash

    foo.we

    <template>
     <div><text>{{foo + bar}}</text></div>
    </template>
    
    <script>
    var _  = require('lodash')
    module.exports = {
      data: {
        foo: 'foo',
        bar: 'bar'
      },
      created: function() {
        _.assign(this.data, {foo: 'the foo', bar: 'the bar'})
      }
    }
    </script>

    用上Tomorrow's css和ES2015

    如今前端的开发,一般离不开预处理器,比如postcssbabel。在默认的we文件中,即使有webpack的助力,这类预处理器也是对其无能为力的。为此,我们需要拆分这个we文件,让它变成标准的htmlcssjs文件。

    bar.we.html

    <template>
     <div><text class="hello">Hello {{name}}</text></div>
    </template>

    bar.we.css

    .hello {
      font-size: 40px;
      color: #333;
    }

    bar.we.js

    module.exports = {
      template: require('./foo.we.html'),
      style: require('./foo.we.css'),
      data: {
        name: 'Weex'
      }
    }

    并且,需要在webpack.config.js中加入几个能解析这些特殊文件的loader

    loaders: [
      {
        test: /\.we\.js(\?[^?]+)?$/,
        loaders: ['weex?type=script']
      },
      {
        test: /\.we\.css(\?[^?]+)?$/, 
        loaders: ['weex?type=style']
      },
      {
        test: /\.we\.html(\?[^?]+)?$/, 
        loaders: ['weex?type=tpl']
      }
    ]

    之后,仍然使用require的方式来引用这个'we'文件

    foo.we

    <template>
     <div><bar></bar></div>
    </template>
    
    <script>
    require('./bar.we.js')
    </script>

    当分割了we文件后,你就可以分别对其中的css或js文件使用你想要的预处理器

    不过需要特别提醒的是,目前weex-loader只支持module.exports={...}的模块输出方式,所以即使你在js文件中用了ES6的import,但请勿使用export来导出模块

    船到桥头自然直

    在实际进行Weex开发时,不免遇到一些令人困惑的问题。另外,也有可能写的代码没那么精湛而使得工程质量或产品性能达不到预期。笔者作为js-framework的主要开发者之一,虽然也没写过多少产品代码,但凭借对js-framework的深入理解,以及对众多业务当中槽点的剖析,尽量给大家呈现一些开发上的实践方案。不求最佳,但求最实用。(注:以下观点,不分先后)

    调用native提供的模块方法

    Weex的代码本身是运行在js的runtime下的,所以为了和native进行通讯,就需要借由hybrid的方式。其中,对于native提供的一系列模块方法,就需要用一种特殊,但直观的方式来调用。

    原本,Weex中集成了一些预定义的API,例如this.$sendMtop。但这些预定义API的维护成本过高,因此在最新甚至以后的Weex版本中,会渐渐废弃这类预定义的API,而改用更加通用的方式:

    var stream = require('@weex-module/stream')
    module.exports = {
      ready: function() {
        if (stream && stream.sendMtop) {
          stream.sendMtop(params, callback)
        } else {
          console.error('stream.sendMtop is invalid')
        }
      }
    }

    这里又再次请出了万能的require,不过和普通的require不同的是,需要指定特定的@weex-module前缀方能正确使用。

    慎用或不用异步函数

    为了解释异步函数的在Weex中的危害,首先要理解在Weex中产生的两类task。一类,是由Weex控制的js和native交互时产生的task(以下简称Weex的task),比如一系列异步调用native模块方法,或者点击事件等。一类,是系统原生的task(以下简称原生的task),比如setTimeoutPromise。在Weex的task中更新数据时,Weex可以自动更新View。而在原生的task中,因为Weex丧失了控制权,所以无法做到自动更新。这就导致,在原生的task中产生的diff,会滞留直到下一次Weex的task才会被触发更新View。从表面上看,就是在这些原生的task中改变数据后,并没有及时反应到View上。为了,避免这个问题的产生,目前来说并不推荐使用Promise。而对于setTimeout来说,可以使用native提供的timer.setTimeout的模块方法。

    生命周期的一二三

    Weex当前版本设计了组件的生命周期,以下的一张图可以比较直观的告诉大家在整个生命周期里都做了些什么事情:

    那么在这些生命周期的Hook里,可以做哪些事情呢:

    1. init中可以进行数据请求,比如mtop。但这个时候上下文中还没有data对象,同时也不建议在之后的任何阶段改变data的数据结构。
    2. created中,可以对data进行操作了,且此时更新数据不会产生多余的diff,但切忌也不能更改data的数据结构。另外,可以通过this.$on来监听子组件的dispatch
    3. ready中,此时子组件已经ready,可以获取子组件的Vm对象了。而此时,如果更新数据,会产生多余的diff。

    特别提醒:这三个阶段,都是不允许更改data的数据结构的。

    [Bug]设置样式的默认值

    来看一个通过改变class来改变样式的例子:

    <template>
      <div>
        <text class="{{className}}" onclick="toggle">Hello Weex</text>
      </div>
    </template>
    
    <style>
    .normal {
      font-size: 40px;
    }
    
    .hightlight {
      font-size: 40px;
      color: red;
    }
    </style>
    
    <script>
    module.exports = {
      data: {
        className: 'normal'
      },
      methods: {
        toggle: function() {
          if (this.className === 'normal') {
             this.className = 'hightlight'
          } else {
            this.className = 'normal'
          }
        }
      }
    }
    </script>

    上述例子,通过点击来切换样式名。但是你会惊奇的发现,在最初一次切换之后,字体的颜色就一直是红色的了。

    这其实是目前Weex一个bug,讨论如何修复的issue在这里#397。原因就是,在Weex中样式表样式的切换,并不会清除原来的样式。例如,当前样式是highlight,其中字体颜色是red,在切换到normal时,因为没有指定字体颜色,结果原来的red颜色就被保留了下来而并没有清除掉。所以,在上面的例子中为了避开这个bug,需要显示的设置字体颜色:

    .normal {
      font-size: 40px;
      color: black;
    }

    另外,对于最佳实践来说,可以通过组合class名称的方式,把需要切换的样式提取出来:

    <template>
      <div>
        <text class="common {{className}}" onclick="toggle">Hello Weex</text>
      </div>
    </template>
    
    <style>
    .common {
      font-size: 40px;
    }
    
    .normal {
      color: black;
    }
    
    .hightlight {
      color: red;
    }
    </style>

    元素上的属性定义

    Weex拥有一套类似前端开发习惯的DSL,HTML和CSS部分也都会遵循W3C的标准。其中元素上的属性定义,对于非前端同学来说会有很多误区,这里务必要说明下。

    1. 属性名必须全部小写,可以使用连接符-
    2. 属性值,尽量保证是原始类型,即number/string/boolean/undefined/null。对象类型的值一般用于大数据量的数据绑定。
    3. 一些HTML文章里会推荐在属性上用data-xxx的方式,这里并不需要特意加data前缀,因为Weex的js中并没有dataset的API可供调用。

    搞定子组件的数据绑定

    趁热打铁,来说下子组件的数据绑定。因为数据绑定也是通过属性来定义的,所以首先要遵循上一段所说的规则。

    1. 绑定数据通过属性来定义,不仅需要在使用的元素上指定属性并绑定父组件中的数据,也要在子组件的data中指定对应的键,并且元素上的属性和子组件中的键名的对应规则是:如果属性中有连接符,则键名为去掉连接符后的驼峰写法,否则全部以小写命名。
    2. 如果仅仅需要给子组件传递数据,而其中的数据结构对父组件是透明的,那么建议直接使用一个属性来映射;如果,属性是子组件的一些功能(且数量小于等于5个),则可以独立开来(基本上和API行为的设计原则差不多),例如:
    <we-element name="sub1">
      <template>
        <div><text>sub1</text></div>
      </template>
    
      <script>
        module.exports = {
          data: {
            aMtopData: {}
          }
        }
      </script>
    </we-element>
    
    <we-element name="sub2">
      <template>
        <div><text>sub2</text></div>
      </template>
    
      <script>
        module.exports = {
          data: {
            option1: '',
            option2: ''
          }
        }
      </script>
    </we-element>
    
    <template>
        <div>
          <sub1 a-mtop-data="{{mtopdata}}"></sub1>
          <sub2 option1="{{options.op1}}" options2="{{options.op2}}"></sub2>
        </div>
    </template>
    
    <script>
      module.exports = {
        data: {
          options: {
            op1: 'op1',
            op2: 'op2'
          },
          mtopdata: {}
        },
        created: function() {
          var self = this
          this.$sendMtop({...}, function(r) {
            self.mtopdata = r.data
          })
        }
      }
    </script>

    遍历长列表

    在我们各类大型运营活动的页面中,大家对楼层/坑位这些词应该不陌生。而这些名词的界面,基本都要靠循环列表来完成。而循环列表的性能又是整个运营页面的关键。所以在遍历这样的列表或者数组的时候,就需要一些技巧。

    通常来说,因为存在楼层的概念,而楼层里又是多个坑位,坑位又经常是双列宝贝,眼瞅着这得用个三重循环才能搞定。不过实际上,双列宝贝可以优化成不使用循环的结构。当然了,前端的童靴们一定要对着你们的服务端童靴保持坚定立场,要求获得清晰且正确的数据结构,确保前端不需要对数据结构做二次处理。

    通常的数据结构和对应的模板一般是这样的:

    <template>
      <div onclick="update">
        <div class="tabheader">
          <div repeat="{{headers}}" track-by="name" append="tree">
            <text>{{name}}</text>
          </div>
        </div>
        <div class="floor" repeat="{{floor in floors}}" track-by="floorId">
          <div class="items" repeat="{{items in floor.items}}" track-by="lineId" append="tree">
            <text>{{items.list[0].name}}</text>
            <text>{{items.list[1].name}}</text>
          </div>
        </div>
      </div>
    </template>
    
    <style>
      .tabheader {
        flex-direction: row;
      }
      .items {
        flex-direction: row;
      }
    </style>
    
    <script>
    module.exports = {
      data: {
        floors: [
          {
            floorId: 1,
            name: 'f1', 
            items:[
              {lineId: 1, list: [{itemId:1, name: 'i1'}, {itemId:2, name: 'i2'}]},
              {lineId: 2, list: [{itemId:3, name: 'i3'}, {itemId:4, name: 'i4'}]}
            ]
          }
        ]
      },
      computed: {
        headers: function() {
          return this.floors.map(function(v) {
            return {name: v.name}
          })
        }
      },
      methods: {
        update: function() {
          this.floors[0].items.push(
            {lineId: 3, list: [{itemId:5, name: 'i5'}, {itemId:6, name: 'i6'}]},
            {lineId: 4, list: [{itemId:7, name: 'i7'}, {itemId:8, name: 'i8'}]} 
          )
          this.floors.push({
            floorId: 2,
            name: 'f2',
            items: [
              {lineId: 5, list: [{itemId:9, name: 'i9'}, {itemId:10, name: 'i10'}]},
              {lineId: 6, list: [{itemId:11, name: 'i11'}, {itemId:12, name: 'i12'}]}
            ]
          })
        }
      }
    }
    </script>

    其中比较常见的数据结构问题,比如items只是一个一维数组。如果能在服务端就处理好items的多维数组问题,那么前端的效率会高很多。

    再仔细剖析其中的模板:

    <div class="tabheader" repeat="{{headers}}">
    
    ...
    
      computed: {
        headers: function() {
          return this.floors.map(function(v) {
            return {name: v.name}
          })
        }
      }

    这里绑定了一个computed特性的数据。当某类数据不太适合展示的时候,推荐可以用computed的方式来达到数据预处理的目的,而不是在created中吭哧吭哧的算一份新的数据结构出来。

    ...
        <div repeat="{{headers}}" track-by="name" append="tree">
    ...
    
    <div class="floor" repeat="{{floor in floors}}" track-by="floorId">
          <div class="items" repeat="{{items in floor.items}}" track-by="lineId">

    在这三个repeat中都用了track-by。它的特点是,可以记录数组中某个项的一个主键,并在之后的更新中复用这个特定的项,而不是重构整个数组。例如

    楼层1增加两行坑位

    this.floors[0].items.push(
      {lineId: 3, list: [{itemId:5, name: 'i5'}, {itemId:6, name: 'i6'}]},
      {lineId: 4, list: [{itemId:7, name: 'i7'}, {itemId:8, name: 'i8'}]} 
    )

    增加一个楼层

    this.floors.push({
      floorId: 2,
      name: 'f2',
      items: [
        {lineId: 5, list: [{itemId:9, name: 'i9'}, {itemId:10, name: 'i10'}]},
        {lineId: 6, list: [{itemId:11, name: 'i11'}, {itemId:12, name: 'i12'}]}
      ]
    })

    如果没有设置track-by,那么Weex会重构整个数组,导致元素被删除后又重新添加。而添加了id作为track-by的主键后,id相同的元素会通过移动的方式来优化操作。

    优化长列表

    长列表相信大家都做过。Weex中,对列表的优化已经非常接近原生系统的列表了,这个要归功于我们的Native团队。但即使有了性能不错的列表,对于首屏的渲染还是有追求的。

    在Weex中,要做无尽列表其实非常简单,因为在listscroll的元素上,已经实现了onloadmore事件,这个事件会在滚动触底(或者离底部一定的距离)时触发,所以这样看起来,做无尽列表变得非常容易。不过,这样的无尽列表体验绝对算不上极致。这个时候,可以借助loading这个组件,并配合onloading事件,来展现更加出色的无尽列表。

    <template>
      <list>
        <cell repeat="{{v in items}}" track-by="id">
          <text>{{v.name}}</text>
        </cell>
        <loading class="loading" onLoading="loadingHandler">
          <text>{{loadingText}}</text>
        </loading>
      </list>
    </template>
    
    <script>
    module.exports = {
      data: {
        index: 0,
        size: 50,
        count: 10,
        loadingText: '加载更多...',
        items: []
      },
      created: function() {
        this.addPage()
      },
      methods: {
        addPage: function() {
          for (var i = 0; i < this.size; i++) {
            var id = this.index * this.size + i
            this.items.push({id: id, name: 'item-' + id})
          }
          this.index++
        },
        loadingHandler: function() {
          if (this.index === this.count) {
            this.loadingText = '没有更多了'
          } else {
            this.addPage()
          }
        }
      }
    }
    </script>

    设计优秀的Weex组件

    在Weex原生功能越来越丰富的前提下,开发者可以设计出各类符合业务需求的UI组件,这些UI组件基本可以遵循标准的模块化开发,已达到复用和高度定制的目的。

    1. 用脚手架来初始化Weex组件的仓库再合适不过了。
    2. Weex是一种数据驱动的设计框架,组件并不是通过API来暴露行为,而是通过数据绑定来给组件设置行为。
    3. 组件的通信,可以通过$dispath/$broadcast来完成,不过这得付出一点点性能的代价。而在父组件拿到直接子组件的对象后,其实可以通过$on/$emit来减少性能的开销。
    4. 如果组件需要高度定制UI,可以考虑使用content/slot标签,具体可以参考下wxc-marquee
    5. 借由脚手架初始化Weex组件工程,可以轻松发布到npm/tnpm,并且开发者在通过npm install安装后,可以轻松的以require方式来引入这些组件。

    调试代码(查看日志)

    Weex未来会接入Chrome Dev-tools,甚至Debugger for IDE,这些都可以小小期待下的。而当下可以通过输出日志的原始方式来调试。

    在最开始的利器一章中,我已经让大家安装了weex-toolkit,并拥有了weex命令。那么现在要用它来开启调试的大门:

    weex --debugger

    或者在脚手架工程中运行:

    npm run debugger

    这个时候会输出一段本地的ip地址,在浏览器里输入这个地址,会展示一个二维码。用手淘debug包Playground扫码之后,就开启了输出日志模式。

    在这个界面中,你可以通过选择设备的日志级别,以及展示的输出级别来找到你想要的日志。同时在代码中,可以通过console.log/debug/info/warn/debug来输出相应级别的日志。

    在日志debug级别中,以[js framework]开头的,便是js-framework的解析操作。在日志verbose级别中,以Calling JSCalling Native开头的,就是jsnative互相通信的操作。

    后记

    到今天为止,笔者绞尽脑汁写了这些实践给各位同学。不过笔者承诺,本文涉及到的很多实践会不断的更新和新增,有兴趣的同学收藏本文,并随时欢迎在评论区进行讨论!

    展开全文
  • 阿里妹导读:本文主要为大家介绍飞猪 Weex 技术体系从无到有的过程,包括 Weex Ui 组件库的开发和发展,重点分享在 Weex Ui 层建设的一些经验,希望能对大家有所启发。 文章较长,首先放上 Weex Ui 的...
  • weex android 其实已经内置了zxing的扫描二维码的功能,我们需要做的就是将其封装成一个weex可以使用的module即可。 先贴代码结构图: 第一步,创建ScanModule.java package com.alibaba.weex; import ...
  • 截止2017-5-8 号,weex框架没有提供扫描二维码的模块,所以就有了本节的内容 本节学习目标 自定义一个扫描二维码模块 先看一下如何使用这个模块 第一步引入这个模块 var camera = weex.requireModule('camera') .....
  • 1.新建自定义ScanModule .java类,一般放...package com.alibaba.weex; import com.taobao.weex.annotation.JSMethod; import com.weex.app.WXPageActivity; import com.taobao.weex.bridge.JSCallback; import com...
  • Weex

    千次阅读 2019-06-02 18:17:36
    Weex 是一个可以使用现代化的 Web 技术开发高性能原生应用的框架。 快速开始 高性能 Weex 使用原生组件和原生模块,来最大化利用原生渲染的性能优势以及平台能力,所有的组件和模块都是可插拔、可扩展的。 ...
  • Weex之路——引路篇 Weex的迭代目前来说已经经过了很多版本,官方的文档已经过时,而且文档本身写的也很简陋,按官方文档很难把APP跑起来。经过多次趟坑后,决定把自己的经历写下来,给当前准备着手Weex开发的人...
  • 一文让你懂weex

    2019-09-11 23:37:58
    weex的初始化 weex的初始化一般从app启动的时候进行。weex的初始化主要完成三件事情: 初始化js framework——initFramework(); 注册公共Component和Module——registerModulesAndComponents(); 注册...
  • 阿里Weex框架快速体验与环境搭建

    万次阅读 2019-09-29 12:35:26
    目录阿里Weex框架快速体验与环境搭建weex sdk集成到Android工程weex服务项目搭建Weex优雅的“降级”到 HTML51. 前言Weex能够完美兼顾性能与动态性,让移动开发者通过简捷的前端语法写出Native级别的性能体验,并支持...
  • weex服务项目搭建

    万次阅读 2019-09-21 23:14:56
    2.服务项目搭建步骤前提需要安装好weex环境,具体参见前面文章:环境搭建地址 接下来讲解如何使用weex-toolkit构建项目:1)创建项目: 命令行到任意文件夹,输入如下指令weex init 执行指令后,会看到如图所示的...
  • weex项目实战篇(二)

    万次阅读 2019-09-29 12:46:27
    1. 前言经常前面的准备,我们终于可以开始上手weex项目了。2.新建weex项目1)新建一个名为hongkong的项目,如图所示: 2 ) 输入项目名称 3)点击【create】则项目则创建成功 4)新建一个.we文件 5)新建一个...
  • ### 安装weex 工具 OSX环境 ``` $ sudo chmod -R 777 /usr...$ weex -v // 查看当前weex工具版本 ``` ### 初始化环境 然后初始化 Weex 项目: ``` $ weex create awesome-project ``` 执行完命令后,在 awesome..
  • Weex多页面配置

    2019-07-12 11:08:54
    Weex是使用Vue和WebPack进行项目配置的。Weex创建的项目默认是只有一个入口的,也就是说,是单页面应用。对于移动开发来说,使用单页面(使用vue-router)是没有原生的页面跳转效果。在Weex的官方文档中,Weex提供了...
  • 随着Weex跨平台技术的持续火热,一时间涌现出了一大批基于Weex的开源解决方案,Weex Eros就是这么一个面向前端Vue的开源APP解决方案。 目前,如果直接使用Weex框架开发应用会存在很多痛点,诸如初始化启动的环境问题...
  • weex项目实战篇(一)

    万次阅读 2019-09-29 12:46:42
    1. 前言通过前面四篇文章的介绍,相信大家对weex基本熟悉了,下面就开始动手做项目,一些细节问题,在项目实战中继续消化。2.开发工具和环境俗话说,工欲善其事必先利器,我选的IDE开发工具为webstorm,webstorm相信...
  • Weex优雅的“降级”到 HTML5

    万次阅读 2019-09-29 12:53:20
    1.前沿Weex 在我们看来已经具有非常多的特点,比如: 1)致力于移动端,充分调度 native 的能力 2)充分解决或回避性能瓶颈 3)灵活扩展,多端统一,优雅“降级”到 HTML5 4)保持较低的开发成本和学习成本 ...
  • Weex Android交互篇

    2019-03-01 15:29:16
    Weex Android交互篇 什么是Weex Android交互? 我们理解的Weex Android交互就是we调用原生方法,原生调用we方法。针对于这种理解,我们可能有些偏差。那就是只有we调用原生方法,而没有we调用原生方法。因为,Weex ...
1 2 3 4 5 ... 20
收藏数 13,232
精华内容 5,292
关键字:

weex