Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
wychl
uni-app
提交
32f99d02
U
uni-app
项目概览
wychl
/
uni-app
与 Fork 源项目一致
Fork自
DCloud / uni-app
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
U
uni-app
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
32f99d02
编写于
12月 09, 2019
作者:
fxy060608
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat(v3): mp runtime
上级
a0fe152b
变更
23
展开全部
隐藏空白更改
内联
并排
Showing
23 changed file
with
811 addition
and
543 deletion
+811
-543
packages/uni-app-plus/dist/index.v3.js
packages/uni-app-plus/dist/index.v3.js
+393
-248
packages/uni-app-plus/dist/service.runtime.esm.js
packages/uni-app-plus/dist/service.runtime.esm.js
+73
-52
packages/uni-mp-weixin/dist/mp.js
packages/uni-mp-weixin/dist/mp.js
+123
-106
packages/uni-template-compiler/__tests__/compiler-app-plus-extra.service.spec.js
...ompiler/__tests__/compiler-app-plus-extra.service.spec.js
+95
-88
packages/uni-template-compiler/__tests__/compiler-app-plus-extra.view.spec.js
...e-compiler/__tests__/compiler-app-plus-extra.view.spec.js
+7
-0
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
+10
-1
packages/uni-template-compiler/lib/app/parser/base-parser.js
packages/uni-template-compiler/lib/app/parser/base-parser.js
+10
-5
packages/uni-template-compiler/lib/app/view.js
packages/uni-template-compiler/lib/app/view.js
+5
-0
src/core/runtime/mp/constants.js
src/core/runtime/mp/constants.js
+3
-3
src/core/runtime/mp/index.js
src/core/runtime/mp/index.js
+15
-0
src/core/runtime/mp/parser/lifecycle-parser.js
src/core/runtime/mp/parser/lifecycle-parser.js
+1
-1
src/core/runtime/mp/polyfill/index.js
src/core/runtime/mp/polyfill/index.js
+5
-4
src/core/runtime/mp/polyfill/relations.js
src/core/runtime/mp/polyfill/relations.js
+11
-11
src/core/runtime/mp/polyfill/state/properties.js
src/core/runtime/mp/polyfill/state/properties.js
+7
-2
src/core/service/plugins/lifecycle.js
src/core/service/plugins/lifecycle.js
+4
-1
src/core/service/plugins/polyfill.js
src/core/service/plugins/polyfill.js
+16
-4
src/core/view/bridge/subscribe/api/util.js
src/core/view/bridge/subscribe/api/util.js
+4
-1
src/platforms/app-plus/service/framework/page.js
src/platforms/app-plus/service/framework/page.js
+2
-2
src/platforms/app-plus/service/framework/plugins/data.js
src/platforms/app-plus/service/framework/plugins/data.js
+6
-0
src/platforms/app-plus/service/framework/plugins/diff.js
src/platforms/app-plus/service/framework/plugins/diff.js
+10
-6
src/platforms/app-plus/service/framework/plugins/vdom-sync.js
...platforms/app-plus/service/framework/plugins/vdom-sync.js
+4
-4
src/platforms/app-plus/view/framework/plugins/data.js
src/platforms/app-plus/view/framework/plugins/data.js
+6
-3
未找到文件。
packages/uni-app-plus/dist/index.v3.js
浏览文件 @
32f99d02
此差异已折叠。
点击以展开。
packages/uni-app-plus/dist/service.runtime.esm.js
浏览文件 @
32f99d02
...
...
@@ -1918,7 +1918,10 @@ function flushCallbacks () {
// where microtasks have too high a priority and fire in between supposedly
// sequential events (e.g. #4521, #6690, which have workarounds)
// or even between bubbling of the same event (#6566).
var
timerFunc
;
// fixed by xxxxxx app-plus 平台 Promise 执行顺序不一致,导致各种乱七八糟的 Bug,统一使用 setTimeout
var
timerFunc
=
function
()
{
setTimeout
(
flushCallbacks
,
0
);
};
// The nextTick behavior leverages the microtask queue, which can be accessed
// via either native Promise.then or MutationObserver.
...
...
@@ -1927,48 +1930,50 @@ var timerFunc;
// completely stops working after triggering a few times... so, if native
// Promise is available, we will use it:
/* istanbul ignore next, $flow-disable-line */
if
(
typeof
Promise
!==
'
undefined
'
&&
isNative
(
Promise
)
&&
!
isIOS
)
{
// fixed by xxxxxx
var
p
=
Promise
.
resolve
();
timerFunc
=
function
()
{
p
.
then
(
flushCallbacks
);
// In problematic UIWebViews, Promise.then doesn't completely break, but
// it can get stuck in a weird state where callbacks are pushed into the
// microtask queue but the queue isn't being flushed, until the browser
// needs to do some other work, e.g. handle a timer. Therefore we can
// "force" the microtask queue to be flushed by adding an empty timer.
if
(
isIOS
)
{
setTimeout
(
noop
);
}
};
}
else
if
(
!
isIE
&&
typeof
MutationObserver
!==
'
undefined
'
&&
(
isNative
(
MutationObserver
)
||
// PhantomJS and iOS 7.x
MutationObserver
.
toString
()
===
'
[object MutationObserverConstructor]
'
))
{
// Use MutationObserver where native Promise is not available,
// e.g. PhantomJS, iOS7, Android 4.4
// (#6466 MutationObserver is unreliable in IE11)
var
counter
=
1
;
var
observer
=
new
MutationObserver
(
flushCallbacks
);
var
textNode
=
document
.
createTextNode
(
String
(
counter
));
observer
.
observe
(
textNode
,
{
characterData
:
true
});
timerFunc
=
function
()
{
counter
=
(
counter
+
1
)
%
2
;
textNode
.
data
=
String
(
counter
);
};
}
else
if
(
typeof
setImmediate
!==
'
undefined
'
&&
isNative
(
setImmediate
))
{
// Fallback to setImmediate.
// Technically it leverages the (macro) task queue,
// but it is still a better choice than setTimeout.
timerFunc
=
function
()
{
setImmediate
(
flushCallbacks
);
};
}
else
{
// Fallback to setTimeout.
timerFunc
=
function
()
{
setTimeout
(
flushCallbacks
,
0
);
};
}
// if (typeof Promise !== 'undefined' && isNative(Promise)) {
// const p = Promise.resolve()
// timerFunc = () => {
// p.then(flushCallbacks)
// // In problematic UIWebViews, Promise.then doesn't completely break, but
// // it can get stuck in a weird state where callbacks are pushed into the
// // microtask queue but the queue isn't being flushed, until the browser
// // needs to do some other work, e.g. handle a timer. Therefore we can
// // "force" the microtask queue to be flushed by adding an empty timer.
// if (isIOS) setTimeout(noop)
// }
// isUsingMicroTask = true
// } else if (!isIE && typeof MutationObserver !== 'undefined' && (
// isNative(MutationObserver) ||
// // PhantomJS and iOS 7.x
// MutationObserver.toString() === '[object MutationObserverConstructor]'
// )) {
// // Use MutationObserver where native Promise is not available,
// // e.g. PhantomJS, iOS7, Android 4.4
// // (#6466 MutationObserver is unreliable in IE11)
// let counter = 1
// const observer = new MutationObserver(flushCallbacks)
// const textNode = document.createTextNode(String(counter))
// observer.observe(textNode, {
// characterData: true
// })
// timerFunc = () => {
// counter = (counter + 1) % 2
// textNode.data = String(counter)
// }
// isUsingMicroTask = true
// } else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {
// // Fallback to setImmediate.
// // Technically it leverages the (macro) task queue,
// // but it is still a better choice than setTimeout.
// timerFunc = () => {
// setImmediate(flushCallbacks)
// }
// } else {
// // Fallback to setTimeout.
// timerFunc = () => {
// setTimeout(flushCallbacks, 0)
// }
// }
function
nextTick
(
cb
,
ctx
)
{
var
_resolve
;
...
...
@@ -2258,18 +2263,29 @@ function mergeVNodeHook (def, hookKey, hook) {
/* */
// fixed by xxxxxx (mp properties)
function
extractPropertiesFromVNodeData
(
data
,
Ctor
,
res
)
{
function
extractPropertiesFromVNodeData
(
data
,
Ctor
,
res
,
context
)
{
var
propOptions
=
Ctor
.
options
.
mpOptions
&&
Ctor
.
options
.
mpOptions
.
properties
;
if
(
isUndef
(
propOptions
))
{
return
res
}
}
var
externalClasses
=
Ctor
.
options
.
mpOptions
.
externalClasses
||
[];
var
attrs
=
data
.
attrs
;
var
props
=
data
.
props
;
if
(
isDef
(
attrs
)
||
isDef
(
props
))
{
for
(
var
key
in
propOptions
)
{
var
altKey
=
hyphenate
(
key
);
checkProp
(
res
,
props
,
key
,
altKey
,
true
)
||
checkProp
(
res
,
attrs
,
key
,
altKey
,
false
);
var
altKey
=
hyphenate
(
key
);
var
result
=
checkProp
(
res
,
props
,
key
,
altKey
,
true
)
||
checkProp
(
res
,
attrs
,
key
,
altKey
,
false
);
// externalClass
if
(
result
&&
res
[
key
]
&&
externalClasses
.
indexOf
(
altKey
)
!==
-
1
&&
context
[
camelize
(
res
[
key
])]
)
{
// 赋值 externalClass 真正的值(模板里 externalClass 的值可能是字符串)
res
[
key
]
=
context
[
camelize
(
res
[
key
])];
}
}
}
return
res
...
...
@@ -2278,7 +2294,8 @@ function extractPropertiesFromVNodeData(data, Ctor, res) {
function
extractPropsFromVNodeData
(
data
,
Ctor
,
tag
tag
,
context
)
{
// we are only extracting raw values here.
// validation and default values are handled in the child
...
...
@@ -2286,7 +2303,7 @@ function extractPropsFromVNodeData (
var
propOptions
=
Ctor
.
options
.
props
;
if
(
isUndef
(
propOptions
))
{
// fixed by xxxxxx
return
extractPropertiesFromVNodeData
(
data
,
Ctor
,
{})
return
extractPropertiesFromVNodeData
(
data
,
Ctor
,
{}
,
context
)
}
var
res
=
{};
var
attrs
=
data
.
attrs
;
...
...
@@ -2315,7 +2332,7 @@ function extractPropsFromVNodeData (
}
}
// fixed by xxxxxx
return
extractPropertiesFromVNodeData
(
data
,
Ctor
,
res
)
return
extractPropertiesFromVNodeData
(
data
,
Ctor
,
res
,
context
)
}
function
checkProp
(
...
...
@@ -3158,6 +3175,8 @@ var componentVNodeHooks = {
// fixed by xxxxxx
componentInstance
.
_isMounted
=
true
;
if
(
componentInstance
.
_$vd
)
{
// 延迟 mounted
callHook
(
componentInstance
,
'
onServiceCreated
'
);
callHook
(
componentInstance
,
'
onServiceAttached
'
);
componentInstance
.
_$vd
.
addMountedVm
(
componentInstance
);
}
else
{
callHook
(
componentInstance
,
'
mounted
'
);
...
...
@@ -3249,7 +3268,7 @@ function createComponent (
}
// extract props
var
propsData
=
extractPropsFromVNodeData
(
data
,
Ctor
,
tag
);
var
propsData
=
extractPropsFromVNodeData
(
data
,
Ctor
,
tag
,
context
);
// functional component
if
(
isTrue
(
Ctor
.
options
.
functional
))
{
...
...
@@ -4110,6 +4129,8 @@ function mountComponent (
// fixed by xxxxxx
vm
.
_isMounted
=
true
;
if
(
vm
.
_$vd
)
{
// 延迟 mounted 事件
callHook
(
vm
,
'
onServiceCreated
'
);
callHook
(
vm
,
'
onServiceAttached
'
);
vm
.
_$vd
.
addMountedVm
(
vm
);
}
else
{
callHook
(
vm
,
'
mounted
'
);
...
...
packages/uni-mp-weixin/dist/mp.js
浏览文件 @
32f99d02
...
...
@@ -26,7 +26,7 @@ function hasOwn (obj, key) {
return
hasOwnProperty
.
call
(
obj
,
key
)
}
function
noop
()
{}
function
noop
()
{
}
/**
* Create a cached version of a pure function.
...
...
@@ -49,9 +49,9 @@ const camelize = cached((str) => {
const
SOURCE_KEY
=
'
__data__
'
;
const
COMPONENT_LIFECYCLE
=
{
'
created
'
:
'
c
reated
'
,
'
attached
'
:
'
creat
ed
'
,
const
COMPONENT_LIFECYCLE
=
{
'
created
'
:
'
onServiceC
reated
'
,
'
attached
'
:
'
onServiceAttach
ed
'
,
'
ready
'
:
'
mounted
'
,
'
moved
'
:
'
moved
'
,
'
detached
'
:
'
destroyed
'
...
...
@@ -147,7 +147,7 @@ function parseLifecycle (mpComponentOptions, vueComponentOptions) {
(
vueComponentOptions
[
COMPONENT_LIFECYCLE
[
name
]]
||
(
vueComponentOptions
[
COMPONENT_LIFECYCLE
[
name
]]
=
[]))
.
push
(
mpComponentOptions
[
name
]);
}
});
});
}
const
mpBehaviors
=
{
...
...
@@ -382,6 +382,102 @@ function parseComponent (mpComponentOptions) {
return
vueComponentOptions
}
function
initRelationHandlers
(
type
,
handler
,
target
,
ctx
)
{
if
(
!
handler
)
{
return
}
const
name
=
`_$
${
type
}
Handlers`
;
(
ctx
[
name
]
||
(
ctx
[
name
]
=
[])).
push
(
function
()
{
handler
.
call
(
ctx
,
target
);
});
}
function
initLinkedHandlers
(
relation
,
target
,
ctx
)
{
const
type
=
'
linked
'
;
const
name
=
relation
.
name
;
const
relationNodes
=
ctx
.
_$relationNodes
||
(
ctx
.
_$relationNodes
=
Object
.
create
(
null
));
(
relationNodes
[
name
]
||
(
relationNodes
[
name
]
=
[])).
push
(
target
);
initRelationHandlers
(
type
,
relation
[
type
],
target
,
ctx
);
}
function
initUnlinkedHandlers
(
relation
,
target
,
ctx
)
{
const
type
=
'
unlinked
'
;
initRelationHandlers
(
type
,
relation
[
type
],
target
,
ctx
);
}
function
findParentRelation
(
parentVm
,
target
,
type
)
{
const
relations
=
parentVm
&&
parentVm
.
$options
.
mpOptions
&&
parentVm
.
$options
.
mpOptions
.
relations
;
if
(
!
relations
)
{
return
[]
}
const
name
=
Object
.
keys
(
relations
).
find
(
name
=>
{
const
relation
=
relations
[
name
];
return
relation
.
target
===
target
&&
relation
.
type
===
type
});
if
(
!
name
)
{
return
[]
}
return
[
relations
[
name
],
parentVm
]
}
function
initParentRelation
(
vm
,
childRelation
,
match
)
{
const
[
parentRelation
,
parentVm
]
=
match
(
vm
,
vm
.
$options
.
mpOptions
.
path
);
if
(
!
parentRelation
)
{
return
}
initLinkedHandlers
(
parentRelation
,
vm
,
parentVm
);
initLinkedHandlers
(
childRelation
,
parentVm
,
vm
);
initUnlinkedHandlers
(
parentRelation
,
vm
,
parentVm
);
initUnlinkedHandlers
(
childRelation
,
parentVm
,
vm
);
}
function
initRelation
(
relation
,
vm
)
{
const
type
=
relation
.
type
;
if
(
type
===
'
parent
'
)
{
initParentRelation
(
vm
,
relation
,
function
matchParent
(
vm
,
target
)
{
return
findParentRelation
(
vm
.
$parent
,
target
,
'
child
'
)
});
}
else
if
(
type
===
'
ancestor
'
)
{
initParentRelation
(
vm
,
relation
,
function
matchAncestor
(
vm
,
target
)
{
let
$parent
=
vm
.
$parent
;
while
(
$parent
)
{
const
ret
=
findParentRelation
(
$parent
,
target
,
'
descendant
'
);
if
(
ret
.
length
)
{
return
ret
}
$parent
=
$parent
.
$parent
;
}
return
[]
});
}
}
function
initRelations
(
vm
)
{
const
{
relations
}
=
vm
.
$options
.
mpOptions
||
{};
if
(
!
relations
)
{
return
}
Object
.
keys
(
relations
).
forEach
(
name
=>
{
initRelation
(
relations
[
name
],
vm
);
});
}
function
handleRelations
(
vm
,
type
)
{
// TODO 需要移除 relationNodes
const
handlers
=
vm
[
`_$
${
type
}
Handlers`
];
if
(
!
handlers
)
{
return
}
handlers
.
forEach
(
handler
=>
handler
());
}
const
sharedPropertyDefinition
=
{
enumerable
:
true
,
configurable
:
true
,
...
...
@@ -467,7 +563,12 @@ function validateProp (key, propsOptions, propsData, vm) {
value
=
!!
value
;
}
const
observer
=
propOptions
&&
propOptions
.
observer
;
observer
&&
observe
(
observer
,
vm
,
value
);
if
(
observer
)
{
// 初始化时,异步触发 observer,否则 observer 中无法访问 methods 或其他
setTimeout
(
function
()
{
observe
(
observer
,
vm
,
value
);
},
4
);
}
return
value
}
return
getPropertyVal
(
propsOptions
[
key
])
...
...
@@ -508,7 +609,7 @@ function initProperties (vm, instanceData) {
/* eslint-disable no-self-compare */
if
(
newVal
===
value
||
(
newVal
!==
newVal
&&
value
!==
value
))
{
return
}
}
value
=
newVal
;
if
(
observer
)
{
observe
(
observer
,
vm
,
newVal
,
oldVal
);
...
...
@@ -589,102 +690,6 @@ function initMethods (vm) {
vm
.
_$updateProperties
=
updateProperties
;
}
function
initRelationHandlers
(
type
,
handler
,
target
,
ctx
,
handlerCtx
)
{
if
(
!
handler
)
{
return
}
const
name
=
`_$
${
type
}
Handlers`
;
(
handlerCtx
[
name
]
||
(
handlerCtx
[
name
]
=
[])).
push
(
function
()
{
handler
.
call
(
ctx
,
target
);
});
}
function
initLinkedHandlers
(
relation
,
target
,
ctx
,
handlerCtx
)
{
const
type
=
'
linked
'
;
const
name
=
relation
.
name
;
const
relationNodes
=
ctx
.
_$relationNodes
||
(
ctx
.
_$relationNodes
=
Object
.
create
(
null
));
(
relationNodes
[
name
]
||
(
relationNodes
[
name
]
=
[])).
push
(
target
);
initRelationHandlers
(
type
,
relation
[
type
],
target
,
ctx
,
handlerCtx
);
}
function
initUnlinkedHandlers
(
relation
,
target
,
ctx
,
handlerCtx
)
{
const
type
=
'
unlinked
'
;
initRelationHandlers
(
type
,
relation
[
type
],
target
,
ctx
,
handlerCtx
);
}
function
findParentRelation
(
parentVm
,
target
,
type
)
{
const
relations
=
parentVm
&&
parentVm
.
$options
.
mpOptions
&&
parentVm
.
$options
.
mpOptions
.
relations
;
if
(
!
relations
)
{
return
[]
}
const
name
=
Object
.
keys
(
relations
).
find
(
name
=>
{
const
relation
=
relations
[
name
];
return
relation
.
target
===
target
&&
relation
.
type
===
type
});
if
(
!
name
)
{
return
[]
}
return
[
relations
[
name
],
parentVm
]
}
function
initParentRelation
(
vm
,
childRelation
,
match
)
{
const
[
parentRelation
,
parentVm
]
=
match
(
vm
,
vm
.
$options
.
mpOptions
.
path
);
if
(
!
parentRelation
)
{
return
}
// 先父后子
initLinkedHandlers
(
parentRelation
,
vm
,
parentVm
,
vm
);
initLinkedHandlers
(
childRelation
,
parentVm
,
vm
,
vm
);
initUnlinkedHandlers
(
parentRelation
,
vm
,
parentVm
,
vm
);
initUnlinkedHandlers
(
childRelation
,
parentVm
,
vm
,
vm
);
}
function
initRelation
(
relation
,
vm
)
{
const
type
=
relation
.
type
;
if
(
type
===
'
parent
'
)
{
initParentRelation
(
vm
,
relation
,
function
matchParent
(
vm
,
target
)
{
return
findParentRelation
(
vm
.
$parent
,
target
,
'
child
'
)
});
}
else
if
(
type
===
'
ancestor
'
)
{
initParentRelation
(
vm
,
relation
,
function
matchAncestor
(
vm
,
target
)
{
let
$parent
=
vm
.
$parent
;
while
(
$parent
)
{
const
ret
=
findParentRelation
(
$parent
,
target
,
'
descendant
'
);
if
(
ret
.
length
)
{
return
ret
}
$parent
=
$parent
.
$parent
;
}
return
[]
});
}
}
function
initRelations
(
vm
)
{
const
{
relations
}
=
vm
.
$options
.
mpOptions
||
{};
if
(
!
relations
)
{
return
}
Object
.
keys
(
relations
).
forEach
(
name
=>
{
initRelation
(
relations
[
name
],
vm
);
});
}
function
handleRelations
(
vm
,
type
)
{
// TODO 需要移除 relationNodes
const
handlers
=
vm
[
`_$
${
type
}
Handlers`
];
if
(
!
handlers
)
{
return
}
handlers
.
forEach
(
handler
=>
handler
());
}
function
handleObservers
(
vm
)
{
const
watch
=
vm
.
$options
.
watch
;
if
(
!
watch
)
{
...
...
@@ -705,13 +710,14 @@ function handleObservers (vm) {
var
polyfill
=
{
beforeCreate
()
{
// 取消 development 时的 Proxy,避免小程序组件模板中使用尚未定义的属性告警
this
.
_renderProxy
=
this
;
},
created
()
{
// properties 中可能会访问 methods,故需要在 created 中初始化
initState
(
this
);
initMethods
(
this
);
initRelations
(
this
);
},
created
()
{
handleRelations
(
this
,
'
linked
'
);
},
mounted
()
{
handleObservers
(
this
);
},
...
...
@@ -749,10 +755,21 @@ function Page (options) {
global
[
'
__wxComponents
'
][
global
[
'
__wxRoute
'
]]
=
pageOptions
;
}
function
initRelationsHandler
(
vueComponentOptions
)
{
// linked 需要在当前组件 attached 之后再执行
if
(
!
vueComponentOptions
[
'
onServiceAttached
'
])
{
vueComponentOptions
[
'
onServiceAttached
'
]
=
[];
}
vueComponentOptions
[
'
onServiceAttached
'
].
push
(
function
onServiceAttached
()
{
handleRelations
(
this
,
'
linked
'
);
});
}
function
Component
(
options
)
{
const
componentOptions
=
parseComponent
(
options
);
componentOptions
.
mixins
.
unshift
(
polyfill
);
componentOptions
.
mpOptions
.
path
=
global
[
'
__wxRoute
'
];
initRelationsHandler
(
componentOptions
);
global
[
'
__wxComponents
'
][
global
[
'
__wxRoute
'
]]
=
componentOptions
;
}
...
...
packages/uni-template-compiler/__tests__/compiler-app-plus-extra.service.spec.js
浏览文件 @
32f99d02
...
...
@@ -5,112 +5,119 @@ function assertCodegen (template, generatedCode, ...args) {
mp
:
{
platform
:
'
app-plus
'
},
service
:
true
,
service
:
true
,
filterModules
:
[
'
swipe
'
]
})
expect
(
compiled
.
render
).
toBe
(
generatedCode
)
}
/* eslint-disable quotes */
describe
(
'
codegen
'
,
()
=>
{
it
(
'
generate block
'
,
()
=>
{
assertCodegen
(
'
<block v-if="show"></block>
'
,
`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((_$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((_$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)}`
)
assertCodegen
(
'
<div><block v-for="(item,index) in list" :key="index"><block><text>{{item}}</text></block></block></div>
'
,
`with(this){return _c('div',[_l((_$s(1,'f',{forItems:list})),function(item,index,$20,$30){return [[_c('text',{key:_$s(("3-"+$30),'a-key',index+'_0'+'_0')},[_v((_$s(("3-"+$30),'t0',_s(item))))])]]})],2)}`
)
describe
(
'
codegen
'
,
()
=>
{
it
(
'
generate block
'
,
()
=>
{
assertCodegen
(
'
<block v-if="show"></block>
'
,
`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((_$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((_$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)}`
)
assertCodegen
(
'
<div><block v-for="(item,index) in list" :key="index"><block><text>{{item}}</text></block></block></div>
'
,
`with(this){return _c('div',[_l((_$s(1,'f',{forItems:list})),function(item,index,$20,$30){return [[_c('text',{key:_$s(("3-"+$30),'a-key',index+'_0'+'_0')},[_v((_$s(("3-"+$30),'t0',_s(item))))])]]})],2)}`
)
})
it
(
'
generate directive
'
,
()
=>
{
assertCodegen
(
'
<p v-custom1:[arg1].modifier="value1" v-custom2></p>
'
,
`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((_$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((_$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((_$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((_$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((_$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((_$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 v-for directive
'
,
()
=>
{
assertCodegen
(
'
<div><template v-for="item in items"><div></div><div></div></template></div>
'
,
`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((_$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((_$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((_$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((_$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((_$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 :id="'a'+b">A{{ d | e | f }}B{{text}}C</div>`
,
`with(this){return _c('div',{attrs:{"id":_$s(0,'a-id','a'+b),"_i":0}},[_v((_$s(0,'t0',_s(_f("f")(_f("e")(d)))))+(_$s(0,'t1',_s(text))))])}`
)
})
it
(
'
generate v-slot
'
,
()
=>
{
assertCodegen
(
'
<current-user v-slot="{ user }">{{ user.firstName }}</current-user>
'
,
`with(this){return _c('current-user',{attrs:{"_i":0},scopedSlots:_u([{key:"default",fn:function({ user }, _svm, _si){return [_v((_svm._$s(("0-"+_si),'t0',_s(user.firstName))))]}}])})}`
)
assertCodegen
(
'
<current-user>ABCD</current-user>
'
,
`with(this){return _c('current-user',{attrs:{"_i":0}},[_v("")])}`
)
assertCodegen
(
`<current-user>
<template v-slot:default="{result}">
<view v-for="(item,index) in result.list">{{item.name}}</view>
</template>
</current-user>`
,
`with(this){return _c('current-user',{attrs:{"_i":0},scopedSlots:_u([{key:"default",fn:function({result}, _svm, _si){return _l((_svm._$s(("2-"+_si),'f',{forItems:result.list})),function(item,index,$20,$30){return _c('view',{key:_svm._$s(("2-"+_si),'f',{forIndex:$20,key:("2-"+_si)+'-'+$30}),attrs:{"_i":(("2-"+_si)+$30)}},[_v((_svm._$s((("2-"+_si)+$30),'t0',_s(item.name))))])})}}])})}`
)
})
it
(
'
generate keep-alive
'
,
()
=>
{
assertCodegen
(
`<keep-alive exclude="componentWithStatus1"><component is="componentWithStatus"/></keep-alive>`
,
`with(this){return _c('keep-alive',{attrs:{"exclude":"componentWithStatus1","_i":0}},[_c("componentWithStatus",{tag:"component",attrs:{"_i":1}})],1)}`
)
assertCodegen
(
`<keep-alive :exclude="componentWithStatus1"><component :is="'componentWithStatus'+index"/></keep-alive>`
,
`with(this){return _c('keep-alive',{attrs:{"exclude":_$s(0,'a-exclude',componentWithStatus1),"_i":0}},[_c(_$s(1,'is','componentWithStatus'+index),{tag:"component",attrs:{"_i":1}})],1)}`
)
})
it
(
'
generate wxs props
'
,
()
=>
{
assertCodegen
(
'
<p :change:prop="swipe.sizeReady" :prop="pos" @touchstart="swipe.touchstart" @touchmove="swipe.touchmove" @touchend="swipe.touchend" @change="change"></p>
'
,
`with(this){return _c('p',{wxsProps:{"change:prop":"pos"},attrs:{"prop":_$s(0,'change:pos',pos),"_i":0},on:{"change":change}})}`
)
})
it
(
'
generate staticClass and id
'
,
()
=>
{
assertCodegen
(
'
<view id="aaa" class="bbbb"></view>
'
,
`with(this){return _c('view',{staticClass:_$s(0,'sc',"bbbb"),attrs:{"id":"aaa","_i":0}})}`
)
})
it
(
'
generate v-slot
'
,
()
=>
{
assertCodegen
(
'
<current-user v-slot="{ user }">{{ user.firstName }}</current-user>
'
,
`with(this){return _c('current-user',{attrs:{"_i":0},scopedSlots:_u([{key:"default",fn:function({ user }, _svm, _si){return [_v((_svm._$s(("0-"+_si),'t0',_s(user.firstName))))]}}])})}`
)
assertCodegen
(
'
<current-user>ABCD</current-user>
'
,
`with(this){return _c('current-user',{attrs:{"_i":0}},[_v("")])}`
)
assertCodegen
(
`<current-user>
<template v-slot:default="{result}">
<view v-for="(item,index) in result.list">{{item.name}}</view>
</template>
</current-user>`
,
`with(this){return _c('current-user',{attrs:{"_i":0},scopedSlots:_u([{key:"default",fn:function({result}, _svm, _si){return _l((_svm._$s(("2-"+_si),'f',{forItems:result.list})),function(item,index,$20,$30){return _c('view',{key:_svm._$s(("2-"+_si),'f',{forIndex:$20,key:("2-"+_si)+'-'+$30}),attrs:{"_i":(("2-"+_si)+$30)}},[_v((_svm._$s((("2-"+_si)+$30),'t0',_s(item.name))))])})}}])})}`
)
})
it
(
'
generate keep-alive
'
,
()
=>
{
assertCodegen
(
`<keep-alive exclude="componentWithStatus1"><component is="componentWithStatus"/></keep-alive>`
,
`with(this){return _c('keep-alive',{attrs:{"exclude":"componentWithStatus1","_i":0}},[_c("componentWithStatus",{tag:"component",attrs:{"_i":1}})],1)}`
)
assertCodegen
(
`<keep-alive :exclude="componentWithStatus1"><component :is="'componentWithStatus'+index"/></keep-alive>`
,
`with(this){return _c('keep-alive',{attrs:{"exclude":_$s(0,'a-exclude',componentWithStatus1),"_i":0}},[_c(_$s(1,'is','componentWithStatus'+index),{tag:"component",attrs:{"_i":1}})],1)}`
)
})
it
(
'
generate wxs props
'
,
()
=>
{
assertCodegen
(
'
<p :change:prop="swipe.sizeReady" :prop="pos" @touchstart="swipe.touchstart" @touchmove="swipe.touchmove" @touchend="swipe.touchend" @change="change"></p>
'
,
`with(this){return _c('p',{wxsProps:{"change:prop":"pos"},attrs:{"prop":_$s(0,'change:pos',pos),"_i":0},on:{"change":change}})}`
)
})
it
(
'
generate staticClass and id
'
,
()
=>
{
assertCodegen
(
'
<view id="aaa" class="bbbb"></view>
'
,
`with(this){return _c('view',{staticClass:_$s(0,'sc',"bbbb"),attrs:{"id":"aaa","_i":0}})}`
)
})
// TODO 后续优化 dataset
// it('generate dataset', () => {
// assertCodegen(
// '<view data-a="1" :data-b="b"></view>',
// `with(this){return _c('view',{attrs:{"data-a":"1","data-b":b,"_i":0}})}`
// )
// })
})
/* eslint-enable quotes */
packages/uni-template-compiler/__tests__/compiler-app-plus-extra.view.spec.js
浏览文件 @
32f99d02
...
...
@@ -63,5 +63,12 @@ describe('codegen', () => {
`with(this){return _c('v-uni-view',{wxsProps:{"change:prop":"pos"},attrs:{"change:prop":swipe.sizeReady,"prop":_$gc(0,'change:pos'),"_i":0},on:{"touchstart":function($event){$event = $handleWxsEvent($event);swipe.touchstart($event, $getComponentDescriptor())},"touchmove":function($event){$event = $handleWxsEvent($event);swipe.touchmove($event, $getComponentDescriptor())},"touchend":function($event){$event = $handleWxsEvent($event);swipe.touchend($event, $getComponentDescriptor())},"change":function($event){return $handleViewEvent($event)}}})}`
)
})
// TODO 后续优化dataset
// it('generate dataset', () => {
// assertCodegen(
// '<view data-a="1" :data-b="b"></view>',
// `with(this){return _c('v-uni-view',{attrs:{"_i":0}})}`
// )
// })
})
/* eslint-enable quotes */
packages/uni-template-compiler/__tests__/demo.js
浏览文件 @
32f99d02
const
compiler
=
require
(
'
../lib
'
)
const
res
=
compiler
.
compile
(
`
<view
><van-grid-item v-for="(item,index) in (4)" :key="item"></van-grid-item
></view>
<view
data-a="1" :data-b="b"
></view>
`
,
{
miniprogram
:
true
,
resourcePath
:
'
/User/fxy/Documents/test.wxml
'
,
...
...
packages/uni-template-compiler/lib/app/optimizer.js
浏览文件 @
32f99d02
...
...
@@ -63,7 +63,16 @@ function markStatic (node) {
const
isCustomComponent
=
isComponent
(
node
.
tag
)
if
(
node
.
attrs
&&
!
isCustomComponent
&&
node
.
tag
!==
'
keep-alive
'
)
{
// 移除静态属性
// 保留 id 属性, selectComponent 需要使用
node
.
attrs
=
node
.
attrs
.
filter
(
attr
=>
attr
.
name
===
'
id
'
||
attr
.
name
===
ID
||
isVar
(
attr
.
value
))
node
.
attrs
=
node
.
attrs
.
filter
(
attr
=>
{
const
{
name
,
value
}
=
attr
return
name
===
'
id
'
||
name
===
ID
||
// name.indexOf('data-') === 0 || // TODO dataset
isVar
(
value
)
})
}
node
.
children
=
node
.
children
.
filter
(
child
=>
{
// 移除静态文本
...
...
packages/uni-template-compiler/lib/app/parser/base-parser.js
浏览文件 @
32f99d02
...
...
@@ -57,13 +57,18 @@ function parseDirs (el, genVar, ignoreDirs = []) {
function
parseAttrs
(
el
,
genVar
)
{
el
.
attrs
&&
el
.
attrs
.
forEach
(
attr
=>
{
const
{
name
,
value
}
=
attr
if
(
attr
.
name
!==
ID
&&
attr
.
name
.
indexOf
(
'
change:
'
)
!==
0
&&
// wxs change:prop
isVar
(
attr
.
value
)
&&
attr
.
value
.
indexOf
(
'
_$
'
)
!==
0
// 已被提前处理过了,如 wxs prop:_$gc(2,'change:prop')
name
!==
ID
&&
// name.indexOf('data-') !== 0 && // TODO dataset 保留
name
.
indexOf
(
'
change:
'
)
!==
0
&&
// wxs change:prop
isVar
(
value
)
&&
value
.
indexOf
(
'
_$
'
)
!==
0
// 已被提前处理过了,如 wxs prop:_$gc(2,'change:prop')
)
{
attr
.
value
=
genVar
(
'
a-
'
+
attr
.
name
,
attr
.
value
)
attr
.
value
=
genVar
(
'
a-
'
+
name
,
value
)
}
})
}
...
...
packages/uni-template-compiler/lib/app/view.js
浏览文件 @
32f99d02
...
...
@@ -139,6 +139,11 @@ function transformNode (el, parent, state, isScopedSlot) {
parseWxsProps
(
el
,
{
isAppView
:
true
})
// if (el.attrs) { // TODO 过滤 dataset
// el.attrs = el.attrs.filter(attr => attr.name.indexOf('data-') !== 0)
// }
parseAttrs
(
el
,
genVar
)
parseProps
(
el
,
genVar
)
...
...
src/core/runtime/mp/constants.js
浏览文件 @
32f99d02
export
const
SOURCE_KEY
=
'
__data__
'
export
const
COMPONENT_LIFECYCLE
=
{
'
created
'
:
'
c
reated
'
,
'
attached
'
:
'
creat
ed
'
,
export
const
COMPONENT_LIFECYCLE
=
{
'
created
'
:
'
onServiceC
reated
'
,
'
attached
'
:
'
onServiceAttach
ed
'
,
'
ready
'
:
'
mounted
'
,
'
moved
'
:
'
moved
'
,
'
detached
'
:
'
destroyed
'
...
...
src/core/runtime/mp/index.js
浏览文件 @
32f99d02
...
...
@@ -8,6 +8,10 @@ import {
parseComponent
}
from
'
./parser/component-parser
'
import
{
handleRelations
}
from
'
./polyfill/relations
'
import
polyfill
from
'
./polyfill/index
'
export
*
from
'
./wxs
'
...
...
@@ -23,10 +27,21 @@ export function Page (options) {
global
[
'
__wxComponents
'
][
global
[
'
__wxRoute
'
]]
=
pageOptions
}
function
initRelationsHandler
(
vueComponentOptions
)
{
// linked 需要在当前组件 attached 之后再执行
if
(
!
vueComponentOptions
[
'
onServiceAttached
'
])
{
vueComponentOptions
[
'
onServiceAttached
'
]
=
[]
}
vueComponentOptions
[
'
onServiceAttached
'
].
push
(
function
onServiceAttached
()
{
handleRelations
(
this
,
'
linked
'
)
})
}
export
function
Component
(
options
)
{
const
componentOptions
=
parseComponent
(
options
)
componentOptions
.
mixins
.
unshift
(
polyfill
)
componentOptions
.
mpOptions
.
path
=
global
[
'
__wxRoute
'
]
initRelationsHandler
(
componentOptions
)
global
[
'
__wxComponents
'
][
global
[
'
__wxRoute
'
]]
=
componentOptions
}
...
...
src/core/runtime/mp/parser/lifecycle-parser.js
浏览文件 @
32f99d02
...
...
@@ -13,5 +13,5 @@ export function parseLifecycle (mpComponentOptions, vueComponentOptions) {
(
vueComponentOptions
[
COMPONENT_LIFECYCLE
[
name
]]
||
(
vueComponentOptions
[
COMPONENT_LIFECYCLE
[
name
]]
=
[]))
.
push
(
mpComponentOptions
[
name
])
}
})
})
}
src/core/runtime/mp/polyfill/index.js
浏览文件 @
32f99d02
...
...
@@ -13,17 +13,18 @@ import {
import
{
handleObservers
}
from
'
./observers
'
}
from
'
./observers
'
export
default
{
beforeCreate
()
{
// 取消 development 时的 Proxy,避免小程序组件模板中使用尚未定义的属性告警
this
.
_renderProxy
=
this
},
created
()
{
// properties 中可能会访问 methods,故需要在 created 中初始化
initState
(
this
)
initMethods
(
this
)
initRelations
(
this
)
},
created
()
{
handleRelations
(
this
,
'
linked
'
)
},
mounted
()
{
handleObservers
(
this
)
},
...
...
src/core/runtime/mp/polyfill/relations.js
浏览文件 @
32f99d02
function
initRelationHandlers
(
type
,
handler
,
target
,
ctx
,
handlerCtx
)
{
function
initRelationHandlers
(
type
,
handler
,
target
,
ctx
)
{
if
(
!
handler
)
{
return
}
const
name
=
`_$
${
type
}
Handlers`
;
(
handlerCtx
[
name
]
||
(
handlerC
tx
[
name
]
=
[])).
push
(
function
()
{
(
ctx
[
name
]
||
(
c
tx
[
name
]
=
[])).
push
(
function
()
{
handler
.
call
(
ctx
,
target
)
})
}
function
initLinkedHandlers
(
relation
,
target
,
ctx
,
handlerCtx
)
{
function
initLinkedHandlers
(
relation
,
target
,
ctx
)
{
const
type
=
'
linked
'
const
name
=
relation
.
name
const
relationNodes
=
ctx
.
_$relationNodes
||
(
ctx
.
_$relationNodes
=
Object
.
create
(
null
));
(
relationNodes
[
name
]
||
(
relationNodes
[
name
]
=
[])).
push
(
target
)
initRelationHandlers
(
type
,
relation
[
type
],
target
,
ctx
,
handlerCtx
)
initRelationHandlers
(
type
,
relation
[
type
],
target
,
ctx
)
}
function
initUnlinkedHandlers
(
relation
,
target
,
ctx
,
handlerCtx
)
{
function
initUnlinkedHandlers
(
relation
,
target
,
ctx
)
{
const
type
=
'
unlinked
'
initRelationHandlers
(
type
,
relation
[
type
],
target
,
ctx
,
handlerCtx
)
initRelationHandlers
(
type
,
relation
[
type
],
target
,
ctx
)
}
function
findParentRelation
(
parentVm
,
target
,
type
)
{
...
...
@@ -44,12 +44,12 @@ function initParentRelation (vm, childRelation, match) {
if
(
!
parentRelation
)
{
return
}
// 先父后子
initLinkedHandlers
(
parentRelation
,
vm
,
parentVm
,
vm
)
initLinkedHandlers
(
childRelation
,
parentVm
,
vm
,
vm
)
initUnlinkedHandlers
(
parentRelation
,
vm
,
parentVm
,
vm
)
initUnlinkedHandlers
(
childRelation
,
parentVm
,
vm
,
vm
)
initLinkedHandlers
(
parentRelation
,
vm
,
parentVm
)
initLinkedHandlers
(
childRelation
,
parentVm
,
vm
)
initUnlinkedHandlers
(
parentRelation
,
vm
,
parentVm
)
initUnlinkedHandlers
(
childRelation
,
parentVm
,
vm
)
}
function
initRelation
(
relation
,
vm
)
{
...
...
src/core/runtime/mp/polyfill/state/properties.js
浏览文件 @
32f99d02
...
...
@@ -43,7 +43,12 @@ function validateProp (key, propsOptions, propsData, vm) {
value
=
!!
value
}
const
observer
=
propOptions
&&
propOptions
.
observer
observer
&&
observe
(
observer
,
vm
,
value
)
if
(
observer
)
{
// 初始化时,异步触发 observer,否则 observer 中无法访问 methods 或其他
setTimeout
(
function
()
{
observe
(
observer
,
vm
,
value
)
},
4
)
}
return
value
}
return
getPropertyVal
(
propsOptions
[
key
])
...
...
@@ -84,7 +89,7 @@ export function initProperties (vm, instanceData) {
/* eslint-disable no-self-compare */
if
(
newVal
===
value
||
(
newVal
!==
newVal
&&
value
!==
value
))
{
return
}
}
value
=
newVal
if
(
observer
)
{
observe
(
observer
,
vm
,
newVal
,
oldVal
)
...
...
src/core/service/plugins/lifecycle.js
浏览文件 @
32f99d02
...
...
@@ -28,7 +28,10 @@ const LIFECYCLE_HOOKS = [
// 'onReady', // 兼容旧版本,应该移除该事件
'
onPageShow
'
,
'
onPageHide
'
,
'
onPageResize
'
'
onPageResize
'
,
// 小程序的 created,attached 生命周期(需要在 service 层的 Vue 内核 mounted 时触发,因小程序 created 可以使用 selectComponent)
'
onServiceCreated
'
,
'
onServiceAttached
'
]
export
function
lifecycleMixin
(
Vue
)
{
// fixed vue-class-component
...
...
src/core/service/plugins/polyfill.js
浏览文件 @
32f99d02
...
...
@@ -12,7 +12,15 @@ function parseSelector (selector) {
if
(
selector
.
indexOf
(
'
#
'
)
===
0
)
{
const
id
=
selector
.
substr
(
1
)
return
function
match
(
vnode
)
{
return
vnode
.
data
&&
vnode
.
data
.
attrs
&&
vnode
.
data
.
attrs
.
id
===
id
// props
if
(
vnode
.
componentInstance
&&
vnode
.
componentInstance
.
id
===
id
)
{
return
true
}
// attrs
if
(
vnode
.
data
&&
vnode
.
data
.
attrs
&&
vnode
.
data
.
attrs
.
id
===
id
)
{
return
true
}
return
false
}
}
else
if
(
selector
.
indexOf
(
'
.
'
)
===
0
)
{
const
clazz
=
selector
.
substr
(
1
)
...
...
@@ -52,17 +60,21 @@ function querySelectorAll (vm, matchSelector, ret) {
}
const
$children
=
vm
.
$children
for
(
let
i
=
0
;
i
<
$children
.
length
;
i
++
)
{
const
childVm
=
querySelectorAll
(
$children
[
i
],
matchSelector
,
ret
)
childVm
&&
ret
.
push
(
childVm
)
querySelectorAll
(
$children
[
i
],
matchSelector
,
ret
)
}
return
ret
}
export
function
initPolyfill
(
Vue
)
{
Vue
.
prototype
.
createIntersectionObserver
=
function
createIntersectionObserver
(
options
)
{
return
uni
.
createIntersectionObserver
(
this
,
options
)
}
Vue
.
prototype
.
selectComponent
=
function
selectComponent
(
selector
)
{
return
querySelector
(
this
,
parseSelector
(
selector
))
}
Vue
.
prototype
.
selectAllComponent
=
function
selectAllComponent
(
selector
)
{
Vue
.
prototype
.
selectAllComponent
s
=
function
selectAllComponents
(
selector
)
{
return
querySelectorAll
(
this
,
parseSelector
(
selector
),
[])
}
}
src/core/view/bridge/subscribe/api/util.js
浏览文件 @
32f99d02
...
...
@@ -12,7 +12,10 @@ function findVmById (id, vm) {
}
}
export
function
findElm
(
component
,
pageVm
)
{
export
function
findElm
(
component
,
pageVm
)
{
if
(
!
pageVm
)
{
return
console
.
error
(
`page is not ready`
)
}
if
(
!
component
)
{
return
pageVm
.
$el
}
...
...
src/platforms/app-plus/service/framework/page.js
浏览文件 @
32f99d02
...
...
@@ -95,8 +95,8 @@ export function registerPage ({
selectComponent
(
selector
)
{
return
this
.
$vm
.
selectComponent
(
selector
)
},
selectAllComponent
(
selector
)
{
return
this
.
$vm
.
selectAllComponent
(
selector
)
selectAllComponent
s
(
selector
)
{
return
this
.
$vm
.
selectAllComponent
s
(
selector
)
}
}
...
...
src/platforms/app-plus/service/framework/plugins/data.js
浏览文件 @
32f99d02
...
...
@@ -144,6 +144,12 @@ function setData (id, name, value) {
case
V_FOR
:
return
setForData
.
call
(
this
,
id
,
value
)
}
// TODO 暂时先传递 dataset 至 view 层(理论上不需要)
if
(
name
.
indexOf
(
'
a-data-
'
)
===
0
)
{
try
{
value
=
JSON
.
stringify
(
value
)
}
catch
(
e
)
{}
}
return
((
this
.
_$newData
[
id
]
||
(
this
.
_$newData
[
id
]
=
{}))[
name
]
=
value
)
}
...
...
src/platforms/app-plus/service/framework/plugins/diff.js
浏览文件 @
32f99d02
...
...
@@ -3,7 +3,8 @@ import {
}
from
'
uni-shared
'
import
{
V_FOR
V_FOR
,
B_STYLE
}
from
'
../../constants
'
function
setResult
(
data
,
k
,
v
)
{
...
...
@@ -52,11 +53,14 @@ function diffElmData (newObj, oldObj) {
old
=
oldObj
[
key
]
if
(
old
!==
cur
)
{
// 全量同步 style (因为 style 可能会动态删除部分样式)
// if (key === B_STYLE && isPlainObject(cur) && isPlainObject(old)) {
// const style = diffObject(cur, old)
// style && setResult(result || (result = Object.create(null)), B_STYLE, style)
// } else
if
(
key
===
V_FOR
&&
Array
.
isArray
(
cur
)
&&
Array
.
isArray
(
old
))
{
if
(
key
===
B_STYLE
&&
isPlainObject
(
cur
)
&&
isPlainObject
(
old
))
{
if
(
Object
.
keys
(
cur
).
length
!==
Object
.
keys
(
old
).
length
)
{
// 长度不等
setResult
(
result
||
(
result
=
Object
.
create
(
null
)),
B_STYLE
,
cur
)
}
else
{
const
style
=
diffObject
(
cur
,
old
,
false
)
style
&&
setResult
(
result
||
(
result
=
Object
.
create
(
null
)),
B_STYLE
,
style
)
}
}
else
if
(
key
===
V_FOR
&&
Array
.
isArray
(
cur
)
&&
Array
.
isArray
(
old
))
{
const
vFor
=
diffArray
(
cur
,
old
)
vFor
&&
setResult
(
result
||
(
result
=
Object
.
create
(
null
)),
V_FOR
,
vFor
)
}
else
{
...
...
src/platforms/app-plus/service/framework/plugins/vdom-sync.js
浏览文件 @
32f99d02
...
...
@@ -152,20 +152,20 @@ export class VDomSync {
this
.
initialized
=
true
this
.
batchData
.
push
([
PAGE_CREATED
,
[
this
.
pageId
,
this
.
pagePath
]])
}
this
.
batchData
=
this
.
batchData
.
filter
(
data
=>
{
const
batchData
=
this
.
batchData
.
filter
(
data
=>
{
if
(
data
[
0
]
===
UPDATED_DATA
&&
!
Object
.
keys
(
data
[
1
][
1
]).
length
)
{
return
false
}
return
true
})
if
(
this
.
batchData
.
length
)
{
this
.
batchData
.
length
=
0
if
(
batchData
.
length
)
{
UniServiceJSBridge
.
publishHandler
(
VD_SYNC
,
{
data
:
this
.
batchData
,
data
:
batchData
,
options
:
{
timestamp
:
Date
.
now
()
}
},
[
this
.
pageId
])
this
.
batchData
.
length
=
0
}
}
...
...
src/platforms/app-plus/view/framework/plugins/data.js
浏览文件 @
32f99d02
...
...
@@ -34,8 +34,8 @@ const handleData = {
const
[
pageId
,
pagePath
,
pageOptions
]
=
data
document
.
title
=
`
${
pagePath
}
[
${
pageId
}
]`
// 设置当前页面伪对象,方便其他地方使用 getCurrentPages 获取当前页面 id,route
setCurrentPage
(
pageId
,
pagePath
)
// 通知页面创建,根据当前页面配置信息,初始化部分事件
setCurrentPage
(
pageId
,
pagePath
)
// 通知页面创建,根据当前页面配置信息,初始化部分事件
UniViewJSBridge
.
subscribeHandler
(
ON_PAGE_CREATE
,
pageOptions
,
pageId
)
// 初始化当前页面 VueComponent(生成页面样式代码)
PageVueComponent
=
getPageVueComponent
(
pagePath
)
...
...
@@ -103,6 +103,9 @@ function vdSync ({
function
getData
(
id
,
name
)
{
try
{
if
(
name
.
indexOf
(
'
a-data-
'
)
===
0
)
{
// TODO 临时方案序列化,反序列化dataset,后续应该将dataset保留在service层
return
JSON
.
parse
(
this
.
$r
[
id
][
name
])
}
return
this
.
$r
[
id
][
name
]
}
catch
(
e
)
{
console
.
error
(
this
.
$options
.
__file
+
`:[
${
this
.
_$id
}
]$r[
${
id
}
][
${
name
}
] is undefined`
)
...
...
@@ -124,7 +127,7 @@ function getChangeData (id, name) {
}
export
function
initData
(
Vue
)
{
Vue
.
prototype
.
_$g
=
getData
Vue
.
prototype
.
_$g
=
getData
Vue
.
prototype
.
_$gc
=
getChangeData
UniViewJSBridge
.
subscribe
(
VD_SYNC
,
vdSync
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录