Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
菜鸟程序猿_c
uni-app
提交
6b4164fe
U
uni-app
项目概览
菜鸟程序猿_c
/
uni-app
与 Fork 源项目一致
Fork自
DCloud / uni-app
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
U
uni-app
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1
Issue
1
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
6b4164fe
编写于
10月 22, 2019
作者:
fxy060608
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
refactor(v3)
上级
04d653a1
变更
23
展开全部
隐藏空白更改
内联
并排
Showing
23 changed file
with
3194 addition
and
3286 deletion
+3194
-3286
packages/uni-app-plus/dist/index.v3.js
packages/uni-app-plus/dist/index.v3.js
+109
-92
packages/uni-app-plus/dist/service.runtime.esm.js
packages/uni-app-plus/dist/service.runtime.esm.js
+81
-92
packages/uni-app-plus/dist/view.umd.js
packages/uni-app-plus/dist/view.umd.js
+2504
-2492
packages/uni-template-compiler/__tests__/compiler-app-plus-extra.service.spec.js
...ompiler/__tests__/compiler-app-plus-extra.service.spec.js
+11
-11
packages/uni-template-compiler/__tests__/compiler-app-plus-extra.view.spec.js
...e-compiler/__tests__/compiler-app-plus-extra.view.spec.js
+1
-1
packages/uni-template-compiler/__tests__/compiler-app-plus.service.spec.js
...late-compiler/__tests__/compiler-app-plus.service.spec.js
+86
-86
packages/uni-template-compiler/__tests__/demo.js
packages/uni-template-compiler/__tests__/demo.js
+1
-1
packages/uni-template-compiler/lib/app/optimizer.js
packages/uni-template-compiler/lib/app/optimizer.js
+25
-2
packages/uni-template-compiler/lib/app/parser/base-parser.js
packages/uni-template-compiler/lib/app/parser/base-parser.js
+68
-0
packages/uni-template-compiler/lib/app/parser/text-parser.js
packages/uni-template-compiler/lib/app/parser/text-parser.js
+2
-11
packages/uni-template-compiler/lib/app/service.js
packages/uni-template-compiler/lib/app/service.js
+76
-258
packages/uni-template-compiler/lib/app/util.js
packages/uni-template-compiler/lib/app/util.js
+8
-5
packages/uni-template-compiler/lib/app/view.js
packages/uni-template-compiler/lib/app/view.js
+42
-108
packages/uni-template-compiler/lib/util.js
packages/uni-template-compiler/lib/util.js
+7
-2
src/platforms/app-plus/constants.js
src/platforms/app-plus/constants.js
+5
-0
src/platforms/app-plus/service/constants.js
src/platforms/app-plus/service/constants.js
+4
-1
src/platforms/app-plus/service/framework/page.js
src/platforms/app-plus/service/framework/page.js
+5
-2
src/platforms/app-plus/service/framework/plugins/data.js
src/platforms/app-plus/service/framework/plugins/data.js
+33
-22
src/platforms/app-plus/service/framework/plugins/vdom-sync.js
...platforms/app-plus/service/framework/plugins/vdom-sync.js
+47
-54
src/platforms/app-plus/service/framework/subscribe-handlers.js
...latforms/app-plus/service/framework/subscribe-handlers.js
+25
-16
src/platforms/app-plus/view/framework/plugins/data.js
src/platforms/app-plus/view/framework/plugins/data.js
+5
-4
src/platforms/app-plus/view/framework/plugins/event.js
src/platforms/app-plus/view/framework/plugins/event.js
+7
-9
src/platforms/app-plus/view/framework/plugins/vdom-sync.js
src/platforms/app-plus/view/framework/plugins/vdom-sync.js
+42
-17
未找到文件。
packages/uni-app-plus/dist/index.v3.js
浏览文件 @
6b4164fe
...
...
@@ -252,6 +252,8 @@ var serviceContext = (function () {
return
hasOwnProperty
.
call
(
obj
,
key
)
}
function
noop
()
{}
function
toRawType
(
val
)
{
return
_toString
.
call
(
val
).
slice
(
8
,
-
1
)
}
...
...
@@ -3591,7 +3593,10 @@ var serviceContext = (function () {
const
V_FOR
=
'
f
'
;
const
V_IF
=
'
i
'
;
const
V_ELSE_IF
=
'
e
'
;
const
V_SHOW
=
'
v-show
'
;
const
V_SHOW
=
'
v-show
'
;
const
B_CLASS
=
'
c
'
;
const
B_STYLE
=
'
s
'
;
const
callbacks
=
{};
const
WEB_INVOKE_APPSERVICE
=
'
WEB_INVOKE_APPSERVICE
'
;
...
...
@@ -6350,8 +6355,11 @@ var serviceContext = (function () {
const
UPDATED_DATA
=
6
;
const
PAGE_CREATED
=
10
;
const
UI_EVENT
=
20
;
const
VD_SYNC
=
'
vdSync
'
;
const
WEBVIEW_READY
=
'
webviewReady
'
;
const
WEBVIEW_UI_EVENT
=
'
webviewUIEvent
'
;
const
VD_SYNC_CALLBACK
=
'
vdSyncCallback
'
;
const
pageFactory
=
Object
.
create
(
null
);
...
...
@@ -6474,7 +6482,7 @@ var serviceContext = (function () {
const
pageId
=
webview
.
id
;
// 通知页面已开始创建
UniServiceJSBridge
.
publishHandler
(
'
vdSync
'
,
{
UniServiceJSBridge
.
publishHandler
(
VD_SYNC
,
{
data
:
[
[
PAGE_CREATE
,
[
pageId
,
route
]]
],
...
...
@@ -6484,7 +6492,9 @@ var serviceContext = (function () {
},
[
pageId
]);
try
{
createPage
(
route
,
pageId
,
query
,
pageInstance
).
$mount
();
}
catch
(
e
)
{}
}
catch
(
e
)
{
console
.
error
(
e
);
}
}
}
...
...
@@ -8740,31 +8750,37 @@ var serviceContext = (function () {
}
}
const
webviewUIEvent
s
=
Object
.
create
(
null
);
const
vdSyncHandler
s
=
Object
.
create
(
null
);
function
register
WebviewUIEvent
(
pageId
,
callback
)
{
(
webviewUIEvents
[
pageId
]
||
(
webviewUIEvent
s
[
pageId
]
=
[])).
push
(
callback
);
function
register
VdSync
(
pageId
,
callback
)
{
(
vdSyncHandlers
[
pageId
]
||
(
vdSyncHandler
s
[
pageId
]
=
[])).
push
(
callback
);
}
function
remove
WebviewUIEvent
(
pageId
)
{
delete
webviewUIEvent
s
[
pageId
];
function
remove
VdSync
(
pageId
)
{
delete
vdSyncHandler
s
[
pageId
];
}
function
on
WebviewUIEvent
({
function
on
VdSync
({
data
,
options
},
pageId
)
{
const
{
cid
,
nid
}
=
options
;
const
handlers
=
webviewUIEvents
[
pageId
];
const
handlers
=
vdSyncHandlers
[
pageId
];
if
(
Array
.
isArray
(
handlers
))
{
handlers
.
forEach
(
handler
=>
{
handler
(
cid
,
nid
,
data
);
handler
(
data
);
});
}
else
{
console
.
error
(
`events[
${
pageId
}
] not found`
);
console
.
error
(
`vdSync[
${
pageId
}
] not found`
);
}
}
const
vdSyncCallbacks
=
[];
// 数据同步 callback
function
onVdSyncCallback
()
{
const
copies
=
vdSyncCallbacks
.
slice
(
0
);
vdSyncCallbacks
.
length
=
0
;
for
(
let
i
=
0
;
i
<
copies
.
length
;
i
++
)
{
copies
[
i
]();
}
}
...
...
@@ -8779,7 +8795,9 @@ var serviceContext = (function () {
});
// TODO 检测目标 preloadWebview 是否已准备好,因为 preloadWebview 准备好时,此处代码还没执行
subscribe
(
WEBVIEW_READY
,
onWebviewReady
);
subscribe
(
WEBVIEW_UI_EVENT
,
onWebviewUIEvent
);
subscribe
(
VD_SYNC
,
onVdSync
);
subscribe
(
VD_SYNC_CALLBACK
,
onVdSyncCallback
);
}
let
appCtx
;
...
...
@@ -8975,109 +8993,99 @@ var serviceContext = (function () {
};
}
function
noop
()
{}
const
handleVdData
=
{
[
UI_EVENT
]:
function
onUIEvent
(
vdBatchEvent
,
vd
)
{
vdBatchEvent
.
forEach
(([
cid
,
nid
,
event
])
=>
{
console
.
log
(
`[EVENT]`
,
cid
,
nid
,
event
);
event
.
preventDefault
=
noop
;
event
.
stopPropagation
=
noop
;
const
target
=
vd
.
elements
.
find
(
target
=>
target
.
cid
===
cid
&&
target
.
nid
===
nid
);
if
(
!
target
)
{
return
console
.
error
(
`event handler[
${
cid
}
][
${
nid
}
] not found`
)
}
target
.
dispatchEvent
(
event
.
type
,
event
);
});
}
};
const
callbacks$a
=
[];
// 数据同步 callback
function
onVdSync$1
(
vdBatchData
,
vd
)
{
vdBatchData
.
forEach
(([
type
,
vdData
])
=>
{
handleVdData
[
type
](
vdData
,
vd
);
});
}
class
VDomSync
{
constructor
(
pageId
,
pagePath
)
{
constructor
(
pageId
,
pagePath
)
{
this
.
pageId
=
pageId
;
this
.
pagePath
=
pagePath
;
this
.
batchData
=
[];
this
.
vms
=
Object
.
create
(
null
);
this
.
initialized
=
false
;
// 事件
this
.
handlers
=
Object
.
create
(
null
);
this
.
elements
=
[];
// 目前仅存储事件 element
this
.
_init
();
}
_init
()
{
UniServiceJSBridge
.
subscribe
(
VD_SYNC_CALLBACK
,
()
=>
{
const
copies
=
callbacks$a
.
slice
(
0
);
callbacks$a
.
length
=
0
;
for
(
let
i
=
0
;
i
<
copies
.
length
;
i
++
)
{
copies
[
i
]();
}
});
registerWebviewUIEvent
(
this
.
pageId
,
(
cid
,
nid
,
event
)
=>
{
console
.
log
(
`[EVENT]`
,
cid
,
nid
,
event
);
event
.
preventDefault
=
noop
;
event
.
stopPropagation
=
noop
;
if
(
this
.
handlers
[
cid
]
&&
this
.
handlers
[
cid
][
nid
]
&&
this
.
handlers
[
cid
][
nid
][
event
.
type
]
)
{
this
.
handlers
[
cid
][
nid
][
event
.
type
].
forEach
(
handler
=>
{
handler
(
event
);
});
}
else
{
console
.
error
(
`event handler[
${
cid
}
][
${
nid
}
][
${
event
.
type
}
] not found`
);
}
_init
()
{
registerVdSync
(
this
.
pageId
,
(
vdBatchData
)
=>
{
onVdSync$1
(
vdBatchData
,
this
);
});
}
addMountedVm
(
vm
)
{
addMountedVm
(
vm
)
{
vm
.
_$mounted
();
// 触发vd数据同步
this
.
add
Callback
(
function
mounted
()
{
this
.
add
VdSyncCallback
(
function
mounted
()
{
vm
.
__call_hook
(
'
mounted
'
);
});
}
addUpdatedVm
(
vm
)
{
addUpdatedVm
(
vm
)
{
vm
.
_$updated
();
// 触发vd数据同步
this
.
add
Callback
(
function
mounted
()
{
this
.
add
VdSyncCallback
(
function
mounted
()
{
vm
.
__call_hook
(
'
updated
'
);
});
}
add
Callback
(
callback
)
{
isFn
(
callback
)
&&
callbacks$a
.
push
(
callback
);
add
VdSyncCallback
(
callback
)
{
isFn
(
callback
)
&&
vdSyncCallbacks
.
push
(
callback
);
}
getVm
(
id
)
{
getVm
(
id
)
{
return
this
.
vms
[
id
]
}
addVm
(
vm
)
{
addVm
(
vm
)
{
this
.
vms
[
vm
.
_$id
]
=
vm
;
}
removeVm
(
vm
)
{
removeVm
(
vm
)
{
delete
this
.
vms
[
vm
.
_$id
];
}
addEvent
(
cid
,
nid
,
name
,
handler
)
{
const
cHandlers
=
this
.
handlers
[
cid
]
||
(
this
.
handlers
[
cid
]
=
Object
.
create
(
null
));
const
nHandlers
=
cHandlers
[
nid
]
||
(
cHandlers
[
nid
]
=
Object
.
create
(
null
));
(
nHandlers
[
name
]
||
(
nHandlers
[
name
]
=
[])).
push
(
handler
);
addElement
(
elm
)
{
this
.
elements
.
indexOf
(
elm
)
===
-
1
&&
this
.
elements
.
push
(
elm
);
}
removeEvent
(
cid
,
nid
,
name
,
handler
)
{
const
cHandlers
=
this
.
handlers
[
cid
]
||
(
this
.
handlers
[
cid
]
=
Object
.
create
(
null
));
const
nHandlers
=
cHandlers
[
nid
]
||
(
cHandlers
[
nid
]
=
Object
.
create
(
null
));
const
eHandlers
=
nHandlers
[
name
];
if
(
Array
.
isArray
(
eHandlers
))
{
const
index
=
eHandlers
.
indexOf
(
handler
);
if
(
index
!==
-
1
)
{
eHandlers
.
splice
(
index
,
1
);
}
removeElement
(
elm
)
{
const
elmIndex
=
this
.
elements
.
indexOf
(
elm
);
if
(
elmIndex
===
-
1
)
{
return
console
.
error
(
`removeElement[
${
elm
.
cid
}
][
${
elm
.
nid
}
] not found`
)
}
this
.
elements
.
splice
(
elmIndex
,
1
);
}
push
(
type
,
nodeI
d
,
data
)
{
this
.
batchData
.
push
([
type
,
[
nodeI
d
,
data
]]);
push
(
type
,
ci
d
,
data
)
{
this
.
batchData
.
push
([
type
,
[
ci
d
,
data
]]);
}
flush
()
{
flush
()
{
if
(
!
this
.
initialized
)
{
this
.
initialized
=
true
;
this
.
batchData
.
push
([
PAGE_CREATED
,
[
this
.
pageId
,
this
.
pagePath
]]);
}
if
(
this
.
batchData
.
length
)
{
UniServiceJSBridge
.
publishHandler
(
'
vdSync
'
,
{
UniServiceJSBridge
.
publishHandler
(
VD_SYNC
,
{
data
:
this
.
batchData
,
options
:
{
timestamp
:
Date
.
now
()
...
...
@@ -9087,12 +9095,12 @@ var serviceContext = (function () {
}
}
destroy
()
{
destroy
()
{
this
.
batchData
.
length
=
0
;
this
.
vms
=
Object
.
create
(
null
);
this
.
initialized
=
false
;
this
.
handlers
=
Object
.
create
(
null
)
;
remove
WebviewUIEvent
(
this
.
pageId
);
this
.
elements
.
length
=
0
;
remove
VdSync
(
this
.
pageId
);
}
}
...
...
@@ -9159,10 +9167,17 @@ var serviceContext = (function () {
if
(
!
this
.
_$vd
)
{
return
}
// TODO 自定义组件中的 slot 数据采集是在组件内部,导致所在 context 中无法获取到差量数据
// 如何保证每个 vm 数据有变动,就加入 diff 中呢?
// 每次变化,可能触发多次 beforeUpdate,updated
// 子组件 updated 时,可能会增加父组件的 diffData,如 slot 等情况
diff
(
this
.
_$newData
,
this
.
_$data
,
this
.
_$vdUpdatedData
);
this
.
_$data
=
JSON
.
parse
(
JSON
.
stringify
(
this
.
_$newData
));
console
.
log
(
`[
${
this
.
_$id
}
] updated `
+
Date
.
now
());
this
.
_$vd
.
initialized
&&
this
.
$nextTick
(
this
.
_$vd
.
flush
.
bind
(
this
.
_$vd
));
// setTimeout 一下再 nextTick( 直接 nextTick 的话,会紧接着该 updated 做 flush,导致父组件 updated 数据被丢弃)
this
.
_$vd
.
initialized
&&
setTimeout
(()
=>
{
this
.
$nextTick
(
this
.
_$vd
.
flush
.
bind
(
this
.
_$vd
));
},
0
);
};
Object
.
defineProperty
(
Vue
.
prototype
,
'
_$vd
'
,
{
...
...
@@ -9188,7 +9203,6 @@ var serviceContext = (function () {
this
.
_$vdMountedData
=
Object
.
create
(
null
);
this
.
_$setData
(
MOUNTED_DATA
,
this
.
_$vdMountedData
);
console
.
log
(
`[
${
this
.
_$id
}
] beforeCreate `
+
Date
.
now
());
// 目前全量采集做 diff(iOS 需要保留全量状态做 restore),理论上可以差量采集
this
.
_$data
=
Object
.
create
(
null
);
this
.
_$newData
=
Object
.
create
(
null
);
}
...
...
@@ -9212,20 +9226,23 @@ var serviceContext = (function () {
});
}
function
setData
(
id
,
name
,
value
)
{
const
diffData
=
this
.
_$newData
[
id
]
||
(
this
.
_$newData
[
id
]
=
{});
if
(
typeof
name
!==
'
string
'
)
{
for
(
let
key
in
name
)
{
diffData
[
key
]
=
name
[
key
];
}
return
name
function
setData
(
id
,
name
,
value
)
{
switch
(
name
)
{
case
B_CLASS
:
value
=
this
.
_$stringifyClass
(
value
);
break
case
B_STYLE
:
value
=
this
.
_$normalizeStyleBinding
(
value
);
break
case
V_IF
:
case
V_ELSE_IF
:
value
=
!!
value
;
break
case
V_FOR
:
return
setForData
.
call
(
this
,
id
,
value
)
}
if
(
name
===
'
a-_i
'
)
{
return
value
}
return
(
diffData
[
name
]
=
value
)
return
((
this
.
_$newData
[
id
]
||
(
this
.
_$newData
[
id
]
=
{}))[
name
]
=
value
)
}
function
setForData
(
id
,
value
)
{
...
...
@@ -9250,11 +9267,11 @@ var serviceContext = (function () {
}
function
setIfData
(
id
,
value
)
{
return
((
this
.
_$newData
[
id
]
||
(
this
.
_$newData
[
id
]
=
{}))[
V_IF
]
=
value
)
return
((
this
.
_$newData
[
id
]
||
(
this
.
_$newData
[
id
]
=
{}))[
V_IF
]
=
!!
value
)
}
function
setElseIfData
(
id
,
value
)
{
return
((
this
.
_$newData
[
id
]
||
(
this
.
_$newData
[
id
]
=
{}))[
V_ELSE_IF
]
=
value
)
return
((
this
.
_$newData
[
id
]
||
(
this
.
_$newData
[
id
]
=
{}))[
V_ELSE_IF
]
=
!!
value
)
}
/* @flow */
...
...
packages/uni-app-plus/dist/service.runtime.esm.js
浏览文件 @
6b4164fe
...
...
@@ -5514,28 +5514,58 @@ var noop$1 = {};
var
UniElement
=
function
UniElement
(
tagName
)
{
this
.
tagName
=
tagName
;
this
.
attrs
=
Object
.
create
(
null
);
this
.
cid
=
''
;
this
.
nid
=
''
;
this
.
events
=
Object
.
create
(
null
);
};
UniElement
.
prototype
.
setAttribute
=
function
setAttribute
(
key
,
value
)
{
this
.
attrs
[
key
]
=
value
;
if
(
key
===
'
cid
'
)
{
this
.
cid
=
value
;
}
else
if
(
key
===
'
nid
'
)
{
this
.
nid
=
value
;
}
};
UniElement
.
prototype
.
dispatchEvent
=
function
dispatchEvent
(
name
,
target
)
{
var
handlers
=
this
.
events
[
name
];
if
(
!
handlers
)
{
console
.
error
((
"
cid=
"
+
(
this
.
cid
)
+
"
,nid=
"
+
(
this
.
nid
)
+
"
dispatchEvent(
"
+
name
+
"
) not found
"
));
}
handlers
.
forEach
(
function
(
handler
)
{
handler
(
target
);
});
};
UniElement
.
prototype
.
addEventListener
=
function
addEventListener
(
name
,
handler
)
{
var
ref
=
this
.
attrs
;
var
cid
=
ref
.
cid
;
var
nid
=
ref
.
nid
;
if
(
!
cid
||
!
nid
)
{
return
console
.
error
((
"
cid=
"
+
cid
+
"
,nid=
"
+
nid
+
"
addEventListener(
"
+
name
+
"
) not found
"
))
if
(
this
.
cid
===
''
||
this
.
nid
===
''
)
{
return
console
.
error
((
"
cid=
"
+
(
this
.
cid
)
+
"
,nid=
"
+
(
this
.
nid
)
+
"
addEventListener(
"
+
name
+
"
) not found
"
))
}
this
.
_$vd
.
addEvent
(
cid
,
nid
,
name
,
handler
);
(
this
.
events
[
name
]
||
(
this
.
events
[
name
]
=
[])).
push
(
handler
);
this
.
_$vd
.
addElement
(
this
);
};
UniElement
.
prototype
.
removeEventListener
=
function
removeEventListener
(
name
,
handler
)
{
var
ref
=
this
.
attrs
;
var
cid
=
ref
.
cid
;
var
nid
=
ref
.
nid
;
if
(
!
cid
||
!
nid
)
{
return
console
.
error
((
"
cid=
"
+
cid
+
"
,nid=
"
+
nid
+
"
removeEventListener(
"
+
name
+
"
) not found
"
))
UniElement
.
prototype
.
removeEventListener
=
function
removeEventListener
(
name
,
handler
)
{
var
this
$1
=
this
;
if
(
this
.
cid
===
''
||
this
.
nid
===
''
)
{
return
console
.
error
((
"
cid=
"
+
(
this
.
cid
)
+
"
,nid=
"
+
(
this
.
nid
)
+
"
removeEventListener(
"
+
name
+
"
) not found
"
))
}
this
.
_$vd
.
removeEvent
(
cid
,
nid
,
name
,
handler
);
var
isRemoved
=
false
;
if
(
this
.
events
[
name
])
{
var
handlerIndex
=
this
.
events
[
name
].
indexOf
(
handler
);
if
(
handlerIndex
!==
-
1
)
{
this
.
events
[
name
].
splice
(
handlerIndex
,
1
);
isRemoved
=
true
;
}
}
if
(
!
isRemoved
)
{
console
.
error
((
"
cid=
"
+
(
this
.
cid
)
+
"
,nid=
"
+
(
this
.
nid
)
+
"
removeEventListener(
"
+
name
+
"
) handler not found
"
));
}
Object
.
keys
(
this
.
events
).
every
(
function
(
eventType
)
{
return
this
$1
.
events
[
eventType
].
length
===
0
;
})
&&
this
.
_$vd
.
removeElement
(
this
);
};
function
createElement$1
(
tagName
)
{
...
...
@@ -6631,7 +6661,14 @@ function updateDOMListeners (oldVnode, vnode) {
var
on
=
vnode
.
data
.
on
||
{};
var
oldOn
=
oldVnode
.
data
.
on
||
{};
target$1
=
vnode
.
elm
;
target$1
.
_$vd
=
vnode
.
context
.
_$vd
;
// fixed by xxxxxx 存储 vd
// fixed by xxxxxx 存储 vd
target$1
.
_$vd
=
vnode
.
context
.
_$vd
;
var
context
=
vnode
.
context
;
// 存储事件标记
target$1
.
setAttribute
(
'
nid
'
,
String
(
vnode
.
data
.
attrs
[
'
_i
'
]));
target$1
.
setAttribute
(
'
cid
'
,
context
.
_$id
);
normalizeEvents
(
on
);
updateListeners
(
on
,
oldOn
,
add$1
,
remove$2
,
createOnceHandler$1
,
vnode
.
context
);
target$1
=
undefined
;
...
...
@@ -6642,6 +6679,31 @@ var events = {
update
:
updateDOMListeners
};
var
platformModules
=
[
events
];
/* */
// the directive module should be applied last, after all
// built-in modules have been applied.
var
modules
=
platformModules
.
concat
(
baseModules
);
var
patch
=
createPatchFunction
({
nodeOps
:
nodeOps
,
modules
:
modules
});
var
show
=
{
bind
:
function
bind
()
{},
update
:
function
update
()
{},
unbind
:
function
unbind
()
{}
};
var
platformDirectives
=
{
show
:
show
};
var
platformComponents
=
{
};
/* */
function
stringifyClass
(
value
)
{
...
...
@@ -6707,82 +6769,6 @@ function normalizeStyleBinding (bindingStyle) {
return
bindingStyle
}
function
updateExtras
(
oldVnode
,
vnode
)
{
var
attrs
=
vnode
.
data
.
attrs
;
var
extras
=
vnode
.
data
.
extras
;
var
isExtrasUndef
=
isUndef
(
extras
);
if
(
isExtrasUndef
&&
isUndef
(
attrs
))
{
return
}
var
elm
=
vnode
.
elm
;
var
context
=
vnode
.
context
;
var
id
=
attrs
[
'
_i
'
];
// 存储事件标记
elm
.
setAttribute
(
'
nid
'
,
String
(
id
));
elm
.
setAttribute
(
'
cid
'
,
context
.
_$id
);
if
(
(
isExtrasUndef
||
Object
.
keys
(
extras
).
length
===
0
)
&&
Object
.
keys
(
attrs
).
length
===
1
)
{
return
}
var
$s
=
vnode
.
context
.
_$s
.
bind
(
vnode
.
context
);
if
(
extras
)
{
if
(
extras
[
'
c
'
])
{
extras
[
'
c
'
]
=
stringifyClass
(
extras
[
'
c
'
]);
}
if
(
extras
[
'
s
'
])
{
extras
[
'
s
'
]
=
normalizeStyleBinding
(
extras
[
'
s
'
]);
}
for
(
var
key
in
extras
)
{
$s
(
id
,
key
,
extras
[
key
]);
}
}
if
(
attrs
)
{
for
(
var
key$1
in
attrs
)
{
key$1
!==
'
_i
'
&&
$s
(
id
,
'
a-
'
+
key$1
,
attrs
[
key$1
]);
}
}
}
var
extras
=
{
create
:
updateExtras
,
update
:
updateExtras
};
var
platformModules
=
[
extras
,
// 在前,设置 cid,nid
events
];
/* */
// the directive module should be applied last, after all
// built-in modules have been applied.
var
modules
=
platformModules
.
concat
(
baseModules
);
var
patch
=
createPatchFunction
({
nodeOps
:
nodeOps
,
modules
:
modules
});
var
platformDirectives
=
{
};
var
platformComponents
=
{
};
function
callHook$2
(
hook
,
args
)
{
var
vm
=
this
;
// #7573 disable dep collection when invoking lifecycle hooks
...
...
@@ -6810,6 +6796,9 @@ var plugin = {
};
Vue
.
prototype
.
__call_hook
=
callHook$2
;
// 运行时需要格式化 class,style
Vue
.
prototype
.
_$stringifyClass
=
stringifyClass
;
Vue
.
prototype
.
_$normalizeStyleBinding
=
normalizeStyleBinding
;
}
};
...
...
packages/uni-app-plus/dist/view.umd.js
浏览文件 @
6b4164fe
此差异已折叠。
点击以展开。
packages/uni-template-compiler/__tests__/compiler-app-plus-extra.service.spec.js
浏览文件 @
6b4164fe
...
...
@@ -15,53 +15,53 @@ describe('codegen', () => {
it
(
'
generate block
'
,
()
=>
{
assertCodegen
(
'
<block v-if="show"></block>
'
,
`with(this){return (_$
i(0
,show))?void 0:_e()}`
`with(this){return (_$
s(0,'i'
,show))?void 0:_e()}`
)
assertCodegen
(
'
<div><block v-for="item in items"><div></div><div></div></block></div>
'
,
`with(this){return _c('div',[_l((_$
f(1,{forItems:items})),function(item,$10,$20,$30){return [_c('div',{key:_$f(1,{forIndex:$20,keyIndex:0,key:1+'-0'+$30})}),_c('div',{key:_$f(1
,{forIndex:$20,keyIndex:1,key:1+'-1'+$30})})]})],2)}`
`with(this){return _c('div',[_l((_$
s(1,'f',{forItems:items})),function(item,$10,$20,$30){return [_c('div',{key:_$s(1,'f',{forIndex:$20,keyIndex:0,key:1+'-0'+$30})}),_c('div',{key:_$s(1,'f'
,{forIndex:$20,keyIndex:1,key:1+'-1'+$30})})]})],2)}`
)
assertCodegen
(
'
<div><block v-for="item in items" :key="item.id"><div></div><div></div></block></div>
'
,
`with(this){return _c('div',[_l((_$
f(1,{forItems:items})),function(item,$10,$20,$30){return [_c('div',{key:_$f(1,{forIndex:$20,keyIndex:0,key:item.id+'_0'})}),_c('div',{key:_$f(1
,{forIndex:$20,keyIndex:1,key:item.id+'_1'})})]})],2)}`
`with(this){return _c('div',[_l((_$
s(1,'f',{forItems:items})),function(item,$10,$20,$30){return [_c('div',{key:_$s(1,'f',{forIndex:$20,keyIndex:0,key:item.id+'_0'})}),_c('div',{key:_$s(1,'f'
,{forIndex:$20,keyIndex:1,key:item.id+'_1'})})]})],2)}`
)
})
it
(
'
generate directive
'
,
()
=>
{
assertCodegen
(
'
<p v-custom1:[arg1].modifier="value1" v-custom2></p>
'
,
`with(this){return _c('p',{
extras:{"v-custom1":value1,"v-custom1-arg":arg1}
,attrs:{"_i":0}})}`
`with(this){return _c('p',{
directives:[{name:"custom1",rawName:"v-custom1:[arg1].modifier",value:(_$s(0,'v-custom1',value1)),expression:"_$s(0,'v-custom1',value1)",arg:_$s(0,'v-custom1-arg',arg1),modifiers:{"modifier":true}},{name:"custom2",rawName:"v-custom2"}]
,attrs:{"_i":0}})}`
)
})
it
(
'
generate v-for directive
'
,
()
=>
{
assertCodegen
(
'
<div><template v-for="item in items"><div></div><div></div></template></div>
'
,
`with(this){return _c('div',[_l((_$
f(1,{forItems:items})),function(item,$10,$20,$30){return [_c('div',{key:_$f(1,{forIndex:$20,keyIndex:0,key:1+'-0'+$30})}),_c('div',{key:_$f(1
,{forIndex:$20,keyIndex:1,key:1+'-1'+$30})})]})],2)}`
`with(this){return _c('div',[_l((_$
s(1,'f',{forItems:items})),function(item,$10,$20,$30){return [_c('div',{key:_$s(1,'f',{forIndex:$20,keyIndex:0,key:1+'-0'+$30})}),_c('div',{key:_$s(1,'f'
,{forIndex:$20,keyIndex:1,key:1+'-1'+$30})})]})],2)}`
)
assertCodegen
(
'
<div><template v-for="item in items">text</template></div>
'
,
`with(this){return _c('div',[_l((_$
f(1,{forItems:items})),function(item,$10,$20,$30){return [_c('text',{key:_$f(1,{forIndex:$20,keyIndex:0,key:1+'-0'+$30}),attrs:{"_i":("1-"+$30)}})]
})],2)}`
`with(this){return _c('div',[_l((_$
s(1,'f',{forItems:items})),function(item,$10,$20,$30){return void 0
})],2)}`
)
assertCodegen
(
'
<div><template v-for="item in items">{{text}}</template></div>
'
,
`with(this){return _c('div',[_l((_$
f(1,{forItems:items})),function(item,$10,$20,$30){return [_c('text',{key:_$f(1,{forIndex:$20,keyIndex:0,key:1+'-0'+$30}),extras:{t0:_s(text)},attrs:{"_i":("1-"+$30)}}
)]})],2)}`
`with(this){return _c('div',[_l((_$
s(1,'f',{forItems:items})),function(item,$10,$20,$30){return [_v((_$s(("1-"+$30),'t0',_s(text)))
)]})],2)}`
)
assertCodegen
(
'
<div><template v-for="item in items"><span></span>{{text}}</template></div>
'
,
`with(this){return _c('div',[_l((_$
f(1,{forItems:items})),function(item,$10,$20,$30){return [_c('span',{key:_$f(1,{forIndex:$20,keyIndex:0,key:1+'-0'+$30})}),_c('text',{extras:{t0:_s(text)},attrs:{"_i":("1-"+$30)}}
)]})],2)}`
`with(this){return _c('div',[_l((_$
s(1,'f',{forItems:items})),function(item,$10,$20,$30){return [_c('span',{key:_$s(1,'f',{forIndex:$20,keyIndex:0,key:1+'-0'+$30})}),_v((_$s(("1-"+$30),'t0',_s(text)))
)]})],2)}`
)
assertCodegen
(
'
<div><template v-for="item in items">a {{text1}} b {{text2}}</template></div>
'
,
`with(this){return _c('div',[_l((_$
f(1,{forItems:items})),function(item,$10,$20,$30){return [_c('text',{key:_$f(1,{forIndex:$20,keyIndex:0,key:1+'-0'+$30}),extras:{t0:_s(text1),t1:_s(text2)},attrs:{"_i":("1-"+$30)}}
)]})],2)}`
`with(this){return _c('div',[_l((_$
s(1,'f',{forItems:items})),function(item,$10,$20,$30){return [_v((_$s(("1-"+$30),'t0',_s(text1)))+(_$s(("1-"+$30),'t1',_s(text2)))
)]})],2)}`
)
assertCodegen
(
'
<div><template v-for="item in items"><span v-if="item.sub"></span></template></div>
'
,
`with(this){return _c('div',[_l((_$
f(1,{forItems:items})),function(item,$10,$20,$30){return [(_$i(("2-"+$30),item.sub))?_c('span',{key:_$f(1
,{forIndex:$20,keyIndex:0,key:1+'-0'+$30})}):_e()]})],2)}`
`with(this){return _c('div',[_l((_$
s(1,'f',{forItems:items})),function(item,$10,$20,$30){return [(_$s(("2-"+$30),'i',item.sub))?_c('span',{key:_$s(1,'f'
,{forIndex:$20,keyIndex:0,key:1+'-0'+$30})}):_e()]})],2)}`
)
})
it
(
'
generate text with multiple statements
'
,
()
=>
{
assertCodegen
(
'
<div>A{{ d | e | f }}B{{text}}C</div>
'
,
`with(this){return _c('div',[_
c('text',{extras:{t0:_s(_f("f")(_f("e")(d))),t1:_s(text)},attrs:{"_i":0}}
)])}`
`with(this){return _c('div',[_
v((_$s(0,'t0',_s(_f("f")(_f("e")(d)))))+(_$s(0,'t1',_s(text)))
)])}`
)
})
})
...
...
packages/uni-template-compiler/__tests__/compiler-app-plus-extra.view.spec.js
浏览文件 @
6b4164fe
...
...
@@ -37,7 +37,7 @@ describe('codegen', () => {
it
(
'
generate slot fallback content
'
,
()
=>
{
assertCodegen
(
'
<div><slot><div>{{hi}}</div></slot></div>
'
,
`with(this){return _c('v-uni-view',{attrs:{"_i":0}},[_t("default",[_c('v-uni-view',{attrs:{"_i":2}},[_v((_$g(2,'t0'
,1
)))])],{"_i":1})],2)}`
`with(this){return _c('v-uni-view',{attrs:{"_i":0}},[_t("default",[_c('v-uni-view',{attrs:{"_i":2}},[_v((_$g(2,'t0')))])],{"_i":1})],2)}`
)
})
})
...
...
packages/uni-template-compiler/__tests__/compiler-app-plus.service.spec.js
浏览文件 @
6b4164fe
此差异已折叠。
点击以展开。
packages/uni-template-compiler/__tests__/demo.js
浏览文件 @
6b4164fe
const
compiler
=
require
(
'
../lib
'
)
const
res
=
compiler
.
compile
(
`
<
p slot="one">hello world</p
>
<
my-component v-model="\n test \n" /
>
`
,
{
resourcePath
:
'
/User/fxy/Documents/test.wxml
'
,
isReservedTag
:
function
(
tag
)
{
...
...
packages/uni-template-compiler/lib/app/optimizer.js
浏览文件 @
6b4164fe
const
{
ID
,
isVar
}
=
require
(
'
./util
'
)
const
{
isComponent
}
=
require
(
'
../util
'
)
let
isPlatformReservedTag
function
no
(
a
,
b
,
c
)
{
...
...
@@ -17,7 +26,7 @@ function isStatic (node) {
if
(
node
.
type
===
3
)
{
return
true
}
if
(
node
.
dynamicClass
||
node
.
dynamicStyle
)
{
if
(
node
.
classBinding
||
node
.
styleBinding
)
{
return
false
}
return
!!
(
node
.
pre
||
(
...
...
@@ -39,7 +48,21 @@ function markStatic (node) {
}
delete
node
.
attrs
}
if
(
node
.
type
===
1
)
{
if
(
node
.
type
===
1
)
{
delete
node
.
staticClass
delete
node
.
staticStyle
if
(
node
.
attrs
&&
!
isComponent
(
node
.
tag
))
{
// 移除静态属性
node
.
attrs
=
node
.
attrs
.
filter
(
attr
=>
attr
.
name
===
ID
||
isVar
(
attr
.
value
))
}
node
.
children
=
node
.
children
.
filter
(
child
=>
{
// 移除静态文本
if
(
child
.
type
===
3
)
{
// ASTText
return
false
}
return
true
})
for
(
let
i
=
0
,
l
=
node
.
children
.
length
;
i
<
l
;
i
++
)
{
const
child
=
node
.
children
[
i
]
markStatic
(
child
)
...
...
packages/uni-template-compiler/lib/app/parser/base-parser.js
0 → 100644
浏览文件 @
6b4164fe
const
{
ID
,
V_IF
,
V_FOR
,
V_ELSE_IF
,
isVar
}
=
require
(
'
../util
'
)
const
parseTextExpr
=
require
(
'
./text-parser
'
)
function
parseIf
(
el
,
createGenVar
)
{
if
(
!
el
.
if
)
{
return
}
el
.
ifConditions
.
forEach
(
con
=>
{
if
(
isVar
(
con
.
exp
))
{
con
.
exp
=
createGenVar
(
con
.
block
.
attrsMap
[
ID
])(
con
.
block
.
elseif
?
V_ELSE_IF
:
V_IF
,
con
.
exp
)
}
})
el
.
if
=
createGenVar
(
el
.
attrsMap
[
ID
])(
V_IF
,
el
.
if
)
}
function
parseFor
(
el
,
createGenVar
)
{
if
(
el
.
for
&&
isVar
(
el
.
for
))
{
el
.
for
=
createGenVar
(
el
.
forId
)(
V_FOR
,
`{forItems:
${
el
.
for
}
}`
)
return
true
}
}
function
parseBinding
(
el
,
genVar
)
{
el
.
classBinding
&&
(
el
.
classBinding
=
genVar
(
'
c
'
,
el
.
classBinding
))
el
.
styleBinding
&&
(
el
.
styleBinding
=
genVar
(
'
s
'
,
el
.
styleBinding
))
}
function
parseDirs
(
el
,
genVar
)
{
el
.
directives
&&
el
.
directives
.
forEach
(
dir
=>
{
dir
.
value
&&
(
dir
.
value
=
genVar
(
'
v-
'
+
dir
.
name
,
dir
.
value
))
dir
.
isDynamicArg
&&
(
dir
.
arg
=
genVar
(
'
v-
'
+
dir
.
name
+
'
-arg
'
,
dir
.
arg
))
})
}
function
parseAttrs
(
el
,
genVar
)
{
el
.
attrs
&&
el
.
attrs
.
forEach
(
attr
=>
{
attr
.
name
!==
ID
&&
isVar
(
attr
.
value
)
&&
(
attr
.
value
=
genVar
(
'
a-
'
+
attr
.
name
,
attr
.
value
))
})
}
function
parseProps
(
el
,
genVar
)
{
el
.
props
&&
el
.
props
.
forEach
(
prop
=>
{
isVar
(
prop
.
value
)
&&
(
prop
.
value
=
genVar
(
'
a-
'
+
prop
.
name
,
prop
.
value
))
})
}
function
parseText
(
el
,
parent
,
state
)
{
// fixed by xxxxxx 注意:保持平台一致性,trim 一下
el
.
parent
&&
(
el
.
parent
=
parent
)
el
.
expression
=
parseTextExpr
(
el
.
text
.
trim
(),
false
,
state
).
expression
}
module
.
exports
=
{
parseIf
,
parseFor
,
parseText
,
parseDirs
,
parseAttrs
,
parseProps
,
parseBinding
}
packages/uni-template-compiler/lib/app/parser/text-parser.js
浏览文件 @
6b4164fe
...
...
@@ -28,7 +28,6 @@ module.exports = function parseText (
if
(
!
tagRE
.
test
(
text
))
{
return
}
const
dynamicTexts
=
[]
// fixed by xxxxxx
const
tokens
=
[]
const
rawTokens
=
[]
let
lastIndex
=
tagRE
.
lastIndex
=
0
...
...
@@ -44,14 +43,7 @@ module.exports = function parseText (
}
// tag token
const
exp
=
parseFilters
(
match
[
1
].
trim
())
if
(
state
.
service
)
{
dynamicTexts
.
push
({
name
:
`t
${
state
.
index
++
}
`
,
value
:
`_s(
${
exp
}
)`
})
}
else
{
tokens
.
push
(
`(
${
state
.
genVar
(
'
t
'
+
(
state
.
index
++
))}
)`
)
}
tokens
.
push
(
`(
${
state
.
genVar
(
'
t
'
+
(
state
.
index
++
),
'
_s(
'
+
exp
+
'
)
'
)}
)`
)
rawTokens
.
push
({
'
@binding
'
:
exp
})
...
...
@@ -65,7 +57,6 @@ module.exports = function parseText (
}
return
{
expression
:
tokens
.
join
(
'
+
'
),
tokens
:
rawTokens
,
dynamicTexts
tokens
:
rawTokens
}
}
packages/uni-template-compiler/lib/app/service.js
浏览文件 @
6b4164fe
const
{
ID
,
ITERATOR
,
V_FOR
,
SET_DATA
,
isVar
,
getForEl
,
processForKey
,
...
...
@@ -12,290 +13,87 @@ const {
isComponent
}
=
require
(
'
../util
'
)
const
parseText
=
require
(
'
./parser/text-parser
'
)
const
{
parseIf
,
parseFor
,
parseText
,
parseDirs
,
parseAttrs
,
parseProps
,
parseBinding
}
=
require
(
'
./parser/base-parser
'
)
const
parseEvent
=
require
(
'
./parser/event-parser
'
)
const
parseBlock
=
require
(
'
./parser/block-parser
'
)
const
p
reTransformNode
=
require
(
'
./pre-transform-node
'
)
const
baseP
reTransformNode
=
require
(
'
./pre-transform-node
'
)
const
optimize
=
require
(
'
./optimizer
'
)
function
genData
(
el
)
{
delete
el
.
$parentIterator3
const
{
events
,
dynamicClass
,
dynamicStyle
,
dynamicAttrs
,
dynamicTexts
,
directivesBinding
}
=
el
let
extras
=
''
if
(
directivesBinding
)
{
const
dirs
=
genDirectives
(
directivesBinding
)
dirs
&&
(
extras
+=
dirs
+
'
,
'
)
}
if
(
dynamicClass
)
{
extras
+=
genDynamicClass
(
dynamicClass
)
+
'
,
'
}
if
(
dynamicStyle
)
{
extras
+=
genDynamicStyle
(
dynamicStyle
)
+
'
,
'
}
if
(
dynamicTexts
)
{
extras
+=
genDynamicTexts
(
dynamicTexts
)
+
'
,
'
}
if
(
events
)
{
const
dynamicHandlers
=
genDynamicHandlers
(
events
)
dynamicHandlers
&&
(
extras
+=
dynamicHandlers
+
'
,
'
)
}
if
(
Array
.
isArray
(
dynamicAttrs
))
{
const
dynamicProps
=
genDynamicProps
(
dynamicAttrs
)
dynamicProps
&&
(
extras
+=
dynamicProps
+
'
,
'
)
}
extras
=
extras
.
replace
(
/,$/
,
''
)
if
(
extras
)
{
return
`extras:{
${
extras
}
},`
}
return
''
}
function
genDirectives
(
dirs
)
{
let
directives
=
[]
dirs
.
forEach
(
dir
=>
{
isVar
(
dir
.
value
)
&&
directives
.
push
(
`"v-
${
dir
.
name
}
":
${
dir
.
value
}
`
)
dir
.
isDynamicArg
&&
(
directives
.
push
(
`"v-
${
dir
.
name
}
-arg":
${
dir
.
arg
}
`
))
})
return
directives
.
join
(
'
,
'
)
}
function
genDynamicClass
(
classBinding
)
{
return
`c:
${
classBinding
}
`
}
function
genDynamicStyle
(
styleBinding
)
{
return
`s:
${
styleBinding
}
`
}
function
genDynamicTexts
(
dynamicTexts
)
{
return
dynamicTexts
.
map
(({
name
,
value
})
=>
{
return
`
${
name
}
:
${
value
}
`
}).
join
(
'
,
'
)
}
function
genDynamicHandlers
(
events
)
{
let
dynamicHandlers
=
[]
let
index
=
0
for
(
let
name
in
events
)
{
const
eventHandler
=
events
[
name
]
if
(
eventHandler
.
dynamic
)
{
eventHandler
.
index
=
index
++
dynamicHandlers
.
push
(
'
"de-
'
+
(
eventHandler
.
index
)
+
'
":
'
+
name
)
}
}
return
dynamicHandlers
.
join
(
'
,
'
)
}
function
genDynamicProps
(
props
,
prefix
=
'
da
'
)
{
let
dynamicProps
=
[]
let
index
=
0
for
(
let
i
=
0
;
i
<
props
.
length
;
i
++
)
{
const
{
name
,
value
,
dynamic
}
=
props
[
i
]
if
(
dynamic
)
{
props
[
i
].
index
=
index
++
dynamicProps
.
push
(
`"
${
prefix
}
-`
+
(
props
[
i
].
index
)
+
'
-n":
'
+
name
)
dynamicProps
.
push
(
`"
${
prefix
}
-`
+
(
props
[
i
].
index
)
+
'
-v":
'
+
value
)
}
}
return
dynamicProps
.
join
(
'
,
'
)
}
// if 使用该方案是因为 template 节点之类无法挂靠 extras
function
processIfConditions
(
el
)
{
if
(
el
.
if
)
{
el
.
ifConditions
.
forEach
(
con
=>
{
if
(
isVar
(
con
.
exp
))
{
const
method
=
con
.
block
.
elseif
?
'
_$e
'
:
'
_$i
'
con
.
exp
=
`
${
method
}
(
${
con
.
block
.
attrsMap
[
ID
]}
,
${
con
.
exp
}
)`
}
})
el
.
if
=
`_$i(
${
el
.
attrsMap
[
ID
]}
,
${
el
.
if
}
)`
}
}
function
removeStatic
(
el
)
{
delete
el
.
staticClass
delete
el
.
staticStyle
}
function
renameBinding
(
el
)
{
// 重命名 classBinding,styleBinding,避免生成 class,style 属性
if
(
el
.
classBinding
)
{
el
.
dynamicClass
=
el
.
classBinding
delete
el
.
classBinding
}
if
(
el
.
styleBinding
)
{
el
.
dynamicStyle
=
el
.
styleBinding
delete
el
.
styleBinding
function
createGenVar
(
id
)
{
return
function
genVar
(
name
,
value
)
{
return
`
${
SET_DATA
}
(
${
id
}
,'
${
name
}
',
${
value
}
)`
}
}
function
p
rocess
Key
(
el
)
{
function
p
arse
Key
(
el
)
{
// add default key
if
(
processForKey
(
el
))
{
el
=
el
.
children
[
0
]
// 当 template 下仅文本时,处理第一个动态文本
}
if
(
el
.
key
&&
(
el
.
key
.
indexOf
(
'
_$f
'
)
!==
0
&&
el
.
key
.
indexOf
(
'
_$s
'
)
!==
0
))
{
// renderList key
const
forEl
=
getForEl
(
el
)
if
(
forEl
)
{
if
(
!
isVar
(
forEl
.
for
))
{
return
}
const
forId
=
forEl
.
forId
const
it
=
forEl
.
iterator2
||
forEl
.
iterator1
||
ITERATOR
if
(
forEl
===
el
)
{
// <view v-for="item in items" :key="item.id"></view>
el
.
key
=
`_$f(
${
forId
}
,{forIndex:
${
it
}
,key:
${
el
.
key
}
})`
}
else
{
// <template v-for="item in items"><view :key="item.id+'1'"></view><view :key="item.id+'2'"></view></template>
const
keyIndex
=
forEl
.
children
.
indexOf
(
el
)
el
.
key
=
`_$f(
${
forId
}
,{forIndex:
${
it
}
,keyIndex:
${
keyIndex
}
,key:
${
el
.
key
}
})`
}
}
else
{
isVar
(
el
.
key
)
&&
(
el
.
key
=
`_$s(
${
el
.
attrsMap
[
ID
]}
,'a-key',
${
el
.
key
}
)`
)
}
if
(
!
el
.
key
||
el
.
key
.
indexOf
(
SET_DATA
)
===
0
)
{
return
}
}
function
processIf
(
el
)
{
processIfConditions
(
el
)
}
function
processDirs
(
el
)
{
if
(
el
.
directives
)
{
const
directivesBinding
=
[]
el
.
directives
=
el
.
directives
.
filter
(
dir
=>
{
directivesBinding
.
push
(
dir
)
if
(
dir
.
name
===
'
model
'
)
{
return
true
}
})
if
(
directivesBinding
.
length
)
{
el
.
directivesBinding
=
directivesBinding
}
if
(
!
el
.
directives
.
length
)
{
delete
el
.
directives
}
const
forEl
=
getForEl
(
el
)
if
(
!
forEl
)
{
isVar
(
el
.
key
)
&&
(
el
.
key
=
createGenVar
(
el
.
attrsMap
[
ID
])(
'
a-key
'
,
el
.
key
))
}
}
function
processDynamicText
(
el
,
state
)
{
el
.
type
=
1
el
.
tag
=
'
text
'
el
.
attrsList
=
[{
name
:
ID
,
value
:
state
.
id
}]
el
.
attrsMap
=
{
[
ID
]:
state
.
id
if
(
!
isVar
(
forEl
.
for
))
{
return
}
el
.
rawAttrsMap
=
{}
el
.
children
=
[]
el
.
plain
=
false
el
.
attrs
=
[{
name
:
ID
,
value
:
String
(
state
.
id
)
}]
el
.
hasBindings
=
true
if
(
el
.
text
)
{
// fixed by xxxxxx 注意:保持平台一致性,trim 一下
const
ret
=
parseText
(
el
.
text
.
trim
(),
false
,
state
)
if
(
ret
&&
ret
.
dynamicTexts
.
length
)
{
el
.
dynamicTexts
=
ret
.
dynamicTexts
}
const
forId
=
forEl
.
forId
const
it
=
forEl
.
iterator2
const
genVar
=
createGenVar
(
forId
)
if
(
forEl
===
el
)
{
// <view v-for="item in items" :key="item.id"></view>
el
.
key
=
genVar
(
V_FOR
,
`{forIndex:
${
it
}
,key:
${
el
.
key
}
}`
)
}
else
{
// <template v-for="item in items"><view :key="item.id+'1'"></view><view :key="item.id+'2'"></view></template>
const
keyIndex
=
forEl
.
children
.
indexOf
(
el
)
el
.
key
=
genVar
(
V_FOR
,
`{forIndex:
${
it
}
,keyIndex:
${
keyIndex
}
,key:
${
el
.
key
}
}`
)
}
delete
el
.
expression
delete
el
.
tokens
delete
el
.
text
return
el
}
function
processText
(
el
)
{
if
(
!
el
.
children
.
length
)
{
function
transformNode
(
el
,
parent
,
state
)
{
if
(
el
.
type
===
3
)
{
return
}
parseBlock
(
el
)
parseEvent
(
el
)
const
state
=
{
id
:
el
.
attrsMap
[
ID
],
index
:
0
,
service
:
true
}
el
.
children
=
el
.
children
.
filter
(
child
=>
{
if
(
child
.
type
===
3
)
{
// ASTText
return
false
}
else
if
(
child
.
type
===
2
&&
child
.
text
)
{
// ASTExpression
processDynamicText
(
child
,
state
)
child
.
parent
=
el
}
return
true
})
// <div><template v-for="item in items">item</template></div>
if
(
!
el
.
children
.
length
&&
el
.
tag
===
'
template
'
&&
el
.
for
)
{
el
.
children
.
push
(
processDynamicText
({
parent
:
el
},
state
))
}
}
function
processAttrs
(
el
)
{
if
(
!
isComponent
(
el
.
tag
))
{
// 自定义组件,不能移除静态 attr
el
.
attrs
=
el
.
attrs
.
filter
(
attr
=>
attr
.
name
===
ID
||
isVar
(
attr
.
value
))
}
}
updateForEleId
(
el
,
state
)
function
processFor
(
el
)
{
if
(
el
.
for
&&
isVar
(
el
.
for
))
{
el
.
for
=
`_$f(
${
el
.
forId
}
,{forItems:
${
el
.
for
}
})`
if
(
el
.
type
===
2
)
{
return
parseText
(
el
,
parent
,
{
index
:
0
,
service
:
true
,
// <uni-popup>{{content}}</uni-popup>
genVar
:
createGenVar
(
parent
.
attrsMap
[
ID
])
})
}
}
function
transformNode
(
el
,
parent
,
state
)
{
parseBlock
(
el
)
parseEvent
(
el
)
const
genVar
=
createGenVar
(
el
.
attrsMap
[
ID
])
removeStatic
(
el
)
renameBinding
(
el
)
parseFor
(
el
,
createGenVar
)
parseKey
(
el
)
processAttrs
(
el
)
processText
(
el
)
parseIf
(
el
,
createGenVar
)
parseBinding
(
el
,
genVar
)
parseDirs
(
el
,
genVar
)
updateForEleId
(
el
,
state
)
if
(
!
isComponent
(
el
.
tag
))
{
parseAttrs
(
el
,
genVar
)
}
processFor
(
el
)
processKey
(
el
)
processIf
(
el
)
processDirs
(
el
)
parseProps
(
el
,
genVar
)
}
function
postTransformNode
(
el
,
options
)
{
...
...
@@ -307,8 +105,28 @@ function postTransformNode (el, options) {
optimize
(
el
,
options
)
}
}
function
parseTag
(
el
)
{
if
(
el
.
tag
===
'
input
'
||
el
.
tag
===
'
textarea
'
)
{
el
.
tag
=
`c-
${
el
.
tag
.
substr
(
0
,
1
)}
`
// 返回一个自定义组件标签,保证 v-model
}
}
function
genData
(
el
)
{
delete
el
.
$parentIterator3
if
(
el
.
model
)
{
el
.
model
.
callback
=
`function ($$v) {}`
}
return
''
}
module
.
exports
=
{
preTransformNode
,
preTransformNode
:
function
(
el
,
options
)
{
parseTag
(
el
)
return
basePreTransformNode
(
el
,
options
)
},
postTransformNode
,
genData
}
}
packages/uni-template-compiler/lib/app/util.js
浏览文件 @
6b4164fe
...
...
@@ -4,8 +4,9 @@ const NUMBER_RE = /^-?\d*(\.\d+)?$/
const
ID
=
'
_i
'
const
ITERATOR1
=
'
$1
'
const
ITERATOR2
=
'
$2
'
const
ITERATOR3
=
'
$3
'
const
DATA_ROOT
=
'
_$g
'
const
ITERATOR3
=
'
$3
'
const
SET_DATA
=
'
_$s
'
const
GET_DATA
=
'
_$g
'
const
V_FOR
=
'
f
'
const
V_IF
=
'
i
'
...
...
@@ -110,7 +111,7 @@ function getForEl (el) {
function
processForKey
(
el
)
{
const
forEl
=
getForEl
(
el
)
if
(
forEl
&&
!
el
.
key
&&
!
el
.
dynamicTexts
)
{
// 占位的 text 标签也无需添加 key
if
(
forEl
&&
!
el
.
key
)
{
// 占位的 text 标签也无需添加 key
if
(
!
isVar
(
forEl
.
for
))
{
// <view v-for="10"></view>
return
}
...
...
@@ -120,7 +121,8 @@ function processForKey (el) {
const
keyIndex
=
forEl
.
children
.
indexOf
(
el
)
el
.
key
=
`
${
forEl
.
forId
}
+'-
${
keyIndex
}
'+
${
it
}
`
}
else
{
// 当 template 下只有文本节点
if
(
el
.
children
&&
el
.
children
.
length
&&
!
el
.
children
.
find
(
child
=>
child
.
key
))
{
if
(
el
.
children
&&
el
.
children
.
length
&&
!
el
.
children
.
find
(
child
=>
child
.
key
))
{
el
.
children
[
0
].
parent
=
el
el
.
children
[
0
].
key
=
`
${
forEl
.
forId
}
+'-0'+
${
it
}
`
return
true
}
...
...
@@ -149,7 +151,8 @@ module.exports = {
V_IF
,
V_ELSE_IF
,
ID
,
DATA_ROOT
,
SET_DATA
,
GET_DATA
,
isVar
,
hasOwn
,
addAttr
,
...
...
packages/uni-template-compiler/lib/app/view.js
浏览文件 @
6b4164fe
const
{
ID
,
DATA_ROOT
,
V_FOR
,
V_IF
,
V_ELSE_IF
,
GET_DATA
,
isVar
,
getForEl
,
updateForEleId
,
...
...
@@ -11,69 +8,30 @@ const {
traverseNode
}
=
require
(
'
./util
'
)
const
{
parseIf
,
parseFor
,
parseText
,
parseDirs
,
parseAttrs
,
parseProps
,
parseBinding
}
=
require
(
'
./parser/base-parser
'
)
const
parseTag
=
require
(
'
./parser/tag-parser
'
)
const
parseText
=
require
(
'
./parser/text-parser
'
)
const
parseEvent
=
require
(
'
./parser/event-parser
'
)
const
parseBlock
=
require
(
'
./parser/block-parser
'
)
const
parseComponent
=
require
(
'
./parser/component-parser
'
)
const
basePreTransformNode
=
require
(
'
./pre-transform-node
'
)
function
createGenVar
(
id
,
isInSlot
=
false
)
{
return
function
genVar
(
name
,
extra
=
''
)
{
const
isFallbackContent
=
isInSlot
?
'
,1
'
:
''
extra
=
extra
?
(
'
,
'
+
extra
)
:
''
return
`
${
DATA_ROOT
}
(
${
id
}
,'
${
name
}
'
${
isFallbackContent
}${
extra
}
)`
}
}
function
isInSlot
(
el
)
{
let
parent
=
el
.
parent
while
(
parent
)
{
if
(
parent
.
tag
===
'
slot
'
)
{
return
true
}
parent
=
parent
.
parent
}
return
false
}
// if 使用该方案是因为 template 节点之类无法挂靠 extras
function
processIfConditions
(
el
)
{
if
(
el
.
if
)
{
el
.
ifConditions
.
forEach
(
con
=>
{
if
(
isVar
(
con
.
exp
))
{
con
.
exp
=
createGenVar
(
con
.
block
.
attrsMap
[
ID
],
isInSlot
(
el
))(
con
.
block
.
elseif
?
V_ELSE_IF
:
V_IF
)
}
})
el
.
if
=
createGenVar
(
el
.
attrsMap
[
ID
],
isInSlot
(
el
))(
V_IF
)
}
}
function
processBinding
(
el
,
genVar
)
{
if
(
el
.
classBinding
)
{
el
.
classBinding
=
genVar
(
'
c
'
)
}
if
(
el
.
styleBinding
)
{
el
.
styleBinding
=
genVar
(
'
s
'
)
}
}
function
processFor
(
el
,
genVal
)
{
if
(
el
.
for
&&
isVar
(
el
.
for
))
{
el
.
for
=
createGenVar
(
el
.
forId
,
isInSlot
(
el
))(
V_FOR
)
// <div><li v-for=" { a, b } in items"></li></div>
// =>
// <div><li v-for="$item in items"></li></div>
if
(
el
.
alias
[
0
]
===
'
{
'
)
{
el
.
alias
=
'
$item
'
}
function
createGenVar
(
id
)
{
return
function
genVar
(
name
)
{
return
`
${
GET_DATA
}
(
${
id
}
,'
${
name
}
')`
}
}
function
p
rocess
Key
(
el
)
{
function
p
arse
Key
(
el
)
{
// add default key
processForKey
(
el
)
...
...
@@ -90,67 +48,44 @@ function processKey (el) {
el
.
key
=
`
${
forEl
.
alias
}
['k
${
keyIndex
}
']`
}
}
else
{
isVar
(
el
.
key
)
&&
(
el
.
key
=
createGenVar
(
el
.
attrsMap
[
ID
]
,
isInSlot
(
el
)
)(
'
a-key
'
))
isVar
(
el
.
key
)
&&
(
el
.
key
=
createGenVar
(
el
.
attrsMap
[
ID
])(
'
a-key
'
))
}
}
}
function
processIf
(
el
)
{
processIfConditions
(
el
)
}
function
processDirs
(
el
,
genVar
)
{
if
(
el
.
directives
)
{
el
.
directives
.
forEach
(
dir
=>
{
dir
.
value
&&
(
dir
.
value
=
genVar
(
'
v-
'
+
dir
.
name
))
dir
.
isDynamicArg
&&
(
dir
.
arg
=
genVar
(
'
v-
'
+
dir
.
name
+
'
-arg
'
))
})
}
}
function
processAttrs
(
el
,
genVar
)
{
el
.
attrs
.
forEach
(
attr
=>
{
attr
.
name
!==
ID
&&
isVar
(
attr
.
value
)
&&
(
attr
.
value
=
genVar
(
'
a-
'
+
attr
.
name
))
})
}
function
processProps
(
el
,
genVar
)
{
el
.
props
&&
el
.
props
.
forEach
(
prop
=>
{
isVar
(
prop
.
value
)
&&
(
prop
.
value
=
genVar
(
'
a-
'
+
prop
.
name
))
})
}
function
processText
(
el
,
parent
)
{
const
state
=
{
index
:
0
,
view
:
true
,
genVar
:
createGenVar
(
parent
.
attrsMap
[
ID
],
isInSlot
(
parent
))
}
// fixed by xxxxxx 注意:保持平台一致性,trim 一下
el
.
expression
=
parseText
(
el
.
text
.
trim
(),
false
,
state
).
expression
}
function
transformNode
(
el
,
parent
,
state
)
{
if
(
el
.
type
===
3
)
{
return
}
parseBlock
(
el
)
parseComponent
(
el
)
parseEvent
(
el
)
// 更新 id
updateForEleId
(
el
,
state
)
if
(
el
.
type
!==
1
)
{
return
(
el
.
type
===
2
&&
processText
(
el
,
parent
))
if
(
el
.
type
===
2
)
{
return
parseText
(
el
,
parent
,
{
index
:
0
,
view
:
true
,
// <uni-popup>{{content}}</uni-popup>
genVar
:
createGenVar
(
parent
.
attrsMap
[
ID
])
})
}
const
id
=
el
.
attrsMap
[
ID
]
const
genVar
=
createGenVar
(
id
,
isInSlot
(
el
))
const
genVar
=
createGenVar
(
el
.
attrsMap
[
ID
])
if
(
parseFor
(
el
,
createGenVar
))
{
if
(
el
.
alias
[
0
]
===
'
{
'
)
{
// <div><li v-for=" { a, b } in items"></li></div>
el
.
alias
=
'
$item
'
}
}
parseKey
(
el
)
processFor
(
el
,
genVar
)
processKey
(
el
)
processIf
(
el
)
processBinding
(
el
,
genVar
)
processDirs
(
el
,
genVar
)
processAttrs
(
el
,
genVar
)
processProps
(
el
,
genVar
)
parseIf
(
el
,
createGenVar
)
parseBinding
(
el
,
genVar
)
parseDirs
(
el
,
genVar
)
parseAttrs
(
el
,
genVar
)
parseProps
(
el
,
genVar
)
}
function
postTransformNode
(
el
)
{
...
...
@@ -162,7 +97,7 @@ function postTransformNode (el) {
}
}
function
process
Events
(
events
)
{
function
handleView
Events
(
events
)
{
Object
.
keys
(
events
).
forEach
(
name
=>
{
const
modifiers
=
Object
.
create
(
null
)
...
...
@@ -208,9 +143,8 @@ function genData (el) {
}
// 放在 postTransformNode 中处理的时机太靠前,v-model 等指令会新增 event
// 理想情况,应该移除自定义组件的 events 配置,但目前不太好准确确定是自定义组件
el
.
events
&&
processEvents
(
el
.
events
)
el
.
nativeEvents
&&
processEvents
(
el
.
nativeEvents
)
el
.
events
&&
handleViewEvents
(
el
.
events
)
el
.
nativeEvents
&&
handleViewEvents
(
el
.
nativeEvents
)
return
''
}
...
...
packages/uni-template-compiler/lib/util.js
浏览文件 @
6b4164fe
...
...
@@ -183,10 +183,15 @@ const {
}
=
require
(
'
./h5
'
)
function
isComponent
(
tagName
)
{
if
(
tagName
===
'
block
'
||
tagName
===
'
template
'
)
{
if
(
tagName
===
'
block
'
||
tagName
===
'
template
'
||
tagName
===
'
c-i
'
||
// v3 service input => c-i
tagName
===
'
c-t
'
// v3 service textarea => c-t
)
{
return
false
}
return
!
hasOwn
(
tags
,
getTagName
(
tagName
))
return
!
hasOwn
(
tags
,
getTagName
(
tagName
.
replace
(
'
v-uni-
'
,
''
)
))
}
module
.
exports
=
{
...
...
src/platforms/app-plus/constants.js
浏览文件 @
6b4164fe
...
...
@@ -2,8 +2,13 @@ export const PAGE_CREATE = 2
export
const
MOUNTED_DATA
=
4
export
const
UPDATED_DATA
=
6
export
const
PAGE_CREATED
=
10
export
const
UI_EVENT
=
20
export
const
LAYOUT_READY
=
30
export
const
VD_SYNC
=
'
vdSync
'
export
const
APP_SERVICE_ID
=
'
__uniapp__service
'
export
const
WEBVIEW_READY
=
'
webviewReady
'
...
...
src/platforms/app-plus/service/constants.js
浏览文件 @
6b4164fe
...
...
@@ -12,4 +12,7 @@ export const VIEW_WEBVIEW_PATH = '_www/__uniappview.html'
export
const
V_FOR
=
'
f
'
export
const
V_IF
=
'
i
'
export
const
V_ELSE_IF
=
'
e
'
export
const
V_SHOW
=
'
v-show
'
export
const
V_SHOW
=
'
v-show
'
export
const
B_CLASS
=
'
c
'
export
const
B_STYLE
=
'
s
'
src/platforms/app-plus/service/framework/page.js
浏览文件 @
6b4164fe
...
...
@@ -8,6 +8,7 @@ import {
}
from
'
./navigator
'
import
{
VD_SYNC
,
PAGE_CREATE
}
from
'
../../constants
'
...
...
@@ -109,7 +110,7 @@ export function registerPage ({
const
pageId
=
webview
.
id
// 通知页面已开始创建
UniServiceJSBridge
.
publishHandler
(
'
vdSync
'
,
{
UniServiceJSBridge
.
publishHandler
(
VD_SYNC
,
{
data
:
[
[
PAGE_CREATE
,
[
pageId
,
route
]]
],
...
...
@@ -119,7 +120,9 @@ export function registerPage ({
},
[
pageId
])
try
{
createPage
(
route
,
pageId
,
query
,
pageInstance
).
$mount
()
}
catch
(
e
)
{}
}
catch
(
e
)
{
console
.
error
(
e
)
}
}
}
...
...
src/platforms/app-plus/service/framework/plugins/data.js
浏览文件 @
6b4164fe
...
...
@@ -6,17 +6,19 @@ import {
import
{
MOUNTED_DATA
,
UPDATED_DATA
}
from
'
../../../constants
'
}
from
'
../../../constants
'
import
{
VDomSync
}
from
'
./vdom-sync
'
import
{
V_IF
,
V_FOR
,
V_ELSE_IF
}
from
'
../../constants
'
V_IF
,
V_FOR
,
V_ELSE_IF
,
B_CLASS
,
B_STYLE
}
from
'
../../constants
'
import
{
diff
...
...
@@ -49,10 +51,17 @@ export function initData (Vue) {
if
(
!
this
.
_$vd
)
{
return
}
// TODO 自定义组件中的 slot 数据采集是在组件内部,导致所在 context 中无法获取到差量数据
// 如何保证每个 vm 数据有变动,就加入 diff 中呢?
// 每次变化,可能触发多次 beforeUpdate,updated
// 子组件 updated 时,可能会增加父组件的 diffData,如 slot 等情况
diff
(
this
.
_$newData
,
this
.
_$data
,
this
.
_$vdUpdatedData
)
this
.
_$data
=
JSON
.
parse
(
JSON
.
stringify
(
this
.
_$newData
))
console
.
log
(
`[
${
this
.
_$id
}
] updated `
+
Date
.
now
())
this
.
_$vd
.
initialized
&&
this
.
$nextTick
(
this
.
_$vd
.
flush
.
bind
(
this
.
_$vd
))
// setTimeout 一下再 nextTick( 直接 nextTick 的话,会紧接着该 updated 做 flush,导致父组件 updated 数据被丢弃)
this
.
_$vd
.
initialized
&&
setTimeout
(()
=>
{
this
.
$nextTick
(
this
.
_$vd
.
flush
.
bind
(
this
.
_$vd
))
},
0
)
}
Object
.
defineProperty
(
Vue
.
prototype
,
'
_$vd
'
,
{
...
...
@@ -78,7 +87,6 @@ export function initData (Vue) {
this
.
_$vdMountedData
=
Object
.
create
(
null
)
this
.
_$setData
(
MOUNTED_DATA
,
this
.
_$vdMountedData
)
console
.
log
(
`[
${
this
.
_$id
}
] beforeCreate `
+
Date
.
now
())
// 目前全量采集做 diff(iOS 需要保留全量状态做 restore),理论上可以差量采集
this
.
_$data
=
Object
.
create
(
null
)
this
.
_$newData
=
Object
.
create
(
null
)
}
...
...
@@ -102,20 +110,23 @@ export function initData (Vue) {
})
}
function
setData
(
id
,
name
,
value
)
{
const
diffData
=
this
.
_$newData
[
id
]
||
(
this
.
_$newData
[
id
]
=
{})
if
(
typeof
name
!==
'
string
'
)
{
for
(
let
key
in
name
)
{
diffData
[
key
]
=
name
[
key
]
}
return
name
function
setData
(
id
,
name
,
value
)
{
switch
(
name
)
{
case
B_CLASS
:
value
=
this
.
_$stringifyClass
(
value
)
break
case
B_STYLE
:
value
=
this
.
_$normalizeStyleBinding
(
value
)
break
case
V_IF
:
case
V_ELSE_IF
:
value
=
!!
value
break
case
V_FOR
:
return
setForData
.
call
(
this
,
id
,
value
)
}
if
(
name
===
'
a-_i
'
)
{
return
value
}
return
(
diffData
[
name
]
=
value
)
return
((
this
.
_$newData
[
id
]
||
(
this
.
_$newData
[
id
]
=
{}))[
name
]
=
value
)
}
function
setForData
(
id
,
value
)
{
...
...
@@ -140,9 +151,9 @@ function setForData (id, value) {
}
function
setIfData
(
id
,
value
)
{
return
((
this
.
_$newData
[
id
]
||
(
this
.
_$newData
[
id
]
=
{}))[
V_IF
]
=
value
)
return
((
this
.
_$newData
[
id
]
||
(
this
.
_$newData
[
id
]
=
{}))[
V_IF
]
=
!!
value
)
}
function
setElseIfData
(
id
,
value
)
{
return
((
this
.
_$newData
[
id
]
||
(
this
.
_$newData
[
id
]
=
{}))[
V_ELSE_IF
]
=
value
)
return
((
this
.
_$newData
[
id
]
||
(
this
.
_$newData
[
id
]
=
{}))[
V_ELSE_IF
]
=
!!
value
)
}
src/platforms/app-plus/service/framework/plugins/vdom-sync.js
浏览文件 @
6b4164fe
import
{
isFn
isFn
,
noop
}
from
'
uni-shared
'
import
{
PAGE_CREATED
,
VD_SYNC_CALLBACK
VD_SYNC
,
UI_EVENT
,
PAGE_CREATED
}
from
'
../../../constants
'
import
{
removeWebviewUIEvent
,
registerWebviewUIEvent
vdSyncCallbacks
,
removeVdSync
,
registerVdSync
}
from
'
../subscribe-handlers
'
function
noop
()
{}
const
handleVdData
=
{
[
UI_EVENT
]:
function
onUIEvent
(
vdBatchEvent
,
vd
)
{
vdBatchEvent
.
forEach
(([
cid
,
nid
,
event
])
=>
{
console
.
log
(
`[EVENT]`
,
cid
,
nid
,
event
)
event
.
preventDefault
=
noop
event
.
stopPropagation
=
noop
const
target
=
vd
.
elements
.
find
(
target
=>
target
.
cid
===
cid
&&
target
.
nid
===
nid
)
if
(
!
target
)
{
return
console
.
error
(
`event handler[
${
cid
}
][
${
nid
}
] not found`
)
}
target
.
dispatchEvent
(
event
.
type
,
event
)
})
}
}
const
callbacks
=
[]
// 数据同步 callback
function
onVdSync
(
vdBatchData
,
vd
)
{
vdBatchData
.
forEach
(([
type
,
vdData
])
=>
{
handleVdData
[
type
](
vdData
,
vd
)
})
}
export
class
VDomSync
{
constructor
(
pageId
,
pagePath
)
{
...
...
@@ -23,55 +43,34 @@ export class VDomSync {
this
.
batchData
=
[]
this
.
vms
=
Object
.
create
(
null
)
this
.
initialized
=
false
// 事件
this
.
handlers
=
Object
.
create
(
null
)
this
.
elements
=
[]
// 目前仅存储事件 element
this
.
_init
()
}
_init
()
{
UniServiceJSBridge
.
subscribe
(
VD_SYNC_CALLBACK
,
()
=>
{
const
copies
=
callbacks
.
slice
(
0
)
callbacks
.
length
=
0
for
(
let
i
=
0
;
i
<
copies
.
length
;
i
++
)
{
copies
[
i
]()
}
})
registerWebviewUIEvent
(
this
.
pageId
,
(
cid
,
nid
,
event
)
=>
{
console
.
log
(
`[EVENT]`
,
cid
,
nid
,
event
)
event
.
preventDefault
=
noop
event
.
stopPropagation
=
noop
if
(
this
.
handlers
[
cid
]
&&
this
.
handlers
[
cid
][
nid
]
&&
this
.
handlers
[
cid
][
nid
][
event
.
type
]
)
{
this
.
handlers
[
cid
][
nid
][
event
.
type
].
forEach
(
handler
=>
{
handler
(
event
)
})
}
else
{
console
.
error
(
`event handler[
${
cid
}
][
${
nid
}
][
${
event
.
type
}
] not found`
)
}
registerVdSync
(
this
.
pageId
,
(
vdBatchData
)
=>
{
onVdSync
(
vdBatchData
,
this
)
})
}
addMountedVm
(
vm
)
{
vm
.
_$mounted
()
// 触发vd数据同步
this
.
addCallback
(
function
mounted
()
{
this
.
add
VdSync
Callback
(
function
mounted
()
{
vm
.
__call_hook
(
'
mounted
'
)
})
}
addUpdatedVm
(
vm
)
{
vm
.
_$updated
()
// 触发vd数据同步
this
.
addCallback
(
function
mounted
()
{
this
.
add
VdSync
Callback
(
function
mounted
()
{
vm
.
__call_hook
(
'
updated
'
)
})
}
addCallback
(
callback
)
{
isFn
(
callback
)
&&
c
allbacks
.
push
(
callback
)
add
VdSync
Callback
(
callback
)
{
isFn
(
callback
)
&&
vdSyncC
allbacks
.
push
(
callback
)
}
getVm
(
id
)
{
...
...
@@ -86,26 +85,20 @@ export class VDomSync {
delete
this
.
vms
[
vm
.
_$id
]
}
addEvent
(
cid
,
nid
,
name
,
handler
)
{
const
cHandlers
=
this
.
handlers
[
cid
]
||
(
this
.
handlers
[
cid
]
=
Object
.
create
(
null
))
const
nHandlers
=
cHandlers
[
nid
]
||
(
cHandlers
[
nid
]
=
Object
.
create
(
null
));
(
nHandlers
[
name
]
||
(
nHandlers
[
name
]
=
[])).
push
(
handler
)
addElement
(
elm
)
{
this
.
elements
.
indexOf
(
elm
)
===
-
1
&&
this
.
elements
.
push
(
elm
)
}
removeEvent
(
cid
,
nid
,
name
,
handler
)
{
const
cHandlers
=
this
.
handlers
[
cid
]
||
(
this
.
handlers
[
cid
]
=
Object
.
create
(
null
))
const
nHandlers
=
cHandlers
[
nid
]
||
(
cHandlers
[
nid
]
=
Object
.
create
(
null
))
const
eHandlers
=
nHandlers
[
name
]
if
(
Array
.
isArray
(
eHandlers
))
{
const
index
=
eHandlers
.
indexOf
(
handler
)
if
(
index
!==
-
1
)
{
eHandlers
.
splice
(
index
,
1
)
}
removeElement
(
elm
)
{
const
elmIndex
=
this
.
elements
.
indexOf
(
elm
)
if
(
elmIndex
===
-
1
)
{
return
console
.
error
(
`removeElement[
${
elm
.
cid
}
][
${
elm
.
nid
}
] not found`
)
}
this
.
elements
.
splice
(
elmIndex
,
1
)
}
push
(
type
,
nodeI
d
,
data
)
{
this
.
batchData
.
push
([
type
,
[
nodeI
d
,
data
]])
push
(
type
,
ci
d
,
data
)
{
this
.
batchData
.
push
([
type
,
[
ci
d
,
data
]])
}
flush
()
{
...
...
@@ -114,7 +107,7 @@ export class VDomSync {
this
.
batchData
.
push
([
PAGE_CREATED
,
[
this
.
pageId
,
this
.
pagePath
]])
}
if
(
this
.
batchData
.
length
)
{
UniServiceJSBridge
.
publishHandler
(
'
vdSync
'
,
{
UniServiceJSBridge
.
publishHandler
(
VD_SYNC
,
{
data
:
this
.
batchData
,
options
:
{
timestamp
:
Date
.
now
()
...
...
@@ -128,7 +121,7 @@ export class VDomSync {
this
.
batchData
.
length
=
0
this
.
vms
=
Object
.
create
(
null
)
this
.
initialized
=
false
this
.
handlers
=
Object
.
create
(
null
)
remove
WebviewUIEvent
(
this
.
pageId
)
this
.
elements
.
length
=
0
remove
VdSync
(
this
.
pageId
)
}
}
src/platforms/app-plus/service/framework/subscribe-handlers.js
浏览文件 @
6b4164fe
import
{
WEBVIEW_READY
,
WEBVIEW_UI_EVENT
VD_SYNC
,
VD_SYNC_CALLBACK
,
WEBVIEW_READY
}
from
'
../../constants
'
import
{
...
...
@@ -44,31 +45,37 @@ function onWebviewReady (data, pageId) {
}
}
const
webviewUIEvent
s
=
Object
.
create
(
null
)
const
vdSyncHandler
s
=
Object
.
create
(
null
)
export
function
register
WebviewUIEvent
(
pageId
,
callback
)
{
(
webviewUIEvents
[
pageId
]
||
(
webviewUIEvent
s
[
pageId
]
=
[])).
push
(
callback
)
export
function
register
VdSync
(
pageId
,
callback
)
{
(
vdSyncHandlers
[
pageId
]
||
(
vdSyncHandler
s
[
pageId
]
=
[])).
push
(
callback
)
}
export
function
remove
WebviewUIEvent
(
pageId
)
{
delete
webviewUIEvent
s
[
pageId
]
export
function
remove
VdSync
(
pageId
)
{
delete
vdSyncHandler
s
[
pageId
]
}
function
on
WebviewUIEvent
({
function
on
VdSync
({
data
,
options
},
pageId
)
{
const
{
cid
,
nid
}
=
options
const
handlers
=
webviewUIEvents
[
pageId
]
const
handlers
=
vdSyncHandlers
[
pageId
]
if
(
Array
.
isArray
(
handlers
))
{
handlers
.
forEach
(
handler
=>
{
handler
(
cid
,
nid
,
data
)
handler
(
data
)
})
}
else
{
console
.
error
(
`events[
${
pageId
}
] not found`
)
console
.
error
(
`vdSync[
${
pageId
}
] not found`
)
}
}
export
const
vdSyncCallbacks
=
[]
// 数据同步 callback
function
onVdSyncCallback
()
{
const
copies
=
vdSyncCallbacks
.
slice
(
0
)
vdSyncCallbacks
.
length
=
0
for
(
let
i
=
0
;
i
<
copies
.
length
;
i
++
)
{
copies
[
i
]()
}
}
...
...
@@ -83,5 +90,7 @@ export function initSubscribeHandlers () {
})
// TODO 检测目标 preloadWebview 是否已准备好,因为 preloadWebview 准备好时,此处代码还没执行
subscribe
(
WEBVIEW_READY
,
onWebviewReady
)
subscribe
(
WEBVIEW_UI_EVENT
,
onWebviewUIEvent
)
subscribe
(
VD_SYNC
,
onVdSync
)
subscribe
(
VD_SYNC_CALLBACK
,
onVdSyncCallback
)
}
src/platforms/app-plus/view/framework/plugins/data.js
浏览文件 @
6b4164fe
import
Vue
from
'
vue
'
import
{
VD_SYNC
,
PAGE_CREATE
,
MOUNTED_DATA
,
UPDATED_DATA
,
...
...
@@ -20,7 +21,7 @@ import {
getPageVueComponent
}
from
'
../../../page-factory
'
let
vd
export
let
vd
let
PageVueComponent
...
...
@@ -68,18 +69,18 @@ function vdSync ({
})
}
function
getData
(
id
,
name
,
isFallbackContent
=
false
)
{
function
getData
(
id
,
name
)
{
try
{
return
this
.
$r
[
id
][
name
]
}
catch
(
e
)
{
!
isFallbackContent
&&
console
.
error
(
this
.
$options
.
__file
+
`:[
${
this
.
_$id
}
]$r[
${
id
}
][
${
name
}
] is undefined`
)
console
.
error
(
this
.
$options
.
__file
+
`:[
${
this
.
_$id
}
]$r[
${
id
}
][
${
name
}
] is undefined`
)
}
}
export
function
initData
(
Vue
)
{
Vue
.
prototype
.
_$g
=
getData
UniViewJSBridge
.
subscribe
(
'
vdSync
'
,
vdSync
)
UniViewJSBridge
.
subscribe
(
VD_SYNC
,
vdSync
)
Object
.
defineProperty
(
Vue
.
prototype
,
'
_$vd
'
,
{
get
()
{
...
...
src/platforms/app-plus/view/framework/plugins/event.js
浏览文件 @
6b4164fe
import
{
WEBVIEW_UI_EVENT
}
from
'
.
./../../constants
'
vd
}
from
'
.
/data
'
export
function
initEvent
(
Vue
)
{
Vue
.
prototype
.
$handleViewEvent
=
function
(
$vueEvent
,
options
)
{
...
...
@@ -19,12 +19,10 @@ export function initEvent (Vue) {
delete
$event
.
stopPropagation
delete
$event
.
options
UniViewJSBridge
.
publishHandler
(
WEBVIEW_UI_EVENT
,
{
data
:
$event
,
options
:
{
cid
,
nid
}
})
vd
.
addUIEvent
(
cid
,
nid
,
$event
)
// 使用 setTimeout 做批量同步
setTimeout
(()
=>
{
vd
.
sendUIEvent
()
},
0
)
}
}
src/platforms/app-plus/view/framework/plugins/vdom-sync.js
浏览文件 @
6b4164fe
...
...
@@ -2,47 +2,72 @@ import {
guid
}
from
'
uni-shared
'
import
{
VD_SYNC
,
UI_EVENT
}
from
'
../../../constants
'
export
class
VDomSync
{
constructor
(
pageId
)
{
this
.
pageId
=
pageId
this
.
add
VDatas
=
[]
this
.
update
VDatas
=
[]
this
.
add
BatchVData
=
[]
this
.
update
BatchVData
=
[]
this
.
vms
=
Object
.
create
(
null
)
this
.
uiEventBatchData
=
[]
}
addVData
(
nodeI
d
,
data
=
{})
{
this
.
add
VDatas
.
push
([
nodeI
d
,
data
])
addVData
(
ci
d
,
data
=
{})
{
this
.
add
BatchVData
.
push
([
ci
d
,
data
])
}
updateVData
(
nodeI
d
,
data
=
{})
{
this
.
update
VDatas
.
push
([
nodeI
d
,
data
])
updateVData
(
ci
d
,
data
=
{})
{
this
.
update
BatchVData
.
push
([
ci
d
,
data
])
}
initVm
(
vm
)
{
const
[
nodeId
,
data
]
=
this
.
addVDatas
.
shift
()
if
(
!
nodeI
d
)
{
const
[
cid
,
data
]
=
this
.
addBatchVData
.
shift
()
if
(
!
ci
d
)
{
vm
.
_$id
=
guid
()
console
.
error
(
'
nodeI
d unmatched
'
,
vm
)
console
.
error
(
'
ci
d unmatched
'
,
vm
)
}
else
{
vm
.
_$id
=
nodeI
d
vm
.
_$id
=
ci
d
}
vm
.
$r
=
data
||
Object
.
create
(
null
)
this
.
vms
[
vm
.
_$id
]
=
vm
}
addUIEvent
(
cid
,
nid
,
event
)
{
this
.
uiEventBatchData
.
push
([
cid
,
nid
,
event
])
}
sendUIEvent
()
{
if
(
this
.
uiEventBatchData
.
length
)
{
UniViewJSBridge
.
publishHandler
(
VD_SYNC
,
{
data
:
[
[
UI_EVENT
,
this
.
uiEventBatchData
]
],
options
:
{
timestamp
:
Date
.
now
()
}
})
this
.
uiEventBatchData
.
length
=
0
}
}
flush
()
{
console
.
log
(
'
update....
'
,
this
.
add
VDatas
,
this
.
updateVDatas
)
this
.
update
VDatas
.
forEach
(([
nodeI
d
,
data
])
=>
{
const
vm
=
this
.
vms
[
nodeI
d
]
console
.
log
(
'
update....
'
,
this
.
add
BatchVData
,
this
.
updateBatchVData
)
this
.
update
BatchVData
.
forEach
(([
ci
d
,
data
])
=>
{
const
vm
=
this
.
vms
[
ci
d
]
if
(
!
vm
)
{
return
console
.
error
(
`Not found
${
nodeI
d
}
`
)
return
console
.
error
(
`Not found
${
ci
d
}
`
)
}
Object
.
keys
(
data
).
forEach
(
nodeI
d
=>
{
Object
.
assign
((
vm
.
$r
[
nodeId
]
||
(
vm
.
$r
[
nodeId
]
=
Object
.
create
(
null
))),
data
[
nodeI
d
])
Object
.
keys
(
data
).
forEach
(
ci
d
=>
{
Object
.
assign
((
vm
.
$r
[
cid
]
||
(
vm
.
$r
[
cid
]
=
Object
.
create
(
null
))),
data
[
ci
d
])
})
vm
.
$forceUpdate
()
})
this
.
update
VDatas
.
length
=
0
this
.
update
BatchVData
.
length
=
0
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录