## 事件

先了解 Mobilebone 中与页面生命周期相关的事件。

### 生命周期

Mobilebone 中，页面从进入到离开为一个完整的生命周期。

整个生命周期过程如下图所示，Mobilebone 在生命周期的各个阶段都暴露了接口可以让开发者自定义事件。

其中：

- `preventdefault` 事件在进入和离开之前都会执行；
- `onpagefirstinto` 事件只会在第1次进入的时候执行；
- `callback` 事件每次页面进入的时候执行；
- `fallback` 事件每次页面离开的时候执行；
- `animationstart` 事件在进入和离开动画执行前都会执行；
- `onpagefirstinto` 事件在进入和离开动画执行后都会执行。

### 设置

Mobilebone 中生命周期事件分全局事件和局部事件。

- 全局事件使用 Mobilebone 对象直接指定，例如希望所有页面进入的时候都执行，可以这样设置：

      Mobilebone.callback = function () {
          console.log('每次页面进入都执行');
      };

- 局部事件则通过 `data-*` 的语法在页面容器元素上设置，例如：

      <div class="page out" data-callback="someFuncName">
          <p>页面内容</p>
      </div>

  表示该页面进入的时候会执行函数名为`someFuncName`的方法。

默认状态下，对于局部事件，Mobilebone 会在 `window` 对象中寻找对应名称的函数并执行。例如，`data-callback="someFuncName"` 设置后 Mobilebone 会执行 `window.someFuncName()`。

然而，在 JavaScript 中，全局对象是容易产生冲突的，因此显然，函数挂载到 `window` 对象中并不适合复杂的项目，Mobilebone 是支持指定事件函数挂载的对象的，同样也分全局设置和局部设置。

- 全局设置通过 Mobilebone.rootTransition 属性进行设置。

  例如有个 Vue 实例对象 `myVue`：

      var myVue = new Vue({
          methods: {
              someFuncName () {}
          }
      });

  则下面的设置就可以让 Mobilebone 调用 Vue 实例对象中的方法：

      Mobilebone.rootTransition = myVue;

- 局部设置通过 `data-root` 属性进行设置，例如：

      <div class="page out" data-root="$" data-callback="callback"></div>

  则当前页面的 `callback` 方法会在 `window.$` 中寻找并执行，此设置不会影响其他页面。

### 事件中的参数

每个生命周期事件都暴露了若干参数，例如：

- onpagefirstinto(pageInto, pageOut, options)
- callback(pageInto, pageOut, options)
- fallback(pageInto, pageOut, options)
- animationstart(page, intoOrOut, options)
- animationend(page, intoOrOut, options)
- preventdefault(pageInto, pageOut, options)

这些参数的作用是让开发者知道当前移入移出的页面是哪个，以及页面间传递的参数是什么（通过 `options.query` 获取）。

至于各个参数的含义和作用可以参考对应的 API 文档：data-callbackKeys.html

### 内置的事件

Mobilebone 对页面中所有的 `<a>` 元素默认的 `'click'`事件行为 和 `<form>` 元素的默认的 `'submit'` 事件行为进行了劫持。

例如：

- 点击 `<a href="#targetPage">` 不再是锚点跳转，而是显示页面中 `id` 属性值是 `'targetPage'` 的页面元素。
- 点击 `<a href="target.html">` 不再是跳转到 `target.html` 页面，而是自动拉取 `target.html` 页面内容并作为一个内嵌的页面显示。
- 提交 `<form action="/someUrl">` 不再是传统的带刷新的表单提交，而是会把当前表单请求返回的内容作为一个内嵌的页面显示。

如果希望 `<a>` 元素和 `<form>` 元素保留默认的行为，可以在这些元素上设置 `data-ajax="false"`，例如：

    <a href="target.html" data-ajax="false">传统的页面跳转</a>

如果希望`<a>` 元素或者 `<form>` 元素在执行无刷新过场之前进行其他的逻辑判断处理，则可以使用 `data-preventdefault` 进行处理，代码示意：

    <a href="login.html" data-preventdefault="isDialogLogin">登录</a>

    let isDialogLogin = function () {
        // 大屏下使用弹框执行登录
        if (screen.width > 800) {
            // 登录弹框显示
            loginDialog.show();
            // 返回 true 表示阻止 Mobilebone 的事件处理行为
            return true;
        }
    };

相关API详见这里：data-ajax、data-preventdefault。

### 页面代码的执行

在 Mobilebone 项目中，入口页面的事件就和普通的网页一样执行的，无论是内联 JavaScript 代码，还是 `src` 地址外链的 JavaScript 代码。

但是，如果是通过 Ajax 请求拉取的请求页，则这些页面中的 JavaScript 代码默认是不执行的，原因在于避免冗余执行。

例如，列表页有20个详情页链接，如果每次请求一个详情页，里面的 JavaScript 代码都全部执行一遍，则会产生大量的重复的 JavaScript 代码执行，这是没有必要的。

在Mobilebone 项目中，更推荐所有页面共用一个主 JavaScript 文件代码，也就是在这个 JavaScript 文件中处理所有的逻辑关系。如果项目比较复杂，可以分页面或模块开发，然后发布的时候合并成一个独立的 JavaScript 文件作为主文件即可。

当然，Mobilebone 提供了执行请求的页面中的 JavaScript 代码的能力，设置 Mobilebone.evalScript 的值为 `true`就可以了。

    Mobilebone.evalScript = true;

但是需要注意的是，设置 `Mobilebone.evalScript` 为 `true` 只会执行内联的 `<script>` 脚本，例如下面的代码会执行：

    <script>console.log('script excuted!');</script>

但是下面的 `1.js` 就不会执行：

    <script src="1.js"></script>

发现错误？想参与编辑？在 GitHub 上编辑此页！