Skip to content

Commit

Permalink
MIP 核心 10.08 上线 (#705)
Browse files Browse the repository at this point in the history
* 单页跳转透传 hash

* add cambrian logo and title

* add cambrian logo and title

* fixed: 修复 iOS 百度 APP 下的页面无法滚动的问题

* [feat] MIP 交互机制升级 (#656)

* add parser

* 添加全局行为

* 增加 event 语法规则

* 添加 navigateTo,fix code

* rewrite mip event

* finish mip event parse

* add visitor

* update

* add arrow

* fix property & callexpression bug

* 整合全局方法

* fix callexpression bug

* 调整代码

* update code

* fix objectexpression bug

* update whitelist

* update test case

* add test case

* modify test case

* add DOM

* 修复 Identifier bug

* 修复 Identifier bug

* add mip-action

* update code

* add argument scope

* 修改路径

* update path

* 打通 action 数据传递

* fix mdata bug

* fix element action bug

* 增加兼容逻辑

* 重写 mip-bind 方法

* update code

* add setData parse fallback

* update bindStyle

* update bindStyle

* update bindStyle

* 增加 watch

* 增加 input  的双向绑定

* 删除无用文件

* 修改 mip-bin 入口

* update code

* 拆分 bind.js

* 拆分 mip-bind/bind.js

* add input global event

* update event action spec

* 修复 style binding

* remove only

* update input global event and toggleVisibility

* 去除 mip-shell/render.js 调用 MIP. 的逻辑

* change lexer from class to function

* add test page

* 优化 lexer 机制

* 修改 lexer 策略

* update test page

* update unit test

* 补 testcase

* 补全 testcase

* 修改 ArrayLiteral 对最后一个 comma 的处理

* 增加测试描述

* add unit test

* add complex function testcase

* fix scrollTO hidden element

* fix can not find mip1 custom element action

* 修复 setData 接收 Vue 响应式对象时疯狂报错的问题

* fix isObject

* 修复 mip-bind 覆盖 MIP.setData 的bug

* 修复  lgtm 所提示的循环中使用 splice 的问题

* fix lgtm alerts

* 修复 bind & vnavigateTo 在 IOS8 下面无法正常工作的兼容性 bug

*  移除 mip-img popup 对 loaded 的筛选 (#668)

* 移除 mip-img popup 对 loaded 的筛选

* fix: hash 锚点追加的问题&pc 页面空白问题&添加百度 APP  iOS 通信功能

* fix: hash 锚点追加的问题&pc 页面空白问题&添加百度 APP  iOS 通信功能

* fix: hash 锚点追加的问题&pc 页面空白问题&添加百度 APP  iOS 通信功能

* fix: hash 锚点追加的问题&pc 页面空白问题&添加百度 APP  iOS 通信功能

* 修复 scrollToHash 当锚点的祖先存在�定位元素时不能滚动到锚点的问题 (#675)

* [feat] mip-bind 功能升级 (#685)

* add scoped mip-data

* update mip-bind dom diff

* 增加 mip-data 的 refresh

* update dom watch

* update dom watcher

* change scoped to scope

* 修复部分 test case

* 优化报错信息

* fix docs

* 增加单测覆盖率

* 补充 testcase

* 新增 mip-data fetchjsonp 支持

* 去掉 mip-data 的 JSONP 支持

* 统一 MIP 表达式的语法形式 (#701)

* 增强 MIP 表达式语法

* 调整文章

* 增加 String.prototype.trim 在 MIP 表达式中的支持
  • Loading branch information
clark-t authored Oct 8, 2019
1 parent 5898aac commit 3ef6a9b
Show file tree
Hide file tree
Showing 9 changed files with 158 additions and 75 deletions.
54 changes: 29 additions & 25 deletions docs/docs/interactive-mip/event-and-action.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ MIP 提供了 `on` 属性来定义对组件的事件绑定与事件触发时的
class="example-button"
on="tap:
top-example.hide,
MIP.scrollTo(id='mip-scrollto-button', duration=500, position='center')"
MIP.scrollTo({id: 'mip-scrollto-button', duration: 500, position: 'center'})"
>点击返回原示例</button>
</div>
Expand Down Expand Up @@ -46,7 +46,7 @@ MIP 提供了 `on` 属性来定义对组件的事件绑定与事件触发时的
<div on="tap:header-element.show">点我</div>
<!-- 调用 MIP 特殊对象上的方法 -->
<div on="tap:MIP.setData({ a: 1 + 2 })"></div>
<div on="tap:MIP.navigateTo(url='https://www.baidu.com', target='_blank')">
<div on="tap:MIP.navigateTo({ url: 'https://www.baidu.com', target: '_blank' })">
```

### 多事件绑定与多行为触发
Expand All @@ -57,7 +57,7 @@ MIP 提供了 `on` 属性来定义对组件的事件绑定与事件触发时的
<input id="input-element"
on="
tap:
input-element.scrollTo(duration=500, position='center'),
input-element.scrollTo({ duration: 500, position: 'center' }),
MIP.setData({ clicked: clicked + 1 });
change:
MIP.setData({ value: event.value })
Expand Down Expand Up @@ -165,12 +165,14 @@ MIP 为所有元素(包括普通 HTML 和 MIP 元素)都提供了一些默
|hide |隐藏元素。<br>如:`element-id.hide` |
|show |显示元素。<br>如:`element-id.show` |
|toggleVisibility |切换显示和隐藏元素。|
|toggleClass(<br>&nbsp;&nbsp;class=STRING,<br>&nbsp;&nbsp;force=BOOLEAN<br>) |切换元素类名。<br>参数 `force` 可选,如果为 true,则只添加类名。如果为 false,则只移除类名。<br> 如:`element-id.toggleClass(class='active')`|
|scrollTo(<br>&nbsp;&nbsp;duration=INTEGER,<br>&nbsp;&nbsp;position=STRING<br>)|视口滚动到元素所在位置。<br>参数 `duration` 可选,用于指定动画时间,单位 ms,默认是 0。<br>参数 `position` 可选,只可取 `top``center` 或者 `bottom`,用于指定滚动后元素在视口的位置,默认是 `top`。<br>如:`element-id.scrollTo(duration=500, position='center')`|
|toggleClass({<br>&nbsp;&nbsp;class: STRING,<br>&nbsp;&nbsp;force: BOOLEAN<br>}) |切换元素类名。<br>参数 `force` 可选,如果为 true,则只添加类名。如果为 false,则只移除类名。<br> 如:`element-id.toggleClass({class: 'active'})`|
|scrollTo({<br>&nbsp;&nbsp;duration: INTEGER,<br>&nbsp;&nbsp;position: STRING<br>})|视口滚动到元素所在位置。<br>参数 `duration` 可选,用于指定动画时间,单位 ms,默认是 0。<br>参数 `position` 可选,只可取 `top``center` 或者 `bottom`,用于指定滚动后元素在视口的位置,默认是 `top`。<br>如:`element-id.scrollTo({duration: 500, position: 'center'})`|
|focus |让元素获得焦点。<br>如:`element-id.focus`|

[notice] 当 MIP 组件自定义方法与全局元素方法重名的情况下,比如 mip-toggle 具有自定义行为 `show``hide`,此时优先触发组件的自定义方法。

[info] 在参数写法上,我们兼容了 AMP 的语法,因此也可以使用类似 AMP 的书写方式传入参数:`element-id.toggleClass(class='active', force=false)`

下面是全局元素方法的一些例子:

#### 隐藏或显示元素
Expand Down Expand Up @@ -207,7 +209,7 @@ MIP 为所有元素(包括普通 HTML 和 MIP 元素)都提供了一些默
<!-- 无法通过 text2.show 方法显示通过 display: none 定义样式的元素 -->
<button on="tap:text2.show">无法显示文字</button>
<!-- 通过 toggleClass 添加或移除 .hide 实现元素的隐藏或显示 -->
<button on="tap:text2.toggleClass(class='hide')">添加/移除 hidden class</button>
<button on="tap:text2.toggleClass({class: 'hide'})">添加/移除 hidden class</button>
<!-- .hide { display: none; } -->
<p id="text2" class="hide">文字2</p>
```
Expand All @@ -223,7 +225,7 @@ MIP 为所有元素(包括普通 HTML 和 MIP 元素)都提供了一些默
<!-- 无法通过 text2.show 方法显示通过 display: none 定义样式的元素 -->
<button on="tap:text2.show" class="example-button">无法显示文字</button>
<!-- 通过 toggleClass 添加或移除 .hide 实现元素的隐藏或显示 -->
<button on="tap:text2.toggleClass(class='hide')" class="example-button">添加/移除 hidden class</button>
<button on="tap:text2.toggleClass({class: 'hide'})" class="example-button">添加/移除 hidden class</button>
<!-- .hide { display: none; } -->
<p id="text2" class="hide">文字2</p>
</div>
Expand All @@ -232,15 +234,15 @@ MIP 为所有元素(包括普通 HTML 和 MIP 元素)都提供了一些默

```html
<!-- 点击滚动到页面底部 -->
<button on="tap:bootm-button.scrollTo(duration=500, position='center')">点击滚动到底部</button>
<button on="tap:bootm-button.scrollTo({ duration: 500, position: 'center' })">点击滚动到底部</button>
```
效果如下所示:

<div class="example-wrapper">
<button id="scroll-button"
on="tap:
bottom-example.show,
bottom-button.scrollTo(duration=500, position='center')"
bottom-button.scrollTo({ duration: 500, position: 'center' })"
class="example-button">点击滚动到底部</button>
</div>

Expand Down Expand Up @@ -271,12 +273,14 @@ MIP 为所有元素(包括普通 HTML 和 MIP 元素)都提供了一些默
|行为|描述|
|---|---|
|setData({<br>&nbsp;&nbsp;[name]: Expression<br>}) |将数据合并到到全局状态树中,结合数据绑定,写入数据时允许写有限的计算表达式进行运算。<br>更多内容请参考[数据绑定](./data-binding/mip-bind.md)<br>如:`MIP.setData({ a: 1 + 1, b: 'hello' })`|
|navigateTo(<br>&nbsp;&nbsp;url=STRING,<br>&nbsp;&nbsp;target=STRING,<br>&nbsp;&nbsp;opener=BOOLEAN<br>) |跳转到指定 `url` 页面。<br>参数 `url` 为必填参数,要跳转到的目标页面 URL<br>参数 `target` 为必填参数,只可取 `_top``_blank`。<br>`opener` 为可选参数,用于指定在 `target=_blank` 时新打开的页面能否访问到 `window.opener`。<br>如:`MIP.navigateTo(url='https://www.baidu.com', target='_blank')`|
|closeOrNavigateTo(<br>&nbsp;&nbsp;url=STRING, <br>&nbsp;&nbsp;target=STRING,<br>&nbsp;&nbsp;opener=BOOLEAN<br>)|关闭当前页面,如果失败则如 `navigateTo` 跳转。一般用作新打开页面的后退操作。<br>参数说明与示例用法同上。|
|scrollTo(<br>&nbsp;&nbsp;id=STRING,<br>&nbsp;&nbsp;duration=INTEGER,<br>&nbsp;&nbsp;position=STRING<br>) |视口滚动到 `id` 元素的位置,类似于全局元素方法 `element-id.scrollTo`。<br>参数 `id` 为必填参数,用于指定要滚动到的元素<br>参数 `duration` 为可选参数<br>参数 `position` 为可选参数。|
|navigateTo({<br>&nbsp;&nbsp;url: STRING,<br>&nbsp;&nbsp;target: STRING,<br>&nbsp;&nbsp;opener: BOOLEAN<br>}) |跳转到指定 `url` 页面。<br>参数 `url` 为必填参数,要跳转到的目标页面 URL<br>参数 `target` 为必填参数,只可取 `_top``_blank`。<br>`opener` 为可选参数,用于指定在 `target=_blank` 时新打开的页面能否访问到 `window.opener`。<br>如:`MIP.navigateTo({ url: 'https://www.baidu.com', target: '_blank' })`|
|closeOrNavigateTo({<br>&nbsp;&nbsp;url: STRING, <br>&nbsp;&nbsp;target: STRING,<br>&nbsp;&nbsp;opener: BOOLEAN<br>})|关闭当前页面,如果失败则如 `navigateTo` 跳转。一般用作新打开页面的后退操作。<br>参数说明与示例用法同上。|
|scrollTo({<br>&nbsp;&nbsp;id: STRING,<br>&nbsp;&nbsp;duration: INTEGER,<br>&nbsp;&nbsp;position: STRING<br>}) |视口滚动到 `id` 元素的位置,类似于全局元素方法 `element-id.scrollTo`。<br>参数 `id` 为必填参数,用于指定要滚动到的元素<br>参数 `duration` 为可选参数<br>参数 `position` 为可选参数。|
|goBack |返回上一个页面,效果等同于 `window.history.back()`<br>如:`MIP.goBack`|
|print |打开当前页面的打印对话框<br>如:`MIP.print`|

[info] 在参数写法上,我们兼容了 AMP 的语法,因此也可以使用类似 AMP 的书写方式传入参数:`MIP.navigateTo(url='https://www.baidu.com', target='_blank')`

下面是一些 MIP 方法的一些使用示例:

#### MIP.setData
Expand Down Expand Up @@ -316,22 +320,22 @@ MIP 为所有元素(包括普通 HTML 和 MIP 元素)都提供了一些默
需要说明的是,在通常情况下,应优先使用 `<a href="xxx"></a>` 的形式实现页面跳转,因为 a 链的形式更有利于搜索引擎的抓取和分析。

```html
<button on="tap:MIP.navigateTo(url='https://www.mipengine.org', target='_blank', opener=true)">在新页面打开 mip 官网</button>
<button on="tap:MIP.closeOrNavigateTo(url='https://www.mipengine.org', target='_blank', opener=true)">关闭页面或者打开 mip 官网</button>
<button on="tap:MIP.navigateTo({ url: 'https://www.mipengine.org', target: '_blank', opener: true })">在新页面打开 mip 官网</button>
<button on="tap:MIP.closeOrNavigateTo({ url: 'https://www.mipengine.org', target: '_blank', opener: true })">关闭页面或者打开 mip 官网</button>
```
效果如下所示:

<div class="example-wrapper">
<button class="example-button" on="tap:MIP.navigateTo(url='https://www.mipengine.org', target='_blank', opener=true)">在新页面打开 mip 官网</button>
<button class="example-button" on="tap:MIP.closeOrNavigateTo(url='https://www.mipengine.org', target='_blank', opener=true)">关闭页面或者打开 mip 官网</button>
<button class="example-button" on="tap:MIP.navigateTo({ url: 'https://www.mipengine.org', target: '_blank', opener: true })">在新页面打开 mip 官网</button>
<button class="example-button" on="tap:MIP.closeOrNavigateTo({ url: 'https://www.mipengine.org', target: '_blank', opener: true })">关闭页面或者打开 mip 官网</button>

</div>

#### MIP.scrollTo


```html
<button on="tap:MIP.scrollTo(id='top-example', duration=500, position='center')">滚动到顶部 id 为 top-button 的按钮处</button>
<button on="tap:MIP.scrollTo({ id: 'top-example', duration: 500, position: 'center' })">滚动到顶部 id 为 top-button 的按钮处</button>
```

效果如下所示:
Expand All @@ -342,7 +346,7 @@ MIP 为所有元素(包括普通 HTML 和 MIP 元素)都提供了一些默
id="mip-scrollto-button"
on="tap:
top-example.show,
MIP.scrollTo(id='top-button', duration=500, position='center')"
MIP.scrollTo({ id: 'top-button', duration: 500, position: 'center' })"
>滚动到顶部 id 为 top-button 的按钮处</button>
</div>
Expand Down Expand Up @@ -392,11 +396,11 @@ mip-action-macro 主要提供的功能包括:
<mip-action-macro
id="macro-id"
condition="event.url === baidu"
on="execute:MIP.navigateTo(url=protocol + event.url, target='_blank')"
on="execute:MIP.navigateTo({ url: protocol + event.url, target: '_blank' })"
></mip-action-macro>

<button on="tap:macro-id.execute(url=baidu)">点击跳转至百度首页</button>
<button on="tap:macro-id.execute(url=mipengine)">点击不会发生任何跳转</button>
<button on="tap:macro-id.execute({ url: baidu })">点击跳转至百度首页</button>
<button on="tap:macro-id.execute({ url: mipengine })">点击不会发生任何跳转</button>
```

效果如下所示:
Expand All @@ -416,11 +420,11 @@ mip-action-macro 主要提供的功能包括:
<mip-action-macro
id="macro-id"
condition="event.url === baidu"
on="execute:MIP.navigateTo(url=protocol + event.url, target='_blank')"
on="execute:MIP.navigateTo({ url: protocol + event.url, target: '_blank' })"
></mip-action-macro>
<button class="example-button" on="tap:macro-id.execute(url=baidu)">点击跳转至百度首页</button>
<button class="example-button" on="tap:macro-id.execute(url=mipengine)">点击不会发生任何跳转</button>
<button class="example-button" on="tap:macro-id.execute({ url: baidu })">点击跳转至百度首页</button>
<button class="example-button" on="tap:macro-id.execute({ url: mipengine })">点击不会发生任何跳转</button>

</div>

Expand All @@ -431,7 +435,7 @@ mip-action-macro 主要提供的功能包括:
class="example-button"
on="tap:
bottom-example.hide,
scroll-button.scrollTo(duration=500, position='center')"
scroll-button.scrollTo({ duration: 500, position: 'center' })"
>点击返回原示例</button>
</div>
Expand Down
20 changes: 3 additions & 17 deletions docs/docs/interactive-mip/expression.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ MIP 支持有限的运算符,利用这些运算符的相互组合,基本能
|类型|说明|示例|
|---|----|---|
|`( expr )`| 分组运算符(小括号) | `1 + (2 - 3)` |
| `{ attr: vaue }` | 字面量对象 | `{a: 1, b: 2, c: 3 + 4}` |
| `{ attr: value }` | 字面量对象 | `{a: 1, b: 2, c: 3 + 4}` |
| `{ [ expr ]: value }` | 可计算属性名的字面量对象 | `{ ['a' + 'bc']: 3 + 4}` |
| `[ item, item ]` | 字面量数组 | `[2, 1, 3]` |
|`expr . attr`| 属性运算符(点运算符) | `userInfo.name` |
|`expr[ expr ]`| 计算属性 | `userInfo['name']` |
Expand Down Expand Up @@ -118,7 +119,7 @@ MIP 还支持使用部分原型链方法,比如下面举例的一些常见的
|----|----|----|
|Array|concat <br>filter <br>indexOf <br>join <br>lastIndexOf <br>map <br>reduce <br>slice <br>some <br>every <br>find <br>sort(修改) <br>splice(修改)| 为了提升 MIP 表达式中的数组操作体验,我们修改了 sort 和 splice 方法,这两个方法将不会对原数组造成影响。<br>其中 sort 将返回排序后的新数组;<br>同时 splice 返回进行插入或删除操作之后的新数组。 <br> `// 返回新的对象 [1, 2, 3]` <br> `[2, 1, 3].sort()`<br> `// 返回新的对象 [1, 3]` <br> `[1, 2, 3].splice(1, 1)` <br> `// false` <br> `[1, 2, 3].some(num => num > 4)` <br> |
|Number|toExponential<br>toFixed<br>toPrecision<br>toString| `// 返回 1.2` <br> `(1.23).toFixed(1)`|
|String|charAt <br>charCodeAt <br>concat <br>indexOf <br>lastIndexOf <br>slice <br>split <br>substr <br>substring <br>toLowerCase <br>toUpperCase | `// 返回 ['1', '2', '3']` <br> `'123'.split()` |
|String|charAt <br>charCodeAt <br>concat <br>indexOf <br>lastIndexOf <br>slice <br>split <br>substr <br>substring <br>toLowerCase <br>toUpperCase <br>trim| `// 返回 ['1', '2', '3']` <br> `'123'.split()` |

## 函数表达式

Expand Down Expand Up @@ -170,18 +171,3 @@ MIP 还支持使用部分原型链方法,比如下面举例的一些常见的
[1, 2, 3].map(item => item++)
```
















13 changes: 5 additions & 8 deletions docs/docs/interactive-mip/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@ MIP 提供了为数众多的官方组件来满足开发者的需求。这些组

```html
<button
on="tap:MIP.navigateTo(url='https://www.baidu.com', target='_blank')"
on="tap:MIP.navigateTo({url: 'https://www.baidu.com', target: '_blank'})"
>点击打开百度首页</button>

<button
on="tap:bottom-item.scrollTo(duration=500, position='center')"
on="tap:bottom-item.scrollTo({duration: 500, position: 'center'})"
>点击跳转到页面底部</button>
```

Expand All @@ -54,13 +54,13 @@ MIP 提供了为数众多的官方组件来满足开发者的需求。这些组
<div class="example-wrapper">
<button
class="example-button"
on="tap:MIP.navigateTo(url='https://www.baidu.com', target='_blank')"
on="tap:MIP.navigateTo({url: 'https://www.baidu.com', target: '_blank'})"
>点击打开百度首页</button>
<button
id="scroll-button"
class="example-button"
on="tap:bottom-button.scrollTo(duration=500, position='center')"
on="tap:bottom-button.scrollTo({duration: 500, position: 'center'})"
>点击跳转到页面底部</button>
</div>
Expand Down Expand Up @@ -205,10 +205,7 @@ MIP 交互机制旨在提升 MIP 页面的可交互性,在 MIP 核心机制和
<p>您已滚动至页面底部</p>
<button class="example-button"
id="bottom-button"
on="tap:scroll-button.scrollTo(duration=1000, position='center')"
on="tap:scroll-button.scrollTo({duration: 1000, position: 'center'})"
>点击滚回原示例</button>
</div>



54 changes: 34 additions & 20 deletions packages/mip/src/util/event-action/grammar/basic.js
Original file line number Diff line number Diff line change
Expand Up @@ -223,10 +223,29 @@ export const $variable = lex.set({
}
})

export const $computedProperty = lex.set({
type: 'ComputedProperty',
rule: () => [
$leftBracket,
_,
$conditional,
_,
$rightBracket
],
match (args) {
return {
type: 'Member',
computed: true,
property: args[2]
}
}
})

export const $property = lex.set({
type: 'Property',
rule: () => [
[or, [
$computedProperty,
$identifier,
$string,
$number
Expand All @@ -237,10 +256,23 @@ export const $property = lex.set({
$conditional
],
match (args) {
return {
key: args[0],
let key = args[0]
let result = {
value: args[4]
}

if (key.computed) {
result.computed = true
result.key = key.property
} else {
result.key = key
}

return result
// return {
// key: args[0],
// value: args[4]
// }
}
})

Expand Down Expand Up @@ -310,24 +342,6 @@ export const $primary = lex.set({
]]
})

export const $computedProperty = lex.set({
type: 'ComputedProperty',
rule: () => [
$leftBracket,
_,
$conditional,
_,
$rightBracket
],
match (args) {
return {
type: 'Member',
computed: true,
property: args[2]
}
}
})

export const $identifierProperty = lex.set({
type: 'IdentifierProperty',
rule: [
Expand Down
14 changes: 12 additions & 2 deletions packages/mip/src/util/event-action/grammar/event-argument.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ import {
or,
any,
opt
// ,
// def
} from '../../parser/lexer'

import {
Expand All @@ -20,6 +18,7 @@ import {

import {
$conditional,
$object,
$number,
$literal,
$variable,
Expand Down Expand Up @@ -162,12 +161,23 @@ export const $mipActionOldArguments = lex.set({
}
})

export const $mipActionObjectArguments = lex.set({
type: 'MIPActionObjectArguments',
rule: $object,
match (args) {
return {
arguments: [args]
}
}
})

export const $mipActionArguments = lex.set({
type: 'MIPActionArguments',
rule: [
_,
[opt,
[or, [
$mipActionObjectArguments,
$mipActionOldArguments,
$mipActionNewArguments
]]
Expand Down
3 changes: 2 additions & 1 deletion packages/mip/src/util/event-action/whitelist/basic.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ export const PROTOTYPE = {
substr: String.prototype.substr,
substring: String.prototype.substring,
toLowerCase: String.prototype.toLowerCase,
toUpperCase: String.prototype.toUpperCase
toUpperCase: String.prototype.toUpperCase,
trim: String.prototype.trim
}
}

Expand Down
Loading

0 comments on commit 3ef6a9b

Please sign in to comment.