Skip to content

Commit 6e98d19

Browse files
authored
8.27 核心上线 (#690)
* 单页跳转透传 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 支持
1 parent 98c1468 commit 6e98d19

File tree

19 files changed

+662
-235
lines changed

19 files changed

+662
-235
lines changed

docs/docs/interactive-mip/data-binding/global-data-definition.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ MIP 提供 SPA 的整站沉浸式的体验,如果要打造复杂的业务场
206206
2. 如果要修改的数据字段仅为页面数据,将不影响共享数据
207207

208208
如:在 C 页面调用
209-
`MIP.setData({'name': 'name-c'})`
209+
`MIP.setData({'name': 'new-c'})`
210210

211211
此时 C 页面可用的数据源为
212212
```json

docs/docs/interactive-mip/data-binding/mip-bind.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -247,13 +247,13 @@ export default {
247247
let selected = MIP.getData('selected')
248248
let index = selected.indexOf(newVal)
249249

250-
if (index) {
250+
if (index !== -1) {
251251
selected.splice(index, 1)
252252
} else {
253-
selected.push(index)
253+
selected.push(newVal)
254254
}
255255

256-
MIP.setData('selectedStr', selected.join(','))
256+
MIP.setData({'selectedStr': selected.join(',')})
257257
})
258258
</mip-script>
259259
```

packages/mip/src/components/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import MipCarousel from './mip-carousel'
1212
import MipIframe from './mip-iframe'
1313
import MipPix from './mip-pix'
1414
import mipBindInit from './mip-bind/init'
15+
import MipDataWatch from './mip-bind/mip-data-watch'
1516
import MipData from './mip-bind/mip-data'
1617
import MipShell from './mip-shell/index'
1718
import MipFixed from './mip-fixed/index'
@@ -34,7 +35,7 @@ export default {
3435
registerElement('mip-video', MipVideo)
3536
registerElement('mip-fixed', MipFixed)
3637
mipBindInit()
37-
// new MipBind()
38+
registerElement('mip-data-watch', MipDataWatch)
3839
registerElement('mip-data', MipData)
3940
isMIPShellDisabled() || registerElement('mip-shell', MipShell)
4041
}

packages/mip/src/components/mip-bind/binding-attr.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,10 @@ export function bindingAttr (node, key, value, oldValue) {
2828
}
2929

3030
let attr = key.slice(prefixLen)
31-
3231
let prop = typeof value === 'object' ? JSON.stringify(value) : value
3332
if (prop === oldValue) {
3433
return prop
3534
}
36-
3735
if (prop === '' || prop === undefined) {
3836
node.removeAttribute(attr)
3937
} else {
@@ -44,7 +42,6 @@ export function bindingAttr (node, key, value, oldValue) {
4442
} else if (BOOLEAN_ATTRS.indexOf(attr) > -1) {
4543
node[attr] = !!prop
4644
}
47-
4845
return prop
4946
}
5047

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/**
2+
* @file dom-watcher.js
3+
* @author clark-t ([email protected])
4+
*/
5+
6+
import { isElementNode } from '../../util/dom/dom'
7+
import {
8+
traverse
9+
} from '../../util/fn'
10+
11+
import {
12+
isBindingAttr
13+
} from './binding'
14+
15+
class DOMWatcher {
16+
constructor () {
17+
this.doms = []
18+
this.watchers = []
19+
}
20+
21+
watch (watcher) {
22+
this.watchers.push(watcher)
23+
}
24+
25+
add (doms) {
26+
for (let dom of doms) {
27+
this.doms.push(dom)
28+
}
29+
}
30+
31+
remove (doms) {
32+
let tmps = doms.slice()
33+
for (let i = this.doms.length - 1; i > -1; i--) {
34+
for (let j = tmps.length - 1; j > -1; j--) {
35+
if (this.doms[i].node === tmps[j].node) {
36+
this.doms.splice(i, 1)
37+
tmps.splice(j, 1)
38+
break
39+
}
40+
}
41+
}
42+
}
43+
44+
update ({add: domList}) {
45+
let bindings = []
46+
47+
for (let dom of domList) {
48+
uniqueMerge(bindings, queryBindings(dom))
49+
}
50+
51+
let changed = diffBindingDOMs(this.doms, bindings)
52+
53+
this.remove(changed.removed)
54+
this.add(changed.add)
55+
56+
for (let watcher of this.watchers) {
57+
watcher(changed, this.doms)
58+
}
59+
}
60+
}
61+
62+
function uniqueMerge (oldList, newList) {
63+
for (let i = 0; i < newList.length; i++) {
64+
let len = oldList.length
65+
let j = 0
66+
for (j = 0; j < len; j++) {
67+
if (oldList[j].node === newList[i].node) {
68+
break
69+
}
70+
}
71+
if (j === len) {
72+
oldList.push(newList[i])
73+
}
74+
}
75+
return oldList
76+
}
77+
78+
function createBindingNodeWrapper (node, attrs) {
79+
let wrapper = { node, attrs }
80+
if (attrs) {
81+
wrapper.keys = Object.keys(attrs)
82+
}
83+
return wrapper
84+
}
85+
86+
function queryBindings (root) {
87+
let results = []
88+
traverse(root, node => {
89+
/* istanbul ignore if */
90+
if (!isElementNode(node)) {
91+
return
92+
}
93+
let attrs = queryBindingAttrs(node)
94+
attrs && results.push(createBindingNodeWrapper(node, attrs))
95+
if (node.children) {
96+
return Array.from(node.children)
97+
}
98+
})
99+
return results
100+
}
101+
102+
function queryBindingAttrs (node) {
103+
let attrs
104+
for (let i = 0; i < node.attributes.length; i++) {
105+
let attr = node.attributes[i]
106+
if (!isBindingAttr(attr.name)) {
107+
continue
108+
}
109+
attrs = attrs || {}
110+
attrs[attr.name] = {expr: attr.value}
111+
}
112+
return attrs
113+
}
114+
115+
function diffBindingDOMs (storeList, newList) {
116+
let output = {
117+
removed: [],
118+
add: newList.slice()
119+
}
120+
121+
for (let i = storeList.length - 1; i > -1; i--) {
122+
let stored = storeList[i]
123+
if (!document.contains(stored.node)) {
124+
output.removed.push(stored)
125+
continue
126+
}
127+
128+
for (let j = output.add.length - 1; j > -1; j--) {
129+
if (stored.node === newList[j].node) {
130+
output.add.splice(j, 1)
131+
break
132+
}
133+
}
134+
}
135+
136+
return output
137+
}
138+
139+
export const instance = new DOMWatcher()
140+
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
* @file binding-value.js
3+
* @author clark-t ([email protected])
4+
*/
5+
6+
import { throttle } from '../../util/fn'
7+
import { createSetDataObject } from './util'
8+
9+
export function addInputListener (add, store) {
10+
const key = 'm-bind:value'
11+
12+
const FORM_ELEMENTS = [
13+
'INPUT',
14+
'TEXTAREA',
15+
'SELECT'
16+
]
17+
18+
for (let info of add) {
19+
let {node, attrs} = info
20+
if (FORM_ELEMENTS.indexOf(node.tagName) === -1) {
21+
// if (!FORM_ELEMENTS.includes(node.tagName)) {
22+
continue
23+
}
24+
25+
let expression = attrs[key] && attrs[key].expr
26+
27+
if (!expression) {
28+
continue
29+
}
30+
31+
const properties = expression.split('.')
32+
const inputThrottle = throttle(function (e) {
33+
let obj = createSetDataObject(properties, e.target.value)
34+
store.set(obj)
35+
}, 100)
36+
node.addEventListener('input', inputThrottle)
37+
}
38+
}
39+

packages/mip/src/components/mip-bind/data-store.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import DataWatcher from './data-watcher'
77
import GlobalData from './global-data'
88
import { merge, getProperty } from './util'
99
import { isObject } from '../../util/fn'
10+
1011
export default class DataStore {
1112
constructor () {
1213
const storage = {}

0 commit comments

Comments
 (0)