weex 源码解析(二) -- vue 文件转为js(Android视角)

通过上一篇 weex 源码解析(一) -- 整体实现思路(Android视角) ,大家应该可以看到主要的实现方式了,接下来,就根据这个主框架,一步一步进行深入分析。

本篇主要是讲解第一步,vue文件的编写,以及js文件的生成。将vue编译为js,如果要运行在android端,需要使用weex-loader.

首先,我们需要知道,vue为什么要先转换为bundle js 文件(bundle的中文意思是捆绑,打包),用什么工具转的,以及bundle js文件里,又有哪些内容呢?接下来我们一步一步解析。

webpack

1.vue文件为什么要转换为bundle js文件。

由于weex是跨平台的框架,所以要可以运行在浏览器上,而浏览器不能识别vue文件,所以只能将vue转为浏览器所能识别的js文件。

2.vue是用什么工具来转为bundle js文件的。

vue是使用webpack来进行转换的

3.webpack的简介

本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。

4.打包后的bundle js文件里有哪些内容呢?

为了能够更加清晰的看到最简单的版本,大家可以先看看这篇《深入剖析 webpack 打包生成的bundle js》,后面我再将这篇文章直接集成到本文中。

看完上面的基础,接下来先贴几份weex 创建好项目后的helloworld代码:

1.entry.js,这个是入口文件。 在webpack的配置里指定好。

import Vue from 'vue';

import weex from 'weex-vue-render';

// import render-core.
// import weex from 'weex-vue-render/dist/index.core';

// need to run `npm i weex-vue-slider weex-vue-stream --save` frist.
// import the plugins (components and modules) you want to use.
// import slider from 'weex-vue-slider';
// import stream from 'weex-vue-stream';

// install the plugins.
// weex.install(slider);
// weex.install(stream);

weex.init(Vue);

复制代码

2.我们初始化weex工程里的helloworld页面,默认的index.vue,入口文件会引用该页面。虽然在上面的entry.js里没有看到引用,但从entry.js生成的临时文件(.temp/index.js)里是可以看到引用的。

.temp/index.js

import Vue from 'vue';

import weex from 'weex-vue-render';

// import render-core.
// import weex from 'weex-vue-render/dist/index.core';

// need to run `npm i weex-vue-slider weex-vue-stream --save` frist.
// import the plugins (components and modules) you want to use.
// import slider from 'weex-vue-slider';
// import stream from 'weex-vue-stream';

// install the plugins.
// weex.install(slider);
// weex.install(stream);

weex.init(Vue);

const App = require('../src/index.vue');
App.el = '#root';
new Vue(App);
复制代码

src/index.vue

<template>
  <div class="wrapper">
    <image :src="logo" class="logo"></image>
    <text class="greeting">The environment is ready!</text>
    <text class="message">Now, let's use Vue.js to build your Weex app.</text>
  </div>
</template>

<script>
  export default {
    data () {
      return {
        logo: 'https://gw.alicdn.com/tfs/TB1yopEdgoQMeJjy1XaXXcSsFXa-640-302.png',
      }
    }
  }
</script>

<style scoped>
  .wrapper {
    justify-content: center;
    align-items: center;
  }
  .logo {
    width: 424px;
    height: 200px;
  }
  .greeting {
    margin-top: 70px;
    font-size: 50px;
    color: #41B883;
  }
  .message {
    margin: 30px;
    font-size: 32px;
    color: #727272;
  }
</style>


复制代码

3.webpack打包后,生成的bundle js文件,bundle的中文意思,就是捆绑,打包。以下代码经过格式化,再加上相关的注释,以便大家可以看得更加清晰。

// { "framework": "Vue"}  //该注释不可删除,主要是告诉JS Framework 使用什么编译器来解析该js文件。


