Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

深入wepy源码:wepy运行原理分析 #4

Open
yingye opened this issue May 21, 2018 · 0 comments
Open

深入wepy源码:wepy运行原理分析 #4

yingye opened this issue May 21, 2018 · 0 comments

Comments

@yingye
Copy link
Owner

yingye commented May 21, 2018

在分析源码之前,我们先来回顾一下,wepy 的使用:

<!-- 小程序入口 app.wpy -->
<script>
import wepy from 'wepy';
export default class extends wepy.app {
  ......
}
</script>

让我们一起看看 export 出来的 class,是怎么转换成小程序语言的。

《深入wepy源码:wpy文件编译过程》中,我们介绍了 wepy-cli 是如何编译 wpy 文件的,里面有说到,complie-script.js 在处理 script 代码时,会加入 wepy 初始化的代码。编译之后 dist 目录下的文件,如下:

// dist/app.js
App(require('./npm/wepy/lib/wepy.js').default.$createApp(_default, {}));

// dist/pages/index.js 
Page(require('./../npm/wepy/lib/wepy.js').default.$createPage(Index , 'pages/index'));

可以看出,主要调用了 $createApp$createPage 方法。在看这两个方法之前,我们先来看一下 wepy 的目录结构,以便后面的分析更好理解。

wepy目录结构

├─wepy                 
  ├─src                     
    ├─app.js                全局app逻辑,请求优化、promisify API、拦截器功能等    
    ├─base.js               定义了 $createApp 和 $createPage 等方法
    ├─component.js          组件逻辑,脏值检查、组件通信等
    ├─event.js              事件方法
    ├─mixin.js              混合方法
    ├─native.js             空,代码里用于app.js中重新定义wx接口
    ├─page.js               继承component,page的一些优化
    ├─util.js               工具方法
    ├─wepy.js               入口文件
  ├─test                
  ├─...

$createApp 和 $createPage

$createApp

// dist/app.js
App(require('./npm/wepy/lib/wepy.js').default.$createApp(_default, {}));

$createApp() 返回了一个类型为 object 的 config,里面包含了 ['onLaunch', 'onShow', 'onHide', 'onError'] 这些方法。

还执行了 $initAPI(),主要利用 Object.defineProperty 的 get 方法,将返回封装为 promise,这里也是 API 实现 promise 写法的核心。

$createPage

// dist/pages/index.js 
Page(require('./../npm/wepy/lib/wepy.js').default.$createPage(Index , 'pages/index'));

$createPage()$createApp() 类似,只不过是返回的是 Page 的方法,此外,还在生命周期中,添加了数据脏值检查 $apply()

数据绑定

wepy 使用脏数据检查对原生小程序 setData 进行封装,在函数运行周期结束时执行脏数据检查。如果在异步函数中更新数据时,则需要手动执行 $apply()。贴一张官方的流程图。

$createPage() 中,会在生命周期中调用 $apply(),来看一下它的定义:

$apply (fn) {
  if (typeof(fn) === 'function') {
    fn.call(this);
    this.$apply();
  } else {
    if (this.$$phase) {
      this.$$phase = '$apply';
    } else {
      this.$digest();
    }
  }
}

$$phase 标识是否有 脏数据检查 在运行,如果没有,则执行 $digest()

$digest() {
  let k;
  let originData = this.$data;
  this.$$phase = '$digest';
  this.$$dc = 0;
  while (this.$$phase) {
    this.$$dc++;
    if (this.$$dc >= 3) {
        throw new Error('Can not call $apply in $apply process');
    }
    ......
    this.$$phase = (this.$$phase === '$apply') ? '$digest' : false;
  }
}

$digest() 执行时,主要是遍历 originData,将 originData[k]this[k] 做对比,如果不一样,放到 readyToSet 中,在循环之后,统一执行 setData 方法。

最后,在检查 $$phase 是否有被设置为 '$apply',如果是,则再做一次脏数据检查。

最后

本文分析的源码以 [email protected] 版本为准,更多信息可参考 wepy github (即 github 1.7.x 分支)。另外,文中有任何表述不清或不当的地方,欢迎大家批评指正。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant