zoukankan      html  css  js  c++  java
  • Weex 初探

    Weex 初探

    Weex 介绍

    Weex 是阿里于 2016 年开源的一款开发框架,它的介绍是:

    Weex 是一个使用 Web 开发体验来开发高性能原生应用的框架。

    它使用了 Web 技术来开发 Android、IOS 应用,从而达到更快的迭代速度,同时降低了开发原生应用的门槛,
    达到生产力和性能共存。

    Weex 项目结构

    Weex 设计之初是为了和原有应用进行兼容开发,和 NativeScript 不同,它只需要在项目中添加 Weex 的 SDK 即可使用。
    它的定位不是全部应用,目标是针对部分变动频繁的应用。它是一种解耦的应用,每个页面相对独立,通过路由的方式对调用各页面,
    通过 API 的方式与设备进行交互。所以可以看到官网上 Weex 的结构图:

    weex 结构图

    weex工程结构

    使用 Weex 构建一个简单的应用

    Weex 做一个简单一些的例子还是比较合适的。本文以仿开眼部分功能为例做一小应用。先看下效果图:

    应用效果图

    项目搭建前准备工作

    首先需要准备好 npm 环境、Android 环境,IOS 环境,由于在 mac 下直接安装 xcode 就具备 IOS 环境了,且 npm 是前端必备开发环境的,就无需再安装了。Android 环境的安装可以直接安装 Android Studio,一键配置好环境。

    打开控制台,全局安装 weex

    npm i -g weex-toolkit weex weex-debugger
    

    创建项目:

    weex create weex-kaiyan
    cd weex-kaiyan
    weex platform add android
    weex platform add ios
    

    按照提示操作即可。安装速度都不是很快,需要耐心等候。为了方便开发,我们采用 airbnb 的代码规范,先在 devDependencies 安装相关依赖(或者全局安装eslint,用 eslint 的init 功能也可以):

    "eslint": "^4.13.1",
    "eslint-config-airbnb-base": "^12.1.0",
    "eslint-friendly-formatter": "^3.0.0",
    "eslint-import-resolver-webpack": "^0.8.3",
    "eslint-loader": "^1.7.1",
    "eslint-plugin-import": "^2.8.0",
    "eslint-plugin-vue": "^4.0.0",
    

    在 .eslintrc.js 中添加

    extends: ['plugin:vue/recommended', 'airbnb-base'],
    

    在 vscode 中启用 lint 功能:

    "eslint.validate": [
        "javascript",
        "javascriptreact",
        "html",
        "vue"
    ],
    "eslint.options": {
        "plugins": ["html"]
    },
    
    

    然后准备好要访问的 api (https://github.com/kaikaixue/Eyepetizer/blob/master/app/src/main/java/com/xk/eyepetizer/api),这样做完了准备工作,可以开始开发了。

    目录结构大概是这样子:

    
    ├── README.md
    ├── android.config.json
    ├── configs
    │   ├── config.js
    │   ├── helper.js
    │   ├── logo.png
    │   ├── plugin.js
    │   ├── utils.js
    │   ├── vue-loader.conf.js
    │   ├── webpack.common.conf.js
    │   ├── webpack.dev.conf.js
    │   ├── webpack.prod.conf.js
    │   └── webpack.test.conf.js
    ├── ios.config.json
    ├── npm-shrinkwrap.json
    ├── package.json
    ├── platforms
    │   ├── android
    │   ├── ios
    │   └── platforms.json
    ├── plugins
    │   └── plugins.json
    ├── src
    │   ├── api
    │   │   └── index.js
    │   ├── components
    │   │   ├── card-list-scroller.vue
    │   │   ├── card-video-no-author.vue
    │   │   ├── card-video.vue
    │   │   └── tab.vue
    │   ├── entry.js
    │   ├── index.vue
    │   ├── mixin-common.js
    │   ├── mixin-preload.js
    │   ├── mixin-router.js
    │   ├── router.js
    │   └── views
    │       ├── categories.vue
    │       ├── categoryHome.vue
    │       ├── home.vue
    │       ├── rank.vue
    │       └── videoDetail.vue
    ├── web
    │   ├── assets
    │   │   ├── preview.css
    │   │   └── qrcode.js
    │   ├── index.html
    │   └── preview.html
    └── webpack.config.js
    

    
    其中 config 文件下是用于放 webpack 打包的配置, src 就是我们的代码目录,platform 里面放 native 代码,
    web 文件夹是我们的 web 的 html 模板。

    项目配置

    要实现三端开发,默认的 weex 项目模板是不行的,它的设计是为 Native 准备的,不考虑单页应用的方式。
    虽然不推荐三端同时开发(兼容三端效率会比较低),但为研究怎么实现我们还是做一下。先安装单页应用必备 vue-router

    修改 entry.js

    然后修改 src/entry.js ,添加手动挂载 vue 的代码,假定我们 src 目录下有个 router.js,
    还有一个所有文件用的mixin,修改完成后的代码如下:

    import Vue from 'vue';
    import weex from 'weex-vue-render';
    import App from './index.vue';
    
    import router from './router';
    import mixin from './mixin-router';
    
    weex.init(Vue);
    
    Vue.mixin(mixin);
    
    App.el = '#root';
    App.router = router;
    
    const app = new Vue(App);
    
    export default app;
    

    在 native 端这个 entry.js 是没用的,native 端是直接使用由 weex 打包生成的 js 文件,
    包括挂载都是框架做的,我们不需要处理,所以它只是给 web 使用的。

    设置入口

    然后设置主入口:build/webpack.common.conf.js中webEntry为固定值:

    const webEntry = {
      'index': helper.rootNode(config.entryFilePath)
    };
    

    同时注释掉读取文件内容并注入entry中

        // if (extname === '.vue') {
        //     const entryFile = path.join(vueWebTemp, dir, path.basename(file, extname) + '.js');
        //     fs.outputFileSync(path.join(entryFile), getEntryFileContent(entryFile, fullpath));
        //     webEntry[name] = path.join(entryFile) + '?entry=true';
        //   }
    

    添加代理

    在 webpack 中添加代理,由于 web 端有跨域问题,我们在 configs/config.js 中添加

    proxyTable: {
      '/api': {
        target: 'https://baobab.kaiyanapp.com/',
        changeOrigin: true,
      }
    },
    

    编写代码

    公用模块

    现在开始像正常写 vue 一样开始码代码吧。要先注意的一点是 native 端不支持 vue-router 的特性,
    需要使用 navigator 模块进行 push 操作,所以我们需要单独写个模块,通过 mixin 方式进行兼容 页面跳转,
    参考 https://www.jianshu.com/p/497f1a9ff33f:

    const isWeex = weex.config.env.platform.toLowerCase() !== 'web';
    const nav = weex.requireModule('navigator');
    
    export default {
      methods: {
        push(path, option = {}) {
          if (isWeex) {
            const toUrl = weex.config.bundleUrl.split('/').slice(0, -1).join('/') + '/' + path.replace(/^//, '') + '.js';// 将a.js的绝对地址转为b.js的绝对地址
            nav.push({
              url: toUrl,
              animated: option.animated || 'true',
            });
          } else {
            this.$router.push(path);// 使用vue-router
          }
        },
        pop(option = {}) {
          if (isWeex) {
            nav.pop({
              animated: option.animated || 'true',
            });
          } else {
            window.history.back();
          }
        },
      },
    };
    

    这样我们在写跳转时候就可以写成:

    this.push('/videoDetail')
    

    同时准备好你需要的 api 库模块(我用的 axios),以及其他公众模块,比如说 storage 。Weex 中的 Storage 模块是为了兼容 web 版本,接口和 web 版本的 LocalStorage 比较类似,只是异步形式。为方便,我们可以将回调式转为 Promise 式:

    function callStorage(type) {
      return function callMethod(...args) {
        const storage = this.$storage;
        return new Promise((resolve, reject) => {
          const callback = (e) => {
            if (e && e.result === 'success') {
              resolve(e.data);
            } else {
              reject(e);
            }
          };
    
          storage[type].call(storage, ...args, callback);
        });
      };
    }
    
    class Storage {
      constructor() {
        this.$storage = weex.requireModule('storage');
      }
      setItem = callStorage('setItem')
      getItem = callStorage('getItem')
      removeItem = callStorage('removeItem')
    }
    

    然后在 Mixin 中使用它即可。如果你有精力的话,可以设计一个基于 storage 的数据传递模块。

    开发页面

    开发页面就和写 vue 一样啦,只是要注意一些点:

    • Weex 支持的元素类型是有限的,用到哪种需要到官网手册中去查询
    • 每个页面是独立,一定要记住这一点,因此 mixin 之类的公用库,需要手动引入到页面中
    • css 选择器只支持一级,比如 .classA 不支持 .classA .classB 这种类型,你需要为设置样式的每个元素添加 className,需要防止变量冲突(web 端是单页应用,可能会有问题)

    Native 端配置

    包括在开发阶段,我们也是需要对 native 端进行效果验证的。Weex 提供了一个简单的命令:

    weex run android 
    weex run ios
    npm run dev
    

    如果已经配置了 IOS 环境,直接运行命令就可以了。不过默认的主页是 index.js,
    可以在 android.config.json 和 ios.config.json 中分别配置 WeexBundle 选项即可。
    需要注意的是,运行状态下默认是打开本地文件的,而运行命令是不会放 views 文件夹目录过去,
    需要手动拷贝一下。安卓下面由于访问本地文件的接口在 7.0 下有问题,
    建议在 app_config.xml 中修改 launch_locally 为 false, 并指定好远程地址。

    调试没问题后,我们按照 Android 和 IOS 各自的方案进行打包即可.

    总结

    由于自己对 Native 开发了解得不多,所以好多东西一知半解,而且 Weex 的包总能发现各种小问题,
    需要强大的耐心去解决或者规避这些问题,只能祝使用的人好运吧。新出的 weex-ui 虽然已经开源好久了,
    有时间可以尝试下,不过由于核心模块没有开源,好多组件不能使用,先观望一段时间,等有好的点子再试试。

  • 相关阅读:
    也谈谈关于WEB的感想
    spring boot,https,双向ssl认证
    Spring Cloud Gateway(二)
    Spring Cloud Gateway(一)
    .Net Web Service 自定义返回值命名
    随便记一下,C#并行环境操作Winform的代码段
    随便记一下,解决Windows Server 2012无法远程登录的方法
    记录C#控件DataGridView绑定BindingList无法排序问题(转)
    记录SQL Server 2019链接Oracle 11g R2的过程
    Json CPP 中文支持与入门示例
  • 原文地址:https://www.cnblogs.com/dreamless/p/8550012.html
Copyright © 2011-2022 走看看