//js普通函数function (args){、、、}
//js普通函数定义后,自己执行自己,叫做自执行函数,可以这么写,(function (args){、、、})(args)
// 代码精简之后,如下:
// (function(modules) { 
//     //...
// })([function(module, exports) {
//     //..
// }])
//下面就只是一个[自执行函数](https://segmentfault.com/a/1190000003985390)
(function (modules) { // webpackBootstrap,这里的modules就是上面的args,在这里,是一个module数据,module代表模块,例如,一个js文件,一个vue文件,一个template,一个style等。。。
  
  // The module cache,module生成后,缓存在之类,以便重复使用
  var installedModules = {};

  // 一个方法内,还可以定义一个内部的方法
  // The require function,通过一个moduleId,创建模块的方法,moduleId一般从0开始,在webpack打包的时候,就指定每个module的id了。
  function __webpack_require__(moduleId) {

    // Check if module is in cache
    if (installedModules[moduleId]) {
      return installedModules[moduleId].exports;

    }
    // Create a new module (and put it into the cache)
    var module = installedModules[moduleId] = {
      i: moduleId, //模块id
      l: false,  //是否已经加载过
      exports: {}  //对外暴露的内容。
    };

    //下面是一个j 的 call方法,使用call方法,是为了改变this的指向。
    // Execute the module function
    modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

    // Flag the module as loaded, 标记模块已经加载完毕
    module.l = true;

    // Return the exports of the module,
    return module.exports;

  }


  // expose the modules object (__webpack_modules__)
  __webpack_require__.m = modules;

  // expose the module cache
  __webpack_require__.c = installedModules;

  // Object.defineProperty(obj, keyName, value);对某个obj的某个key,进行设置。
  // define getter function for harmony exports,这里的getter是一个方法。
  __webpack_require__.d = function (exports, name, getter) {
    if (!__webpack_require__.o(exports, name)) {
      Object.defineProperty(exports, name, {
        configurable: false, //设置false后,该value的enumerable,get等不能再被修改。
        enumerable: true, //是否可以被枚举获取到该key和value。
        get: getter //其他地方调用获取该key的值的时候,会返回getter方法里的return值。

      });

    }

  };

  // 获取默认的export对象,如果是es6规范语法,则返回module.default,否则,就返回module。
  // getDefaultExport function for compatibility with non-harmony modules
  __webpack_require__.n = function (module) {
    var getter = module && module.__esModule ?
      function getDefault() { return module['default']; } :
      function getModuleExports() { return module; };
    __webpack_require__.d(getter, 'a', getter);
    return getter;

  };

  //某个对象,是否有某个属性的方法。
  // Object.prototype.hasOwnProperty.call
  __webpack_require__.o = function (object, property) {
    return Object.prototype.hasOwnProperty.call(object, property); 
  };

  // __webpack_public_path__,webpack配置下的公共路径
  __webpack_require__.p = "";

  // Load entry module and return exports,这里加载入口module,并返回export对象。
  return __webpack_require__(__webpack_require__.s = 0);

})
  /************************************下面是modules************************************//
  ([
/* 0 */ // 这个modules是入口模块,moduleId为0
/***/ (function (module, exports, __webpack_require__) {

      var __vue_exports__, __vue_options__
      var __vue_styles__ = []

      /* styles */ //获取styles modules
      __vue_styles__.push(__webpack_require__(1))

      /* script */ //获取script module
      __vue_exports__ = __webpack_require__(2)

      /* template */ //获取template module
      var __vue_template__ = __webpack_require__(3)
      
      //__vue_exports__ || {}意思是如果__vue_exports__为空,就执行||后面那一项,即返回{},否则就返回__vue_exports__
      __vue_options__ = __vue_exports__ = __vue_exports__ || {} 
      if (
        typeof __vue_exports__.default === "object" ||  //typeof是用来判断某个obj的类型的。
        typeof __vue_exports__.default === "function"
      ) {

    //下面这里有2个方法,一个是Object.keys(obj),是将obj里的所有成员变量的key放在数组中,并返回例如返回['key1','key2','key3']
    //另一个是数组的some方法,array.some(function(key){xxx}),这里会将array中的每个key传给function,进行执行判断,返回boolean值。只要有一个值为true,那array.some(function(key){xxx})就为true,否则为false。
        if (Object.keys(__vue_exports__).some(
          function (key) {
            return key !== "default" && key !== "__esModule"
          }
        )
        ) {
          console.error("named exports are not supported in *.vue files.")
        }
        __vue_options__ = __vue_exports__ = __vue_exports__.default
      }


      if (typeof __vue_options__ === "function") {
        __vue_options__ = __vue_options__.options
      }
      __vue_options__.__file = "/home/linshaoyou1/work/patch-code/flyme5/flyme5_base/meizu/SDK/ali-weex5/src/index.vue"
      __vue_options__.render = __vue_template__.render
      __vue_options__.staticRenderFns = __vue_template__.staticRenderFns
      __vue_options__._scopeId = "data-v-6cc2e18e"
      __vue_options__.style = __vue_options__.style || {}
      __vue_styles__.forEach(function (module) {
        for (var name in module) {
          __vue_options__.style[name] = module[name]
        }
      })
      if (typeof weex === "object" && weex && weex.document) {
        try {
          weex.document.registerStyleSheets(__vue_options__._scopeId, __vue_styles__)
        } catch (e) { }
      }

      module.exports = __vue_exports__
      module.exports.el = 'true'
      new Vue(module.exports)


      /***/
    }),
/* 1 */
/***/ (function (module, exports) {

      module.exports = {
        "wrapper": {
          "justifyContent": "center",
          "alignItems": "center"
        },
        "logo": {
          "width": "424",
          "height": "200"
        },
        "greeting": {
          "marginTop": "70",
          "fontSize": "50",
          "color": "#41B883"
        },
        "message": {
          "marginTop": "30",
          "marginRight": "30",
          "marginBottom": "30",
          "marginLeft": "30",
          "fontSize": "32",
          "color": "#727272"
        }
      }

      /***/
    }),
/* 2 */
/***/ (function (module, exports, __webpack_require__) {

      "use strict"; //使用严苛模式,所以如果没有遵循语法,会报异常。例如,某个变量不声明,就开始使用,会报异常。


      Object.defineProperty(exports, "__esModule", {
        value: true
      });

      exports.default = {
        data: function data() {
          return {
            logo: 'https://gw.alicdn.com/tfs/TB1yopEdgoQMeJjy1XaXXcSsFXa-640-302.png'
          };
        }
      };

      /***/
    }),
/* 3 */
/***/ (function (module, exports) {

      module.exports = {
        render: function () {
          var _vm = this;
          var _h = _vm.$createElement; 
          var _c = _vm._self._c || _h; //这里_c就是创建元素,也就是创建虚拟节点的方法。
          return _c(
            'div', //type 标签
            {
              staticClass: ["wrapper"] // style的class
            },
            [ //这个标签下的子标签
              _c(
                'image',
                {
                  staticClass: ["logo"],
                  attrs: {
                    "src": _vm.logo //其他属性
                  }
                }
              ),
              _c(
                'text',
                {
                  staticClass: ["greeting"]
                },
                [
                  _vm._v("The environment is ready!") //子标签里只有String字符串。
                ]
              ),
              _c(
                'text',
                {
                  staticClass: ["message"]
                },
                [
                  _vm._v("Now, let's use Vue.js to build your Weex app.")
                ]
              )
            ]
          )
        },
        staticRenderFns: []
      }
      module.exports.render._withStripped = true

      /***/
    })
  ]);
复制代码

转载于:https://juejin.im/post/5ab66653f265da23884d0457

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值