Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
genary
uni-app
提交
5bef921d
U
uni-app
项目概览
genary
/
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,发现更多精彩内容 >>
提交
5bef921d
编写于
5月 16, 2019
作者:
fxy060608
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat(mp): refactor
上级
63fa0d5e
变更
34
展开全部
显示空白变更内容
内联
并排
Showing
34 changed file
with
2701 addition
and
1793 deletion
+2701
-1793
build/rollup.config.js
build/rollup.config.js
+2
-1
packages/uni-app-plus/dist/index.js
packages/uni-app-plus/dist/index.js
+290
-230
packages/uni-mp-alipay/dist/index.js
packages/uni-mp-alipay/dist/index.js
+450
-422
packages/uni-mp-baidu/dist/index.js
packages/uni-mp-baidu/dist/index.js
+298
-252
packages/uni-mp-toutiao/dist/index.js
packages/uni-mp-toutiao/dist/index.js
+351
-237
packages/uni-mp-weixin/dist/index.js
packages/uni-mp-weixin/dist/index.js
+259
-233
src/core/runtime/wrapper/create-app.js
src/core/runtime/wrapper/create-app.js
+4
-109
src/core/runtime/wrapper/create-component.js
src/core/runtime/wrapper/create-component.js
+4
-106
src/core/runtime/wrapper/create-page.js
src/core/runtime/wrapper/create-page.js
+5
-101
src/core/runtime/wrapper/util.js
src/core/runtime/wrapper/util.js
+52
-23
src/platforms/app-plus/runtime/wrapper/app-parser.js
src/platforms/app-plus/runtime/wrapper/app-parser.js
+17
-0
src/platforms/app-plus/runtime/wrapper/component-parser.js
src/platforms/app-plus/runtime/wrapper/component-parser.js
+10
-0
src/platforms/app-plus/runtime/wrapper/index.js
src/platforms/app-plus/runtime/wrapper/index.js
+0
-19
src/platforms/app-plus/runtime/wrapper/page-parser.js
src/platforms/app-plus/runtime/wrapper/page-parser.js
+21
-0
src/platforms/mp-alipay/runtime/wrapper/app-parser.js
src/platforms/mp-alipay/runtime/wrapper/app-parser.js
+32
-0
src/platforms/mp-alipay/runtime/wrapper/component-parser.js
src/platforms/mp-alipay/runtime/wrapper/component-parser.js
+123
-0
src/platforms/mp-alipay/runtime/wrapper/page-parser.js
src/platforms/mp-alipay/runtime/wrapper/page-parser.js
+73
-0
src/platforms/mp-alipay/runtime/wrapper/util.js
src/platforms/mp-alipay/runtime/wrapper/util.js
+150
-0
src/platforms/mp-baidu/runtime/wrapper/app-parser.js
src/platforms/mp-baidu/runtime/wrapper/app-parser.js
+16
-0
src/platforms/mp-baidu/runtime/wrapper/component-parser.js
src/platforms/mp-baidu/runtime/wrapper/component-parser.js
+33
-0
src/platforms/mp-baidu/runtime/wrapper/index.js
src/platforms/mp-baidu/runtime/wrapper/index.js
+0
-38
src/platforms/mp-baidu/runtime/wrapper/page-parser.js
src/platforms/mp-baidu/runtime/wrapper/page-parser.js
+39
-0
src/platforms/mp-baidu/runtime/wrapper/util.js
src/platforms/mp-baidu/runtime/wrapper/util.js
+9
-0
src/platforms/mp-toutiao/runtime/wrapper/app-parser.js
src/platforms/mp-toutiao/runtime/wrapper/app-parser.js
+28
-0
src/platforms/mp-toutiao/runtime/wrapper/component-parser.js
src/platforms/mp-toutiao/runtime/wrapper/component-parser.js
+50
-0
src/platforms/mp-toutiao/runtime/wrapper/page-parser.js
src/platforms/mp-toutiao/runtime/wrapper/page-parser.js
+27
-0
src/platforms/mp-toutiao/runtime/wrapper/util.js
src/platforms/mp-toutiao/runtime/wrapper/util.js
+80
-0
src/platforms/mp-weixin/runtime/wrapper/app-base-parser.js
src/platforms/mp-weixin/runtime/wrapper/app-base-parser.js
+74
-0
src/platforms/mp-weixin/runtime/wrapper/app-parser.js
src/platforms/mp-weixin/runtime/wrapper/app-parser.js
+13
-0
src/platforms/mp-weixin/runtime/wrapper/component-base-parser.js
...tforms/mp-weixin/runtime/wrapper/component-base-parser.js
+95
-0
src/platforms/mp-weixin/runtime/wrapper/component-parser.js
src/platforms/mp-weixin/runtime/wrapper/component-parser.js
+13
-0
src/platforms/mp-weixin/runtime/wrapper/page-base-parser.js
src/platforms/mp-weixin/runtime/wrapper/page-base-parser.js
+33
-0
src/platforms/mp-weixin/runtime/wrapper/page-parser.js
src/platforms/mp-weixin/runtime/wrapper/page-parser.js
+13
-0
src/platforms/mp-weixin/runtime/wrapper/util.js
src/platforms/mp-weixin/runtime/wrapper/util.js
+37
-22
未找到文件。
build/rollup.config.js
浏览文件 @
5bef921d
...
...
@@ -36,7 +36,8 @@ module.exports = {
plugins
:
[
alias
({
'
uni-shared
'
:
path
.
resolve
(
__dirname
,
'
../src/shared/util.js
'
),
'
uni-platform
'
:
path
.
resolve
(
__dirname
,
'
../src/platforms/
'
+
process
.
env
.
UNI_PLATFORM
)
'
uni-platform
'
:
path
.
resolve
(
__dirname
,
'
../src/platforms/
'
+
process
.
env
.
UNI_PLATFORM
),
'
uni-wrapper
'
:
path
.
resolve
(
__dirname
,
'
../src/core/runtime/wrapper
'
)
}),
replace
({
__GLOBAL__
:
platform
.
prefix
,
...
...
packages/uni-app-plus/dist/index.js
浏览文件 @
5bef921d
...
...
@@ -40,7 +40,7 @@ const camelize = cached((str) => {
return
str
.
replace
(
camelizeRE
,
(
_
,
c
)
=>
c
?
c
.
toUpperCase
()
:
''
)
});
const
SYNC_API_RE
=
/subNVue|requireNativePlugin|upx2px|hideKeyboard|canIUse|^create|Sync$|Manager$/
;
const
SYNC_API_RE
=
/subNVue|requireNativePlugin|upx2px|hideKeyboard|canIUse|^create|Sync$|Manager$
|base64ToArrayBuffer|arrayBufferToBase64
/
;
const
CONTEXT_API_RE
=
/^create|Manager$/
;
...
...
@@ -89,6 +89,7 @@ function promisify (name, api) {
fail
:
reject
}),
...
params
);
/* eslint-disable no-extend-native */
if
(
!
Promise
.
prototype
.
finally
)
{
Promise
.
prototype
.
finally
=
function
(
callback
)
{
const
promise
=
this
.
constructor
;
return
this
.
then
(
...
...
@@ -98,6 +99,7 @@ function promisify (name, api) {
})
)
};
}
}))
}
}
...
...
@@ -371,84 +373,67 @@ Component = function (options = {}) {
return
MPComponent
(
options
)
};
const
mocks
=
[
'
__route__
'
,
'
__wxExparserNodeId__
'
,
'
__wxWebviewId__
'
];
const
PAGE_EVENT_HOOKS
=
[
'
onPullDownRefresh
'
,
'
onReachBottom
'
,
'
onShareAppMessage
'
,
'
onPageScroll
'
,
'
onResize
'
,
'
onTabItemTap
'
];
function
initBehavior
(
options
)
{
return
Behavior
(
options
)
}
function
initRefs
(
vm
)
{
const
mpInstance
=
vm
.
$scope
;
Object
.
defineProperty
(
vm
,
'
$refs
'
,
{
get
()
{
const
$refs
=
{};
const
components
=
mpInstance
.
selectAllComponents
(
'
.vue-ref
'
);
components
.
forEach
(
component
=>
{
const
ref
=
component
.
dataset
.
ref
;
$refs
[
ref
]
=
component
.
$vm
||
component
;
});
const
forComponents
=
mpInstance
.
selectAllComponents
(
'
.vue-ref-in-for
'
);
forComponents
.
forEach
(
component
=>
{
const
ref
=
component
.
dataset
.
ref
;
if
(
!
$refs
[
ref
])
{
$refs
[
ref
]
=
[];
}
$refs
[
ref
].
push
(
component
.
$vm
||
component
);
});
return
$refs
function
initMocks
(
vm
,
mocks
)
{
const
mpInstance
=
vm
.
$mp
[
vm
.
mpType
];
mocks
.
forEach
(
mock
=>
{
if
(
hasOwn
(
mpInstance
,
mock
))
{
vm
[
mock
]
=
mpInstance
[
mock
];
}
});
}
function
triggerLink
(
mpInstance
,
vueOptions
)
{
mpInstance
.
triggerEvent
(
'
__l
'
,
mpInstance
.
$vm
||
vueOptions
,
{
bubbles
:
true
,
composed
:
true
function
initHooks
(
mpOptions
,
hooks
)
{
hooks
.
forEach
(
hook
=>
{
mpOptions
[
hook
]
=
function
(
args
)
{
return
this
.
$vm
&&
this
.
$vm
.
__call_hook
(
hook
,
args
)
};
});
}
function
handleLink
(
event
)
{
if
(
event
.
detail
.
$mp
)
{
// vm
if
(
!
event
.
detail
.
$parent
)
{
event
.
detail
.
$parent
=
this
.
$vm
;
event
.
detail
.
$parent
.
$children
.
push
(
event
.
detail
);
event
.
detail
.
$root
=
this
.
$vm
.
$root
;
}
}
else
{
// vueOptions
if
(
!
event
.
detail
.
parent
)
{
event
.
detail
.
parent
=
this
.
$vm
;
}
function
initVueComponent
(
Vue$$1
,
vueOptions
)
{
vueOptions
=
vueOptions
.
default
||
vueOptions
;
let
VueComponent
;
if
(
isFn
(
vueOptions
))
{
VueComponent
=
vueOptions
;
vueOptions
=
VueComponent
.
extendOptions
;
}
else
{
VueComponent
=
Vue$$1
.
extend
(
vueOptions
);
}
return
[
VueComponent
,
vueOptions
]
}
function
initPage$1
(
pageOptions
)
{
return
initComponent$1
(
pageOptions
)
function
initSlots
(
vm
,
vueSlots
)
{
if
(
Array
.
isArray
(
vueSlots
)
&&
vueSlots
.
length
)
{
const
$slots
=
Object
.
create
(
null
);
vueSlots
.
forEach
(
slotName
=>
{
$slots
[
slotName
]
=
true
;
});
vm
.
$scopedSlots
=
vm
.
$slots
=
$slots
;
}
}
function
initComponent$1
(
componentOptions
)
{
componentOptions
.
methods
.
$getAppWebview
=
function
()
{
return
plus
.
webview
.
getWebviewById
(
`
${
this
.
__wxWebviewId__
}
`
)
};
return
Component
(
componentOptions
)
}
function
initVueIds
(
vueIds
,
mpInstance
)
{
vueIds
=
(
vueIds
||
''
).
split
(
'
,
'
);
const
len
=
vueIds
.
length
;
function
initMocks
(
vm
,
mocks$$
1
)
{
const
mpInstance
=
vm
.
$mp
[
vm
.
mpType
];
mocks$$1
.
forEach
(
mock
=>
{
if
(
hasOwn
(
mpInstance
,
mock
))
{
vm
[
mock
]
=
mpInstance
[
mock
];
if
(
len
===
1
)
{
mpInstance
.
_$vueId
=
vueIds
[
0
];
}
else
if
(
len
===
2
)
{
mpInstance
.
_$vueId
=
vueIds
[
0
];
mpInstance
.
_$vuePid
=
vueIds
[
1
];
}
});
}
function
initHooks
(
mpOptions
,
hooks
)
{
hooks
.
forEach
(
hook
=>
{
mpOptions
[
hook
]
=
function
(
args
)
{
return
this
.
$vm
.
__call_hook
(
hook
,
args
)
};
});
}
function
getData
(
vueOptions
,
context
)
{
function
initData
(
vueOptions
,
context
)
{
let
data
=
vueOptions
.
data
||
{};
const
methods
=
vueOptions
.
methods
||
{};
...
...
@@ -490,7 +475,7 @@ function createObserver (name) {
}
}
function
getBehaviors
(
vueOptions
)
{
function
initBehaviors
(
vueOptions
,
initBehavior
)
{
const
vueBehaviors
=
vueOptions
[
'
behaviors
'
];
const
vueExtends
=
vueOptions
[
'
extends
'
];
const
vueMixins
=
vueOptions
[
'
mixins
'
];
...
...
@@ -519,7 +504,7 @@ function getBehaviors (vueOptions) {
if
(
isPlainObject
(
vueExtends
)
&&
vueExtends
.
props
)
{
behaviors
.
push
(
initBehavior
({
properties
:
ge
tProperties
(
vueExtends
.
props
,
true
)
properties
:
ini
tProperties
(
vueExtends
.
props
,
true
)
})
);
}
...
...
@@ -528,7 +513,7 @@ function getBehaviors (vueOptions) {
if
(
isPlainObject
(
vueMixin
)
&&
vueMixin
.
props
)
{
behaviors
.
push
(
initBehavior
({
properties
:
ge
tProperties
(
vueMixin
.
props
,
true
)
properties
:
ini
tProperties
(
vueMixin
.
props
,
true
)
})
);
}
...
...
@@ -545,9 +530,13 @@ function parsePropType (key, type, defaultValue, file) {
return
type
}
function
ge
tProperties
(
props
,
isBehavior
=
false
,
file
=
''
)
{
function
ini
tProperties
(
props
,
isBehavior
=
false
,
file
=
''
)
{
const
properties
=
{};
if
(
!
isBehavior
)
{
properties
.
vueId
=
{
type
:
String
,
value
:
''
};
properties
.
vueSlots
=
{
// 小程序不能直接定义 $slots 的 props,所以通过 vueSlots 转换到 $slots
type
:
null
,
value
:
[],
...
...
@@ -798,23 +787,14 @@ function handleEvent (event) {
const
hooks
=
[
'
onHide
'
,
'
onError
'
,
'
onPageNotFound
'
,
'
onUniNViewMessage
'
'
onPageNotFound
'
];
function
initVm
(
vm
)
{
if
(
this
.
$vm
)
{
// 百度竟然 onShow 在 onLaunch 之前?
return
}
this
.
$vm
=
vm
;
this
.
$vm
.
$mp
=
{
app
:
this
};
}
function
createApp
(
vm
)
{
function
parseBaseApp
(
vm
,
{
mocks
,
initRefs
})
{
Vue
.
prototype
.
mpHost
=
"
app-plus
"
;
Vue
.
mixin
({
beforeCreate
()
{
...
...
@@ -838,183 +818,182 @@ function createApp (vm) {
initRefs
(
this
);
initMocks
(
this
,
mocks
);
}
},
created
()
{
// 处理 injections
this
.
__init_injections
(
this
);
this
.
__init_provide
(
this
);
}
});
const
appOptions
=
{
onLaunch
(
args
)
{
initVm
.
call
(
this
,
vm
);
this
.
$vm
=
vm
;
this
.
$vm
.
$mp
=
{
app
:
this
};
this
.
$vm
.
$scope
=
this
;
this
.
$vm
.
_isMounted
=
true
;
this
.
$vm
.
__call_hook
(
'
mounted
'
);
this
.
$vm
.
__call_hook
(
'
mounted
'
,
args
);
this
.
$vm
.
__call_hook
(
'
onLaunch
'
,
args
);
},
onShow
(
args
)
{
initVm
.
call
(
this
,
vm
);
this
.
$vm
.
__call_hook
(
'
onShow
'
,
args
);
}
};
// 兼容旧版本 globalData
appOptions
.
globalData
=
vm
.
$options
.
globalData
||
{};
initHooks
(
appOptions
,
hooks
);
// 延迟执行,因为 App 的注册在 main.js 之前,可能导致生命周期内 Vue 原型上开发者注册的属性无法访问
App
(
appOptions
);
initHooks
(
appOptions
,
hooks
);
return
vm
return
appOptions
}
const
hooks$1
=
[
'
onShow
'
,
'
onHide
'
,
'
onPullDownRefresh
'
,
'
onReachBottom
'
,
'
onShareAppMessage
'
,
'
onPageScroll
'
,
'
onResize
'
,
'
onTabItemTap
'
,
'
onBackPress
'
,
'
onNavigationBarButtonTap
'
,
'
onNavigationBarSearchInputChanged
'
,
'
onNavigationBarSearchInputConfirmed
'
,
'
onNavigationBarSearchInputClicked
'
];
const
mocks
=
[
'
__route__
'
,
'
__wxExparserNodeId__
'
,
'
__wxWebviewId__
'
];
function
initVm$1
(
VueComponent
)
{
// 百度的 onLoad 触发在 attached 之前
if
(
this
.
$vm
)
{
return
function
findVmByVueId
(
vm
,
vuePid
)
{
const
$children
=
vm
.
$children
;
// 优先查找直属
let
parentVm
=
$children
.
find
(
childVm
=>
childVm
.
$scope
.
_$vueId
===
vuePid
);
if
(
parentVm
)
{
return
parentVm
}
// 反向递归查找
for
(
let
i
=
$children
.
length
-
1
;
i
>=
0
;
i
--
)
{
parentVm
=
findVmByVueId
(
$children
[
i
],
vuePid
);
if
(
parentVm
)
{
return
parentVm
}
}
}
this
.
$vm
=
new
VueComponent
({
mpType
:
'
page
'
,
mpInstance
:
this
});
function
initBehavior
(
options
)
{
return
Behavior
(
options
)
}
this
.
$vm
.
__call_hook
(
'
created
'
);
this
.
$vm
.
$mount
();
function
isPage
()
{
return
!!
this
.
route
}
function
createPage
(
vueOptions
)
{
vueOptions
=
vueOptions
.
default
||
vueOptions
;
let
VueComponent
;
if
(
isFn
(
vueOptions
))
{
VueComponent
=
vueOptions
;
vueOptions
=
VueComponent
.
extendOptions
;
}
else
{
VueComponent
=
Vue
.
extend
(
vueOptions
);
}
const
pageOptions
=
{
options
:
{
multipleSlots
:
true
,
addGlobalClass
:
true
},
data
:
getData
(
vueOptions
,
Vue
.
prototype
),
lifetimes
:
{
// 当页面作为组件时
attached
()
{
initVm$1
.
call
(
this
,
VueComponent
);
},
ready
()
{
this
.
$vm
.
__call_hook
(
'
beforeMount
'
);
this
.
$vm
.
_isMounted
=
true
;
this
.
$vm
.
__call_hook
(
'
mounted
'
);
this
.
$vm
.
__call_hook
(
'
onReady
'
);
},
detached
()
{
this
.
$vm
.
$destroy
();
function
initRelation
(
detail
)
{
this
.
triggerEvent
(
'
__l
'
,
detail
);
}
function
initRefs
(
vm
)
{
const
mpInstance
=
vm
.
$scope
;
Object
.
defineProperty
(
vm
,
'
$refs
'
,
{
get
()
{
const
$refs
=
{};
const
components
=
mpInstance
.
selectAllComponents
(
'
.vue-ref
'
);
components
.
forEach
(
component
=>
{
const
ref
=
component
.
dataset
.
ref
;
$refs
[
ref
]
=
component
.
$vm
||
component
;
});
const
forComponents
=
mpInstance
.
selectAllComponents
(
'
.vue-ref-in-for
'
);
forComponents
.
forEach
(
component
=>
{
const
ref
=
component
.
dataset
.
ref
;
if
(
!
$refs
[
ref
])
{
$refs
[
ref
]
=
[];
}
},
methods
:
{
// 作为页面时
onLoad
(
args
)
{
initVm$1
.
call
(
this
,
VueComponent
);
this
.
$vm
.
$mp
.
query
=
args
;
// 又要兼容 mpvue
this
.
$vm
.
__call_hook
(
'
onLoad
'
,
args
);
// 开发者可能会在 onLoad 时赋值,提前到 mount 之前
},
onUnload
()
{
this
.
$vm
.
__call_hook
(
'
onUnload
'
);
},
__e
:
handleEvent
,
__l
:
handleLink
$refs
[
ref
].
push
(
component
.
$vm
||
component
);
});
return
$refs
}
};
});
}
initHooks
(
pageOptions
.
methods
,
hooks$1
);
function
handleLink
(
event
)
{
const
{
vuePid
,
vueOptions
}
=
event
.
detail
||
event
.
value
;
// detail 是微信,value 是百度(dipatch)
return
initPage$1
(
pageOptions
,
vueOptions
)
}
let
parentVm
;
function
initVm$2
(
VueComponent
)
{
if
(
this
.
$vm
)
{
return
if
(
vuePid
)
{
parentVm
=
findVmByVueId
(
this
.
$vm
,
vuePid
);
}
const
properties
=
this
.
properties
;
if
(
!
parentVm
)
{
parentVm
=
this
.
$vm
;
}
const
options
=
{
mpType
:
'
component
'
,
mpInstance
:
this
,
propsData
:
properties
};
// 初始化 vue 实例
this
.
$vm
=
new
VueComponent
(
options
);
vueOptions
.
parent
=
parentVm
;
}
// 处理$slots,$scopedSlots(暂不支持动态变化$slots)
const
vueSlots
=
properties
.
vueSlots
;
if
(
Array
.
isArray
(
vueSlots
)
&&
vueSlots
.
length
)
{
const
$slots
=
Object
.
create
(
null
);
vueSlots
.
forEach
(
slotName
=>
{
$slots
[
slotName
]
=
true
;
});
this
.
$vm
.
$scopedSlots
=
this
.
$vm
.
$slots
=
$slots
;
}
// 性能优先,mount 提前到 attached 中,保证组件首次渲染数据被合并
// 导致与标准 Vue 的差异,data 和 computed 中不能使用$parent,provide等组件属性
this
.
$vm
.
$mount
();
function
parseApp
(
vm
)
{
return
parseBaseApp
(
vm
,
{
mocks
,
initRefs
})
}
function
createComponent
(
vueOptions
)
{
vueOptions
=
vueOptions
.
default
||
vueOptions
;
const
hooks$1
=
[
'
onUniNViewMessage
'
];
let
VueComponent
;
if
(
isFn
(
vueOptions
))
{
VueComponent
=
vueOptions
;
// TODO form-field props.name,props.value
vueOptions
=
VueComponent
.
extendOptions
;
}
else
{
VueComponent
=
Vue
.
extend
(
vueOptions
);
}
function
parseApp$1
(
vm
)
{
const
appOptions
=
parseApp
(
vm
);
const
behaviors
=
getBehaviors
(
vueOptions
);
initHooks
(
appOptions
,
hooks$1
);
const
properties
=
getProperties
(
vueOptions
.
props
,
false
,
vueOptions
.
__file
);
return
appOptions
}
function
createApp
(
vm
)
{
App
(
parseApp$1
(
vm
));
return
vm
}
function
parseBaseComponent
(
vueComponentOptions
,
{
isPage
:
isPage$$1
,
initRelation
:
initRelation$$1
}
=
{})
{
let
[
VueComponent
,
vueOptions
]
=
initVueComponent
(
Vue
,
vueComponentOptions
);
const
componentOptions
=
{
options
:
{
multipleSlots
:
true
,
addGlobalClass
:
true
},
data
:
ge
tData
(
vueOptions
,
Vue
.
prototype
),
behaviors
,
properties
,
data
:
ini
tData
(
vueOptions
,
Vue
.
prototype
),
behaviors
:
initBehaviors
(
vueOptions
,
initBehavior
)
,
properties
:
initProperties
(
vueOptions
.
props
,
false
,
vueOptions
.
__file
)
,
lifetimes
:
{
attached
()
{
initVm$2
.
call
(
this
,
VueComponent
);
const
properties
=
this
.
properties
;
const
options
=
{
mpType
:
isPage$$1
.
call
(
this
)
?
'
page
'
:
'
component
'
,
mpInstance
:
this
,
propsData
:
properties
};
initVueIds
(
properties
.
vueId
,
this
);
// 处理父子关系
initRelation$$1
.
call
(
this
,
{
vuePid
:
this
.
_$vuePid
,
vueOptions
:
options
});
// 初始化 vue 实例
this
.
$vm
=
new
VueComponent
(
options
);
// 处理$slots,$scopedSlots(暂不支持动态变化$slots)
initSlots
(
this
.
$vm
,
properties
.
vueSlots
);
// 触发首次 setData
this
.
$vm
.
$mount
();
},
ready
()
{
initVm$2
.
call
(
this
,
VueComponent
);
// 目前发现部分情况小程序 attached 不触发
triggerLink
(
this
);
// 处理 parent,children
// 补充生命周期
this
.
$vm
.
__call_hook
(
'
created
'
);
this
.
$vm
.
__call_hook
(
'
beforeMount
'
);
// 当组件 props 默认值为 true,初始化时传入 false 会导致 created,ready 触发, 但 attached 不触发
// https://developers.weixin.qq.com/community/develop/doc/00066ae2844cc0f8eb883e2a557800
if
(
this
.
$vm
)
{
this
.
$vm
.
_isMounted
=
true
;
this
.
$vm
.
__call_hook
(
'
mounted
'
);
this
.
$vm
.
__call_hook
(
'
onReady
'
);
}
else
{
this
.
is
&&
console
.
warn
(
this
.
is
+
'
is not attached
'
);
}
},
detached
()
{
this
.
$vm
.
$destroy
();
...
...
@@ -1022,7 +1001,7 @@ function createComponent (vueOptions) {
},
pageLifetimes
:
{
show
(
args
)
{
this
.
$vm
.
__call_hook
(
'
onPageShow
'
,
args
);
this
.
$vm
&&
this
.
$vm
.
__call_hook
(
'
onPageShow
'
,
args
);
},
hide
()
{
this
.
$vm
&&
this
.
$vm
.
__call_hook
(
'
onPageHide
'
);
...
...
@@ -1032,12 +1011,93 @@ function createComponent (vueOptions) {
}
},
methods
:
{
__
e
:
handleEvent
,
__
l
:
handleLink
__
l
:
handleLink
,
__
e
:
handleEvent
}
};
return
initComponent$1
(
componentOptions
,
vueOptions
)
if
(
isPage$$1
)
{
return
componentOptions
}
return
[
componentOptions
,
VueComponent
]
}
function
parseComponent
(
vueComponentOptions
)
{
return
parseBaseComponent
(
vueComponentOptions
,
{
isPage
,
initRelation
})
}
function
parseComponent$1
(
vueComponentOptions
)
{
const
componentOptions
=
parseComponent
(
vueComponentOptions
);
componentOptions
.
methods
.
$getAppWebview
=
function
()
{
return
plus
.
webview
.
getWebviewById
(
`
${
this
.
__wxWebviewId__
}
`
)
};
return
componentOptions
}
const
hooks$2
=
[
'
onShow
'
,
'
onHide
'
,
'
onUnload
'
];
hooks$2
.
push
(...
PAGE_EVENT_HOOKS
);
function
parseBasePage
(
vuePageOptions
,
{
isPage
,
initRelation
})
{
const
pageOptions
=
parseComponent$1
(
vuePageOptions
,
{
isPage
,
initRelation
});
initHooks
(
pageOptions
.
methods
,
hooks$2
);
pageOptions
.
methods
.
onLoad
=
function
(
args
)
{
this
.
$vm
.
$mp
.
query
=
args
;
// 兼容 mpvue
this
.
$vm
.
__call_hook
(
'
onLoad
'
,
args
);
};
return
pageOptions
}
function
parsePage
(
vuePageOptions
)
{
return
parseBasePage
(
vuePageOptions
,
{
isPage
,
initRelation
})
}
const
hooks$3
=
[
'
onBackPress
'
,
'
onNavigationBarButtonTap
'
,
'
onNavigationBarSearchInputChanged
'
,
'
onNavigationBarSearchInputConfirmed
'
,
'
onNavigationBarSearchInputClicked
'
];
function
parsePage$1
(
vuePageOptions
)
{
const
pageOptions
=
parsePage
(
vuePageOptions
);
initHooks
(
pageOptions
.
methods
,
hooks$3
);
return
pageOptions
}
function
createPage
(
vuePageOptions
)
{
{
return
Component
(
parsePage$1
(
vuePageOptions
))
}
}
function
createComponent
(
vueOptions
)
{
{
return
Component
(
parseComponent$1
(
vueOptions
))
}
}
todos
.
forEach
(
todoApi
=>
{
...
...
packages/uni-mp-alipay/dist/index.js
浏览文件 @
5bef921d
此差异已折叠。
点击以展开。
packages/uni-mp-baidu/dist/index.js
浏览文件 @
5bef921d
...
...
@@ -89,6 +89,7 @@ function promisify (name, api) {
fail
:
reject
}),
...
params
);
/* eslint-disable no-extend-native */
if
(
!
Promise
.
prototype
.
finally
)
{
Promise
.
prototype
.
finally
=
function
(
callback
)
{
const
promise
=
this
.
constructor
;
return
this
.
then
(
...
...
@@ -98,6 +99,7 @@ function promisify (name, api) {
})
)
};
}
}))
}
}
...
...
@@ -469,64 +471,14 @@ Component = function (options = {}) {
return
MPComponent
(
options
)
};
function
initBehavior
(
options
)
{
return
Behavior
(
options
)
}
function
initRefs
(
vm
)
{
const
mpInstance
=
vm
.
$scope
;
Object
.
defineProperty
(
vm
,
'
$refs
'
,
{
get
()
{
const
$refs
=
{};
const
components
=
mpInstance
.
selectAllComponents
(
'
.vue-ref
'
);
components
.
forEach
(
component
=>
{
const
ref
=
component
.
dataset
.
ref
;
$refs
[
ref
]
=
component
.
$vm
||
component
;
});
const
forComponents
=
mpInstance
.
selectAllComponents
(
'
.vue-ref-in-for
'
);
forComponents
.
forEach
(
component
=>
{
const
ref
=
component
.
dataset
.
ref
;
if
(
!
$refs
[
ref
])
{
$refs
[
ref
]
=
[];
}
$refs
[
ref
].
push
(
component
.
$vm
||
component
);
});
return
$refs
}
});
}
const
mocks$1
=
[
'
nodeId
'
];
function
initPage$1
(
pageOptions
)
{
return
initComponent$1
(
pageOptions
)
}
function
initComponent$1
(
componentOptions
)
{
componentOptions
.
messages
=
{
'
__l
'
:
handleLink$1
};
return
Component
(
componentOptions
)
}
function
triggerLink$1
(
mpInstance
,
vueOptions
)
{
mpInstance
.
dispatch
(
'
__l
'
,
mpInstance
.
$vm
||
vueOptions
);
}
function
handleLink$1
(
event
)
{
const
target
=
event
.
value
;
if
(
target
.
$mp
)
{
if
(
!
target
.
$parent
)
{
target
.
$parent
=
this
.
$vm
;
target
.
$parent
.
$children
.
push
(
target
);
target
.
$root
=
this
.
$vm
.
$root
;
}
}
else
{
if
(
!
target
.
parent
)
{
target
.
parent
=
this
.
$vm
;
}
}
}
const
PAGE_EVENT_HOOKS
=
[
'
onPullDownRefresh
'
,
'
onReachBottom
'
,
'
onShareAppMessage
'
,
'
onPageScroll
'
,
'
onResize
'
,
'
onTabItemTap
'
];
function
initMocks
(
vm
,
mocks
)
{
const
mpInstance
=
vm
.
$mp
[
vm
.
mpType
];
...
...
@@ -540,12 +492,46 @@ function initMocks (vm, mocks) {
function
initHooks
(
mpOptions
,
hooks
)
{
hooks
.
forEach
(
hook
=>
{
mpOptions
[
hook
]
=
function
(
args
)
{
return
this
.
$vm
.
__call_hook
(
hook
,
args
)
return
this
.
$vm
&&
this
.
$vm
.
__call_hook
(
hook
,
args
)
};
});
}
function
getData
(
vueOptions
,
context
)
{
function
initVueComponent
(
Vue$$1
,
vueOptions
)
{
vueOptions
=
vueOptions
.
default
||
vueOptions
;
let
VueComponent
;
if
(
isFn
(
vueOptions
))
{
VueComponent
=
vueOptions
;
vueOptions
=
VueComponent
.
extendOptions
;
}
else
{
VueComponent
=
Vue$$1
.
extend
(
vueOptions
);
}
return
[
VueComponent
,
vueOptions
]
}
function
initSlots
(
vm
,
vueSlots
)
{
if
(
Array
.
isArray
(
vueSlots
)
&&
vueSlots
.
length
)
{
const
$slots
=
Object
.
create
(
null
);
vueSlots
.
forEach
(
slotName
=>
{
$slots
[
slotName
]
=
true
;
});
vm
.
$scopedSlots
=
vm
.
$slots
=
$slots
;
}
}
function
initVueIds
(
vueIds
,
mpInstance
)
{
vueIds
=
(
vueIds
||
''
).
split
(
'
,
'
);
const
len
=
vueIds
.
length
;
if
(
len
===
1
)
{
mpInstance
.
_$vueId
=
vueIds
[
0
];
}
else
if
(
len
===
2
)
{
mpInstance
.
_$vueId
=
vueIds
[
0
];
mpInstance
.
_$vuePid
=
vueIds
[
1
];
}
}
function
initData
(
vueOptions
,
context
)
{
let
data
=
vueOptions
.
data
||
{};
const
methods
=
vueOptions
.
methods
||
{};
...
...
@@ -587,7 +573,7 @@ function createObserver (name) {
}
}
function
getBehaviors
(
vueOptions
)
{
function
initBehaviors
(
vueOptions
,
initBehavior
)
{
const
vueBehaviors
=
vueOptions
[
'
behaviors
'
];
const
vueExtends
=
vueOptions
[
'
extends
'
];
const
vueMixins
=
vueOptions
[
'
mixins
'
];
...
...
@@ -616,7 +602,7 @@ function getBehaviors (vueOptions) {
if
(
isPlainObject
(
vueExtends
)
&&
vueExtends
.
props
)
{
behaviors
.
push
(
initBehavior
({
properties
:
ge
tProperties
(
vueExtends
.
props
,
true
)
properties
:
ini
tProperties
(
vueExtends
.
props
,
true
)
})
);
}
...
...
@@ -625,7 +611,7 @@ function getBehaviors (vueOptions) {
if
(
isPlainObject
(
vueMixin
)
&&
vueMixin
.
props
)
{
behaviors
.
push
(
initBehavior
({
properties
:
ge
tProperties
(
vueMixin
.
props
,
true
)
properties
:
ini
tProperties
(
vueMixin
.
props
,
true
)
})
);
}
...
...
@@ -658,9 +644,13 @@ function parsePropType (key, type, defaultValue, file) {
return
type
}
function
ge
tProperties
(
props
,
isBehavior
=
false
,
file
=
''
)
{
function
ini
tProperties
(
props
,
isBehavior
=
false
,
file
=
''
)
{
const
properties
=
{};
if
(
!
isBehavior
)
{
properties
.
vueId
=
{
type
:
String
,
value
:
''
};
properties
.
vueSlots
=
{
// 小程序不能直接定义 $slots 的 props,所以通过 vueSlots 转换到 $slots
type
:
null
,
value
:
[],
...
...
@@ -918,40 +908,17 @@ function handleEvent (event) {
});
}
function
baiduComponentDestroy
(
$vm
)
{
$vm
.
$children
.
forEach
(
childVm
=>
{
childVm
.
$mp
.
component
.
detached
();
});
$vm
.
$mp
.
component
.
detached
();
}
function
baiduPageDestroy
(
$vm
)
{
$vm
.
$destroy
();
$vm
.
$children
.
forEach
(
childVm
=>
{
baiduComponentDestroy
(
childVm
);
});
}
const
hooks
=
[
'
onHide
'
,
'
onError
'
,
'
onPageNotFound
'
,
'
onUniNViewMessage
'
'
onPageNotFound
'
];
function
initVm
(
vm
)
{
if
(
this
.
$vm
)
{
// 百度竟然 onShow 在 onLaunch 之前?
return
}
this
.
$vm
=
vm
;
this
.
$vm
.
$mp
=
{
app
:
this
};
}
function
createApp
(
vm
)
{
function
parseBaseApp
(
vm
,
{
mocks
,
initRefs
})
{
Vue
.
prototype
.
mpHost
=
"
mp-baidu
"
;
Vue
.
mixin
({
beforeCreate
()
{
...
...
@@ -973,195 +940,172 @@ function createApp (vm) {
if
(
this
.
mpType
!==
'
app
'
)
{
initRefs
(
this
);
initMocks
(
this
,
mocks
$1
);
initMocks
(
this
,
mocks
);
}
},
created
()
{
// 处理 injections
this
.
__init_injections
(
this
);
this
.
__init_provide
(
this
);
}
});
const
appOptions
=
{
onLaunch
(
args
)
{
initVm
.
call
(
this
,
vm
);
this
.
$vm
=
vm
;
this
.
$vm
.
$mp
=
{
app
:
this
};
this
.
$vm
.
$scope
=
this
;
this
.
$vm
.
_isMounted
=
true
;
this
.
$vm
.
__call_hook
(
'
mounted
'
);
this
.
$vm
.
__call_hook
(
'
mounted
'
,
args
);
this
.
$vm
.
__call_hook
(
'
onLaunch
'
,
args
);
},
onShow
(
args
)
{
initVm
.
call
(
this
,
vm
);
this
.
$vm
.
__call_hook
(
'
onShow
'
,
args
);
}
};
// 兼容旧版本 globalData
appOptions
.
globalData
=
vm
.
$options
.
globalData
||
{};
initHooks
(
appOptions
,
hooks
);
// 延迟执行,因为 App 的注册在 main.js 之前,可能导致生命周期内 Vue 原型上开发者注册的属性无法访问
App
(
appOptions
);
initHooks
(
appOptions
,
hooks
);
return
vm
return
appOptions
}
const
hooks$1
=
[
'
onShow
'
,
'
onHide
'
,
'
onPullDownRefresh
'
,
'
onReachBottom
'
,
'
onShareAppMessage
'
,
'
onPageScroll
'
,
'
onResize
'
,
'
onTabItemTap
'
,
'
onBackPress
'
,
'
onNavigationBarButtonTap
'
,
'
onNavigationBarSearchInputChanged
'
,
'
onNavigationBarSearchInputConfirmed
'
,
'
onNavigationBarSearchInputClicked
'
];
function
initVm$1
(
VueComponent
)
{
// 百度的 onLoad 触发在 attached 之前
if
(
this
.
$vm
)
{
return
function
findVmByVueId
(
vm
,
vuePid
)
{
const
$children
=
vm
.
$children
;
// 优先查找直属
let
parentVm
=
$children
.
find
(
childVm
=>
childVm
.
$scope
.
_$vueId
===
vuePid
);
if
(
parentVm
)
{
return
parentVm
}
// 反向递归查找
for
(
let
i
=
$children
.
length
-
1
;
i
>=
0
;
i
--
)
{
parentVm
=
findVmByVueId
(
$children
[
i
],
vuePid
);
if
(
parentVm
)
{
return
parentVm
}
this
.
$vm
=
new
VueComponent
({
mpType
:
'
page
'
,
mpInstance
:
this
});
{
this
.
$vm
.
$baiduComponentInstances
=
Object
.
create
(
null
);
}
}
this
.
$vm
.
__call_hook
(
'
created
'
);
this
.
$vm
.
$mount
();
function
initBehavior
(
options
)
{
return
Behavior
(
options
)
}
function
createPage
(
vueOptions
)
{
vueOptions
=
vueOptions
.
default
||
vueOptions
;
let
VueComponent
;
if
(
isFn
(
vueOptions
))
{
VueComponent
=
vueOptions
;
vueOptions
=
VueComponent
.
extendOptions
;
}
else
{
VueComponent
=
Vue
.
extend
(
vueOptions
);
}
const
pageOptions
=
{
options
:
{
multipleSlots
:
true
,
addGlobalClass
:
true
},
data
:
getData
(
vueOptions
,
Vue
.
prototype
),
lifetimes
:
{
// 当页面作为组件时
attached
()
{
initVm$1
.
call
(
this
,
VueComponent
);
},
ready
()
{
this
.
$vm
.
__call_hook
(
'
beforeMount
'
);
this
.
$vm
.
_isMounted
=
true
;
this
.
$vm
.
__call_hook
(
'
mounted
'
);
this
.
$vm
.
__call_hook
(
'
onReady
'
);
},
detached
()
{
this
.
$vm
.
$destroy
();
}
},
methods
:
{
// 作为页面时
onLoad
(
args
)
{
initVm$1
.
call
(
this
,
VueComponent
);
{
// 百度当组件作为页面时 pageinstancce 不是原来组件的 instance
this
.
pageinstance
.
$vm
=
this
.
$vm
;
}
this
.
$vm
.
$mp
.
query
=
args
;
// 又要兼容 mpvue
this
.
$vm
.
__call_hook
(
'
onLoad
'
,
args
);
// 开发者可能会在 onLoad 时赋值,提前到 mount 之前
},
onUnload
()
{
this
.
$vm
.
__call_hook
(
'
onUnload
'
);
{
// 百度组件不会在页面 unload 时触发 detached
baiduPageDestroy
(
this
.
$vm
);
function
initRefs
(
vm
)
{
const
mpInstance
=
vm
.
$scope
;
Object
.
defineProperty
(
vm
,
'
$refs
'
,
{
get
()
{
const
$refs
=
{};
const
components
=
mpInstance
.
selectAllComponents
(
'
.vue-ref
'
);
components
.
forEach
(
component
=>
{
const
ref
=
component
.
dataset
.
ref
;
$refs
[
ref
]
=
component
.
$vm
||
component
;
});
const
forComponents
=
mpInstance
.
selectAllComponents
(
'
.vue-ref-in-for
'
);
forComponents
.
forEach
(
component
=>
{
const
ref
=
component
.
dataset
.
ref
;
if
(
!
$refs
[
ref
])
{
$refs
[
ref
]
=
[];
}
},
__e
:
handleEvent
,
__l
:
handleLink$1
$refs
[
ref
].
push
(
component
.
$vm
||
component
);
});
return
$refs
}
};
});
}
initHooks
(
pageOptions
.
methods
,
hooks$1
);
function
handleLink
(
event
)
{
const
{
vuePid
,
vueOptions
}
=
event
.
detail
||
event
.
value
;
// detail 是微信,value 是百度(dipatch)
return
initPage$1
(
pageOptions
,
vueOptions
)
}
let
parentVm
;
function
initVm$2
(
VueComponent
)
{
if
(
this
.
$vm
)
{
return
if
(
vuePid
)
{
parentVm
=
findVmByVueId
(
this
.
$vm
,
vuePid
);
}
const
properties
=
this
.
properties
;
if
(
!
parentVm
)
{
parentVm
=
this
.
$vm
;
}
const
options
=
{
mpType
:
'
component
'
,
mpInstance
:
this
,
propsData
:
properties
};
// 初始化 vue 实例
this
.
$vm
=
new
VueComponent
(
options
);
vueOptions
.
parent
=
parentVm
;
}
// 处理$slots,$scopedSlots(暂不支持动态变化$slots)
const
vueSlots
=
properties
.
vueSlots
;
if
(
Array
.
isArray
(
vueSlots
)
&&
vueSlots
.
length
)
{
const
$slots
=
Object
.
create
(
null
);
vueSlots
.
forEach
(
slotName
=>
{
$slots
[
slotName
]
=
true
;
});
this
.
$vm
.
$scopedSlots
=
this
.
$vm
.
$slots
=
$slots
;
}
// 性能优先,mount 提前到 attached 中,保证组件首次渲染数据被合并
// 导致与标准 Vue 的差异,data 和 computed 中不能使用$parent,provide等组件属性
this
.
$vm
.
$mount
();
const
mocks$1
=
[
'
nodeId
'
];
function
isPage$1
()
{
return
!
this
.
ownerId
}
function
createComponent
(
vueOptions
)
{
vueOptions
=
vueOptions
.
default
||
vueOptions
;
function
initRelation$1
(
detail
)
{
this
.
dispatch
(
'
__l
'
,
detail
);
}
let
VueComponent
;
if
(
isFn
(
vueOptions
))
{
VueComponent
=
vueOptions
;
// TODO form-field props.name,props.value
vueOptions
=
VueComponent
.
extendOptions
;
}
else
{
VueComponent
=
Vue
.
extend
(
vueOptions
);
}
function
parseApp
(
vm
)
{
return
parseBaseApp
(
vm
,
{
mocks
:
mocks$1
,
initRefs
})
}
const
behaviors
=
getBehaviors
(
vueOptions
);
function
createApp
(
vm
)
{
App
(
parseApp
(
vm
));
return
vm
}
const
properties
=
getProperties
(
vueOptions
.
props
,
false
,
vueOptions
.
__file
);
function
parseBaseComponent
(
vueComponentOptions
,
{
isPage
:
isPage$$1
,
initRelation
:
initRelation$$1
}
=
{})
{
let
[
VueComponent
,
vueOptions
]
=
initVueComponent
(
Vue
,
vueComponentOptions
);
const
componentOptions
=
{
options
:
{
multipleSlots
:
true
,
addGlobalClass
:
true
},
data
:
ge
tData
(
vueOptions
,
Vue
.
prototype
),
behaviors
,
properties
,
data
:
ini
tData
(
vueOptions
,
Vue
.
prototype
),
behaviors
:
initBehaviors
(
vueOptions
,
initBehavior
)
,
properties
:
initProperties
(
vueOptions
.
props
,
false
,
vueOptions
.
__file
)
,
lifetimes
:
{
attached
()
{
initVm$2
.
call
(
this
,
VueComponent
);
const
properties
=
this
.
properties
;
const
options
=
{
mpType
:
isPage$$1
.
call
(
this
)
?
'
page
'
:
'
component
'
,
mpInstance
:
this
,
propsData
:
properties
};
initVueIds
(
properties
.
vueId
,
this
);
// 处理父子关系
initRelation$$1
.
call
(
this
,
{
vuePid
:
this
.
_$vuePid
,
vueOptions
:
options
});
// 初始化 vue 实例
this
.
$vm
=
new
VueComponent
(
options
);
// 处理$slots,$scopedSlots(暂不支持动态变化$slots)
initSlots
(
this
.
$vm
,
properties
.
vueSlots
);
// 触发首次 setData
this
.
$vm
.
$mount
();
},
ready
()
{
initVm$2
.
call
(
this
,
VueComponent
);
// 目前发现部分情况小程序 attached 不触发
triggerLink$1
(
this
);
// 处理 parent,children
// 补充生命周期
this
.
$vm
.
__call_hook
(
'
created
'
);
this
.
$vm
.
__call_hook
(
'
beforeMount
'
);
// 当组件 props 默认值为 true,初始化时传入 false 会导致 created,ready 触发, 但 attached 不触发
// https://developers.weixin.qq.com/community/develop/doc/00066ae2844cc0f8eb883e2a557800
if
(
this
.
$vm
)
{
this
.
$vm
.
_isMounted
=
true
;
this
.
$vm
.
__call_hook
(
'
mounted
'
);
this
.
$vm
.
__call_hook
(
'
onReady
'
);
}
else
{
this
.
is
&&
console
.
warn
(
this
.
is
+
'
is not attached
'
);
}
},
detached
()
{
this
.
$vm
.
$destroy
();
...
...
@@ -1169,7 +1113,7 @@ function createComponent (vueOptions) {
},
pageLifetimes
:
{
show
(
args
)
{
this
.
$vm
.
__call_hook
(
'
onPageShow
'
,
args
);
this
.
$vm
&&
this
.
$vm
.
__call_hook
(
'
onPageShow
'
,
args
);
},
hide
()
{
this
.
$vm
&&
this
.
$vm
.
__call_hook
(
'
onPageHide
'
);
...
...
@@ -1179,12 +1123,114 @@ function createComponent (vueOptions) {
}
},
methods
:
{
__e
:
handleEvent
,
__l
:
handleLink$1
__l
:
handleLink
,
__e
:
handleEvent
}
};
if
(
isPage$$1
)
{
return
componentOptions
}
return
[
componentOptions
,
VueComponent
]
}
function
parseComponent
(
vueOptions
)
{
const
componentOptions
=
parseBaseComponent
(
vueOptions
,
{
isPage
:
isPage$1
,
initRelation
:
initRelation$1
});
const
oldAttached
=
componentOptions
.
lifetimes
.
attached
;
componentOptions
.
lifetimes
.
attached
=
function
attached
()
{
oldAttached
.
call
(
this
);
if
(
isPage$1
.
call
(
this
))
{
// 百度 onLoad 在 attached 之前触发
// 百度 当组件作为页面时 pageinstancce 不是原来组件的 instance
this
.
pageinstance
.
$vm
=
this
.
$vm
;
this
.
$vm
.
$mp
.
query
=
this
.
pageinstance
.
_$args
;
// 兼容 mpvue
this
.
$vm
.
__call_hook
(
'
onLoad
'
,
this
.
pageinstance
.
_$args
);
}
};
componentOptions
.
messages
=
{
'
__l
'
:
componentOptions
.
methods
[
'
__l
'
]
};
delete
componentOptions
.
methods
[
'
__l
'
];
return
componentOptions
}
const
hooks$1
=
[
'
onShow
'
,
'
onHide
'
,
'
onUnload
'
];
return
initComponent$1
(
componentOptions
,
vueOptions
)
hooks$1
.
push
(...
PAGE_EVENT_HOOKS
);
function
parseBasePage
(
vuePageOptions
,
{
isPage
,
initRelation
})
{
const
pageOptions
=
parseComponent
(
vuePageOptions
,
{
isPage
,
initRelation
});
initHooks
(
pageOptions
.
methods
,
hooks$1
);
pageOptions
.
methods
.
onLoad
=
function
(
args
)
{
this
.
$vm
.
$mp
.
query
=
args
;
// 兼容 mpvue
this
.
$vm
.
__call_hook
(
'
onLoad
'
,
args
);
};
return
pageOptions
}
function
detached
(
$vm
)
{
$vm
.
$children
.
forEach
(
childVm
=>
{
childVm
.
$scope
.
detached
();
});
$vm
.
$scope
.
detached
();
}
function
onPageUnload
(
$vm
)
{
$vm
.
$destroy
();
$vm
.
$children
.
forEach
(
childVm
=>
{
detached
(
childVm
);
});
}
function
parsePage
(
vuePageOptions
)
{
const
pageOptions
=
parseBasePage
(
vuePageOptions
,
{
isPage
:
isPage$1
,
initRelation
:
initRelation$1
});
pageOptions
.
methods
.
onLoad
=
function
onLoad
(
args
)
{
// 百度 onLoad 在 attached 之前触发,先存储 args, 在 attached 里边触发 onLoad
this
.
pageinstance
.
_$args
=
args
;
};
pageOptions
.
methods
.
onUnload
=
function
onUnload
()
{
this
.
$vm
.
__call_hook
(
'
onUnload
'
);
onPageUnload
(
this
.
$vm
);
};
return
pageOptions
}
function
createPage
(
vuePageOptions
)
{
{
return
Component
(
parsePage
(
vuePageOptions
))
}
}
function
createComponent
(
vueOptions
)
{
{
return
Component
(
parseComponent
(
vueOptions
))
}
}
todos
.
forEach
(
todoApi
=>
{
...
...
packages/uni-mp-toutiao/dist/index.js
浏览文件 @
5bef921d
...
...
@@ -89,6 +89,7 @@ function promisify (name, api) {
fail
:
reject
}),
...
params
);
/* eslint-disable no-extend-native */
if
(
!
Promise
.
prototype
.
finally
)
{
Promise
.
prototype
.
finally
=
function
(
callback
)
{
const
promise
=
this
.
constructor
;
return
this
.
then
(
...
...
@@ -98,6 +99,7 @@ function promisify (name, api) {
})
)
};
}
}))
}
}
...
...
@@ -514,76 +516,14 @@ Component = function (options = {}) {
return
MPComponent
(
options
)
};
function
initBehavior
(
options
)
{
return
Behavior
(
options
)
}
const
instances
=
Object
.
create
(
null
);
const
mocks$1
=
[
'
__route__
'
,
'
__webviewId__
'
,
'
__nodeid__
'
];
function
initPage$1
(
pageOptions
)
{
return
initComponent$1
(
pageOptions
)
}
function
initComponent$1
(
componentOptions
)
{
if
(
componentOptions
.
properties
)
{
// ref
componentOptions
.
properties
.
vueRef
=
{
type
:
String
,
value
:
''
};
}
return
Component
(
componentOptions
)
}
function
initRefs$1
(
vm
)
{
const
mpInstance
=
vm
.
$scope
;
mpInstance
.
selectAllComponents
(
'
.vue-ref
'
,
(
components
)
=>
{
components
.
forEach
(
component
=>
{
const
ref
=
component
.
data
.
vueRef
;
// 头条的组件 dataset 竟然是空的
vm
.
$refs
[
ref
]
=
component
.
$vm
||
component
;
});
});
mpInstance
.
selectAllComponents
(
'
.vue-ref-in-for
'
,
(
forComponents
)
=>
{
forComponents
.
forEach
(
component
=>
{
const
ref
=
component
.
data
.
vueRef
;
if
(
!
vm
.
$refs
[
ref
])
{
vm
.
$refs
[
ref
]
=
[];
}
vm
.
$refs
[
ref
].
push
(
component
.
$vm
||
component
);
});
});
}
function
triggerLink$1
(
mpInstance
)
{
const
nodeId
=
mpInstance
.
__nodeid__
+
''
;
const
webviewId
=
mpInstance
.
__webviewId__
+
''
;
instances
[
webviewId
+
'
_
'
+
nodeId
]
=
mpInstance
.
$vm
;
mpInstance
.
triggerEvent
(
'
__l
'
,
{
nodeId
,
webviewId
},
{
bubbles
:
true
,
composed
:
true
});
}
// TODO 目前有 bug,composed 不生效
function
handleLink$1
(
event
)
{
const
nodeId
=
event
.
detail
.
nodeId
;
const
webviewId
=
event
.
detail
.
webviewId
;
const
childVm
=
instances
[
webviewId
+
'
_
'
+
nodeId
];
if
(
childVm
)
{
childVm
.
$parent
=
this
.
$vm
;
childVm
.
$parent
.
$children
.
push
(
event
.
detail
);
childVm
.
$root
=
this
.
$vm
.
$root
;
delete
instances
[
webviewId
+
'
_
'
+
nodeId
];
}
}
const
PAGE_EVENT_HOOKS
=
[
'
onPullDownRefresh
'
,
'
onReachBottom
'
,
'
onShareAppMessage
'
,
'
onPageScroll
'
,
'
onResize
'
,
'
onTabItemTap
'
];
function
initMocks
(
vm
,
mocks
)
{
const
mpInstance
=
vm
.
$mp
[
vm
.
mpType
];
...
...
@@ -597,12 +537,46 @@ function initMocks (vm, mocks) {
function
initHooks
(
mpOptions
,
hooks
)
{
hooks
.
forEach
(
hook
=>
{
mpOptions
[
hook
]
=
function
(
args
)
{
return
this
.
$vm
.
__call_hook
(
hook
,
args
)
return
this
.
$vm
&&
this
.
$vm
.
__call_hook
(
hook
,
args
)
};
});
}
function
getData
(
vueOptions
,
context
)
{
function
initVueComponent
(
Vue$$1
,
vueOptions
)
{
vueOptions
=
vueOptions
.
default
||
vueOptions
;
let
VueComponent
;
if
(
isFn
(
vueOptions
))
{
VueComponent
=
vueOptions
;
vueOptions
=
VueComponent
.
extendOptions
;
}
else
{
VueComponent
=
Vue$$1
.
extend
(
vueOptions
);
}
return
[
VueComponent
,
vueOptions
]
}
function
initSlots
(
vm
,
vueSlots
)
{
if
(
Array
.
isArray
(
vueSlots
)
&&
vueSlots
.
length
)
{
const
$slots
=
Object
.
create
(
null
);
vueSlots
.
forEach
(
slotName
=>
{
$slots
[
slotName
]
=
true
;
});
vm
.
$scopedSlots
=
vm
.
$slots
=
$slots
;
}
}
function
initVueIds
(
vueIds
,
mpInstance
)
{
vueIds
=
(
vueIds
||
''
).
split
(
'
,
'
);
const
len
=
vueIds
.
length
;
if
(
len
===
1
)
{
mpInstance
.
_$vueId
=
vueIds
[
0
];
}
else
if
(
len
===
2
)
{
mpInstance
.
_$vueId
=
vueIds
[
0
];
mpInstance
.
_$vuePid
=
vueIds
[
1
];
}
}
function
initData
(
vueOptions
,
context
)
{
let
data
=
vueOptions
.
data
||
{};
const
methods
=
vueOptions
.
methods
||
{};
...
...
@@ -644,7 +618,7 @@ function createObserver (name) {
}
}
function
getBehaviors
(
vueOptions
)
{
function
initBehaviors
(
vueOptions
,
initBehavior
)
{
const
vueBehaviors
=
vueOptions
[
'
behaviors
'
];
const
vueExtends
=
vueOptions
[
'
extends
'
];
const
vueMixins
=
vueOptions
[
'
mixins
'
];
...
...
@@ -673,7 +647,7 @@ function getBehaviors (vueOptions) {
if
(
isPlainObject
(
vueExtends
)
&&
vueExtends
.
props
)
{
behaviors
.
push
(
initBehavior
({
properties
:
ge
tProperties
(
vueExtends
.
props
,
true
)
properties
:
ini
tProperties
(
vueExtends
.
props
,
true
)
})
);
}
...
...
@@ -682,7 +656,7 @@ function getBehaviors (vueOptions) {
if
(
isPlainObject
(
vueMixin
)
&&
vueMixin
.
props
)
{
behaviors
.
push
(
initBehavior
({
properties
:
ge
tProperties
(
vueMixin
.
props
,
true
)
properties
:
ini
tProperties
(
vueMixin
.
props
,
true
)
})
);
}
...
...
@@ -699,9 +673,13 @@ function parsePropType (key, type, defaultValue, file) {
return
type
}
function
ge
tProperties
(
props
,
isBehavior
=
false
,
file
=
''
)
{
function
ini
tProperties
(
props
,
isBehavior
=
false
,
file
=
''
)
{
const
properties
=
{};
if
(
!
isBehavior
)
{
properties
.
vueId
=
{
type
:
String
,
value
:
''
};
properties
.
vueSlots
=
{
// 小程序不能直接定义 $slots 的 props,所以通过 vueSlots 转换到 $slots
type
:
null
,
value
:
[],
...
...
@@ -952,23 +930,14 @@ function handleEvent (event) {
const
hooks
=
[
'
onHide
'
,
'
onError
'
,
'
onPageNotFound
'
,
'
onUniNViewMessage
'
'
onPageNotFound
'
];
function
initVm
(
vm
)
{
if
(
this
.
$vm
)
{
// 百度竟然 onShow 在 onLaunch 之前?
return
}
this
.
$vm
=
vm
;
this
.
$vm
.
$mp
=
{
app
:
this
};
}
function
createApp
(
vm
)
{
function
parseBaseApp
(
vm
,
{
mocks
,
initRefs
})
{
Vue
.
prototype
.
mpHost
=
"
mp-toutiao
"
;
Vue
.
mixin
({
beforeCreate
()
{
...
...
@@ -989,209 +958,354 @@ function createApp (vm) {
delete
this
.
$options
.
mpInstance
;
if
(
this
.
mpType
!==
'
app
'
)
{
initRefs
$1
(
this
);
initMocks
(
this
,
mocks
$1
);
initRefs
(
this
);
initMocks
(
this
,
mocks
);
}
},
created
()
{
// 处理 injections
this
.
__init_injections
(
this
);
this
.
__init_provide
(
this
);
}
});
const
appOptions
=
{
onLaunch
(
args
)
{
initVm
.
call
(
this
,
vm
);
this
.
$vm
=
vm
;
this
.
$vm
.
$mp
=
{
app
:
this
};
this
.
$vm
.
$scope
=
this
;
this
.
$vm
.
_isMounted
=
true
;
this
.
$vm
.
__call_hook
(
'
mounted
'
);
this
.
$vm
.
__call_hook
(
'
mounted
'
,
args
);
this
.
$vm
.
__call_hook
(
'
onLaunch
'
,
args
);
},
onShow
(
args
)
{
initVm
.
call
(
this
,
vm
);
this
.
$vm
.
__call_hook
(
'
onShow
'
,
args
);
}
};
// 兼容旧版本 globalData
appOptions
.
globalData
=
vm
.
$options
.
globalData
||
{};
initHooks
(
appOptions
,
hooks
);
// 延迟执行,因为 App 的注册在 main.js 之前,可能导致生命周期内 Vue 原型上开发者注册的属性无法访问
initHooks
(
appOptions
,
hooks
);
App
(
appOptions
);
return
appOptions
}
return
vm
function
findVmByVueId
(
vm
,
vuePid
)
{
const
$children
=
vm
.
$children
;
// 优先查找直属
let
parentVm
=
$children
.
find
(
childVm
=>
childVm
.
$scope
.
_$vueId
===
vuePid
);
if
(
parentVm
)
{
return
parentVm
}
// 反向递归查找
for
(
let
i
=
$children
.
length
-
1
;
i
>=
0
;
i
--
)
{
parentVm
=
findVmByVueId
(
$children
[
i
],
vuePid
);
if
(
parentVm
)
{
return
parentVm
}
}
}
const
hooks$1
=
[
'
onShow
'
,
'
onHide
'
,
'
onPullDownRefresh
'
,
'
onReachBottom
'
,
'
onShareAppMessage
'
,
'
onPageScroll
'
,
'
onResize
'
,
'
onTabItemTap
'
,
'
onBackPress
'
,
'
onNavigationBarButtonTap
'
,
'
onNavigationBarSearchInputChanged
'
,
'
onNavigationBarSearchInputConfirmed
'
,
'
onNavigationBarSearchInputClicked
'
];
function
initBehavior
(
options
)
{
return
Behavior
(
options
)
}
function
initVm$1
(
VueComponent
)
{
// 百度的 onLoad 触发在 attached 之前
if
(
this
.
$vm
)
{
return
function
handleLink
(
event
)
{
const
{
vuePid
,
vueOptions
}
=
event
.
detail
||
event
.
value
;
// detail 是微信,value 是百度(dipatch)
let
parentVm
;
if
(
vuePid
)
{
parentVm
=
findVmByVueId
(
this
.
$vm
,
vuePid
);
}
this
.
$vm
=
new
VueComponent
({
mpType
:
'
page
'
,
mpInstance
:
this
if
(
!
parentVm
)
{
parentVm
=
this
.
$vm
;
}
vueOptions
.
parent
=
parentVm
;
}
const
mocks$1
=
[
'
__route__
'
,
'
__webviewId__
'
,
'
__nodeid__
'
,
'
__nodeId__
'
];
function
isPage$1
()
{
return
this
.
__nodeid__
===
0
||
this
.
__nodeId__
===
0
}
function
initRefs$1
(
vm
)
{
const
mpInstance
=
vm
.
$scope
;
mpInstance
.
selectAllComponents
(
'
.vue-ref
'
,
(
components
)
=>
{
components
.
forEach
(
component
=>
{
const
ref
=
component
.
dataset
.
ref
;
vm
.
$refs
[
ref
]
=
component
.
$vm
||
component
;
});
});
mpInstance
.
selectAllComponents
(
'
.vue-ref-in-for
'
,
(
forComponents
)
=>
{
forComponents
.
forEach
(
component
=>
{
const
ref
=
component
.
dataset
.
ref
;
if
(
!
vm
.
$refs
[
ref
])
{
vm
.
$refs
[
ref
]
=
[];
}
vm
.
$refs
[
ref
].
push
(
component
.
$vm
||
component
);
});
});
}
this
.
$vm
.
__call_hook
(
'
created
'
);
this
.
$vm
.
$mount
();
const
instances
=
Object
.
create
(
null
);
function
initRelation$1
({
vuePid
,
mpInstance
})
{
// 头条 triggerEvent 后,接收事件时机特别晚,已经到了 ready 之后
const
nodeId
=
(
mpInstance
.
__nodeId__
||
mpInstance
.
__nodeid__
)
+
''
;
const
webviewId
=
mpInstance
.
__webviewId__
+
''
;
instances
[
webviewId
+
'
_
'
+
nodeId
]
=
mpInstance
.
$vm
;
this
.
triggerEvent
(
'
__l
'
,
{
vuePid
,
nodeId
,
webviewId
});
}
function
createPage
(
vueOptions
)
{
vueOptions
=
vueOptions
.
default
||
vueOptions
;
let
VueComponent
;
if
(
isFn
(
vueOptions
))
{
VueComponent
=
vueOptions
;
vueOptions
=
VueComponent
.
extendOptions
;
}
else
{
VueComponent
=
Vue
.
extend
(
vueOptions
);
function
handleLink$1
({
detail
:
{
vuePid
,
nodeId
,
webviewId
}
})
{
const
vm
=
instances
[
webviewId
+
'
_
'
+
nodeId
];
if
(
!
vm
)
{
return
}
const
pageOptions
=
{
let
parentVm
;
if
(
vuePid
)
{
parentVm
=
findVmByVueId
(
this
.
$vm
,
vuePid
);
}
if
(
!
parentVm
)
{
parentVm
=
this
.
$vm
;
}
vm
.
$parent
=
parentVm
;
vm
.
$root
=
parentVm
.
$root
;
parentVm
.
$children
.
push
(
vm
);
vm
.
__call_hook
(
'
created
'
);
vm
.
__call_hook
(
'
beforeMount
'
);
vm
.
_isMounted
=
true
;
vm
.
__call_hook
(
'
mounted
'
);
vm
.
__call_hook
(
'
onReady
'
);
}
function
parseApp
(
vm
)
{
Vue
.
prototype
.
_$fallback
=
true
;
// 降级(调整原 vue 的部分生命周期,如 created,beforeMount,inject,provide)
Vue
.
mixin
({
created
()
{
// 处理 injections,头条 triggerEvent 是异步,且触发时机很慢,故延迟 relation 设置
if
(
this
.
mpType
!==
'
app
'
)
{
initRefs$1
(
this
);
this
.
__init_injections
(
this
);
this
.
__init_provide
(
this
);
}
}
});
return
parseBaseApp
(
vm
,
{
mocks
:
mocks$1
,
initRefs
:
function
()
{}
// attached 时,可能查询不到
})
}
function
createApp
(
vm
)
{
App
(
parseApp
(
vm
));
return
vm
}
function
parseBaseComponent
(
vueComponentOptions
,
{
isPage
:
isPage$$1
,
initRelation
:
initRelation$$1
}
=
{})
{
let
[
VueComponent
,
vueOptions
]
=
initVueComponent
(
Vue
,
vueComponentOptions
);
const
componentOptions
=
{
options
:
{
multipleSlots
:
true
,
addGlobalClass
:
true
},
data
:
getData
(
vueOptions
,
Vue
.
prototype
),
lifetimes
:
{
// 当页面作为组件时
data
:
initData
(
vueOptions
,
Vue
.
prototype
),
behaviors
:
initBehaviors
(
vueOptions
,
initBehavior
),
properties
:
initProperties
(
vueOptions
.
props
,
false
,
vueOptions
.
__file
),
lifetimes
:
{
attached
()
{
initVm$1
.
call
(
this
,
VueComponent
);
const
properties
=
this
.
properties
;
const
options
=
{
mpType
:
isPage$$1
.
call
(
this
)
?
'
page
'
:
'
component
'
,
mpInstance
:
this
,
propsData
:
properties
};
initVueIds
(
properties
.
vueId
,
this
);
// 处理父子关系
initRelation$$1
.
call
(
this
,
{
vuePid
:
this
.
_$vuePid
,
vueOptions
:
options
});
// 初始化 vue 实例
this
.
$vm
=
new
VueComponent
(
options
);
// 处理$slots,$scopedSlots(暂不支持动态变化$slots)
initSlots
(
this
.
$vm
,
properties
.
vueSlots
);
// 触发首次 setData
this
.
$vm
.
$mount
();
},
ready
()
{
this
.
$vm
.
__call_hook
(
'
beforeMount
'
);
// 当组件 props 默认值为 true,初始化时传入 false 会导致 created,ready 触发, 但 attached 不触发
// https://developers.weixin.qq.com/community/develop/doc/00066ae2844cc0f8eb883e2a557800
if
(
this
.
$vm
)
{
this
.
$vm
.
_isMounted
=
true
;
this
.
$vm
.
__call_hook
(
'
mounted
'
);
this
.
$vm
.
__call_hook
(
'
onReady
'
);
}
else
{
this
.
is
&&
console
.
warn
(
this
.
is
+
'
is not attached
'
);
}
},
detached
()
{
this
.
$vm
.
$destroy
();
}
},
methods
:
{
// 作为页面时
onLoad
(
args
)
{
initVm$1
.
call
(
this
,
VueComponent
);
this
.
$vm
.
$mp
.
query
=
args
;
// 又要兼容 mpvue
this
.
$vm
.
__call_hook
(
'
onLoad
'
,
args
);
// 开发者可能会在 onLoad 时赋值,提前到 mount 之前
pageLifetimes
:
{
show
(
args
)
{
this
.
$vm
&&
this
.
$vm
.
__call_hook
(
'
onPageShow
'
,
args
);
},
onUnload
()
{
this
.
$vm
.
__call_hook
(
'
onUnload
'
);
hide
()
{
this
.
$vm
&&
this
.
$vm
.
__call_hook
(
'
onPageHide
'
);
},
__e
:
handleEvent
,
__l
:
handleLink$1
resize
(
size
)
{
this
.
$vm
&&
this
.
$vm
.
__call_hook
(
'
onPageResize
'
,
size
);
}
},
methods
:
{
__l
:
handleLink
,
__e
:
handleEvent
}
};
initHooks
(
pageOptions
.
methods
,
hooks$1
);
return
initPage$1
(
pageOptions
,
vueOptions
)
if
(
isPage$$1
)
{
return
componentOptions
}
return
[
componentOptions
,
VueComponent
]
}
function
initVm$2
(
VueComponent
)
{
if
(
this
.
$vm
)
{
return
}
function
parseComponent
(
vueOptions
)
{
const
[
componentOptions
,
VueComponent
]
=
parseBaseComponent
(
vueOptions
);
componentOptions
.
lifetimes
.
attached
=
function
attached
()
{
const
properties
=
this
.
properties
;
const
options
=
{
mpType
:
'
component
'
,
mpType
:
isPage$1
.
call
(
this
)
?
'
page
'
:
'
component
'
,
mpInstance
:
this
,
propsData
:
properties
};
initVueIds
(
properties
.
vueId
,
this
);
// 初始化 vue 实例
this
.
$vm
=
new
VueComponent
(
options
);
// 处理$slots,$scopedSlots(暂不支持动态变化$slots)
const
vueSlots
=
properties
.
vueSlots
;
if
(
Array
.
isArray
(
vueSlots
)
&&
vueSlots
.
length
)
{
const
$slots
=
Object
.
create
(
null
);
vueSlots
.
forEach
(
slotName
=>
{
$slots
[
slotName
]
=
true
;
initSlots
(
this
.
$vm
,
properties
.
vueSlots
);
// 处理父子关系
initRelation$1
.
call
(
this
,
{
vuePid
:
this
.
_$vuePid
,
mpInstance
:
this
});
this
.
$vm
.
$scopedSlots
=
this
.
$vm
.
$slots
=
$slots
;
}
// 性能优先,mount 提前到 attached 中,保证组件首次渲染数据被合并
// 导致与标准 Vue 的差异,data 和 computed 中不能使用$parent,provide等组件属性
// 触发首次 setData
this
.
$vm
.
$mount
();
};
// ready 比 handleLink 还早,初始化逻辑放到 handleLink 中
delete
componentOptions
.
lifetimes
.
ready
;
componentOptions
.
methods
.
__l
=
handleLink$1
;
return
componentOptions
}
function
createComponent
(
vueOptions
)
{
vueOptions
=
vueOptions
.
default
||
vueOptions
;
const
hooks$1
=
[
'
onShow
'
,
'
onHide
'
,
'
onUnload
'
];
let
VueComponent
;
if
(
isFn
(
vueOptions
))
{
VueComponent
=
vueOptions
;
// TODO form-field props.name,props.value
vueOptions
=
VueComponent
.
extendOptions
;
}
else
{
VueComponent
=
Vue
.
extend
(
vueOptions
);
}
hooks$1
.
push
(...
PAGE_EVENT_HOOKS
);
const
behaviors
=
getBehaviors
(
vueOptions
);
function
parseBasePage
(
vuePageOptions
,
{
isPage
,
initRelation
})
{
const
pageOptions
=
parseComponent
(
vuePageOptions
,
{
isPage
,
initRelation
});
const
properties
=
getProperties
(
vueOptions
.
props
,
false
,
vueOptions
.
__file
);
initHooks
(
pageOptions
.
methods
,
hooks$1
);
const
componentOptions
=
{
options
:
{
multipleSlots
:
true
,
addGlobalClass
:
true
},
data
:
getData
(
vueOptions
,
Vue
.
prototype
),
behaviors
,
properties
,
lifetimes
:
{
attached
()
{
initVm$2
.
call
(
this
,
VueComponent
);
},
ready
()
{
initVm$2
.
call
(
this
,
VueComponent
);
// 目前发现部分情况小程序 attached 不触发
triggerLink$1
(
this
);
// 处理 parent,children
pageOptions
.
methods
.
onLoad
=
function
(
args
)
{
this
.
$vm
.
$mp
.
query
=
args
;
// 兼容 mpvue
this
.
$vm
.
__call_hook
(
'
onLoad
'
,
args
);
};
return
pageOptions
}
// 补充生命周期
function
parsePage
(
vuePageOptions
)
{
const
pageOptions
=
parseBasePage
(
vuePageOptions
,
{
isPage
:
isPage$1
,
initRelation
:
initRelation$1
});
// 页面需要在 ready 中触发,其他组件是在 handleLink 中触发
pageOptions
.
lifetimes
.
ready
=
function
ready
()
{
if
(
this
.
$vm
&&
this
.
$vm
.
mpType
===
'
page
'
)
{
this
.
$vm
.
__call_hook
(
'
created
'
);
this
.
$vm
.
__call_hook
(
'
beforeMount
'
);
this
.
$vm
.
_isMounted
=
true
;
this
.
$vm
.
__call_hook
(
'
mounted
'
);
this
.
$vm
.
__call_hook
(
'
onReady
'
);
},
detached
()
{
this
.
$vm
.
$destroy
();
}
},
pageLifetimes
:
{
show
(
args
)
{
this
.
$vm
.
__call_hook
(
'
onPageShow
'
,
args
);
},
hide
()
{
this
.
$vm
&&
this
.
$vm
.
__call_hook
(
'
onPageHide
'
);
},
resize
(
size
)
{
this
.
$vm
&&
this
.
$vm
.
__call_hook
(
'
onPageResize
'
,
size
);
}
},
methods
:
{
__e
:
handleEvent
,
__l
:
handleLink$1
}
else
{
this
.
is
&&
console
.
warn
(
this
.
is
+
'
is not ready
'
);
}
};
return
initComponent$1
(
componentOptions
,
vueOptions
)
return
pageOptions
}
function
createPage
(
vuePageOptions
)
{
{
return
Component
(
parsePage
(
vuePageOptions
))
}
}
function
createComponent
(
vueOptions
)
{
{
return
Component
(
parseComponent
(
vueOptions
))
}
}
todos
.
forEach
(
todoApi
=>
{
...
...
packages/uni-mp-weixin/dist/index.js
浏览文件 @
5bef921d
...
...
@@ -40,7 +40,7 @@ const camelize = cached((str) => {
return
str
.
replace
(
camelizeRE
,
(
_
,
c
)
=>
c
?
c
.
toUpperCase
()
:
''
)
});
const
SYNC_API_RE
=
/subNVue|requireNativePlugin|upx2px|hideKeyboard|canIUse|^create|Sync$|Manager$/
;
const
SYNC_API_RE
=
/subNVue|requireNativePlugin|upx2px|hideKeyboard|canIUse|^create|Sync$|Manager$
|base64ToArrayBuffer|arrayBufferToBase64
/
;
const
CONTEXT_API_RE
=
/^create|Manager$/
;
...
...
@@ -89,6 +89,7 @@ function promisify (name, api) {
fail
:
reject
}),
...
params
);
/* eslint-disable no-extend-native */
if
(
!
Promise
.
prototype
.
finally
)
{
Promise
.
prototype
.
finally
=
function
(
callback
)
{
const
promise
=
this
.
constructor
;
return
this
.
then
(
...
...
@@ -98,6 +99,7 @@ function promisify (name, api) {
})
)
};
}
}))
}
}
...
...
@@ -371,66 +373,18 @@ Component = function (options = {}) {
return
MPComponent
(
options
)
};
const
mocks
=
[
'
__route__
'
,
'
__wxExparserNodeId__
'
,
'
__wxWebviewId__
'
];
function
initPage
(
pageOptions
)
{
return
initComponent
(
pageOptions
)
}
function
initComponent
(
componentOptions
)
{
return
Component
(
componentOptions
)
}
function
initBehavior
(
options
)
{
return
Behavior
(
options
)
}
function
initRefs
(
vm
)
{
const
mpInstance
=
vm
.
$scope
;
Object
.
defineProperty
(
vm
,
'
$refs
'
,
{
get
()
{
const
$refs
=
{};
const
components
=
mpInstance
.
selectAllComponents
(
'
.vue-ref
'
);
components
.
forEach
(
component
=>
{
const
ref
=
component
.
dataset
.
ref
;
$refs
[
ref
]
=
component
.
$vm
||
component
;
});
const
forComponents
=
mpInstance
.
selectAllComponents
(
'
.vue-ref-in-for
'
);
forComponents
.
forEach
(
component
=>
{
const
ref
=
component
.
dataset
.
ref
;
if
(
!
$refs
[
ref
])
{
$refs
[
ref
]
=
[];
}
$refs
[
ref
].
push
(
component
.
$vm
||
component
);
});
return
$refs
}
});
}
function
triggerLink
(
mpInstance
,
vueOptions
)
{
mpInstance
.
triggerEvent
(
'
__l
'
,
mpInstance
.
$vm
||
vueOptions
,
{
bubbles
:
true
,
composed
:
true
});
}
function
handleLink
(
event
)
{
if
(
event
.
detail
.
$mp
)
{
// vm
if
(
!
event
.
detail
.
$parent
)
{
event
.
detail
.
$parent
=
this
.
$vm
;
event
.
detail
.
$parent
.
$children
.
push
(
event
.
detail
);
event
.
detail
.
$root
=
this
.
$vm
.
$root
;
}
}
else
{
// vueOptions
if
(
!
event
.
detail
.
parent
)
{
event
.
detail
.
parent
=
this
.
$vm
;
}
}
}
const
PAGE_EVENT_HOOKS
=
[
'
onPullDownRefresh
'
,
'
onReachBottom
'
,
'
onShareAppMessage
'
,
'
onPageScroll
'
,
'
onResize
'
,
'
onTabItemTap
'
];
function
initMocks
(
vm
,
mocks
$$1
)
{
function
initMocks
(
vm
,
mocks
)
{
const
mpInstance
=
vm
.
$mp
[
vm
.
mpType
];
mocks
$$1
.
forEach
(
mock
=>
{
mocks
.
forEach
(
mock
=>
{
if
(
hasOwn
(
mpInstance
,
mock
))
{
vm
[
mock
]
=
mpInstance
[
mock
];
}
...
...
@@ -440,12 +394,46 @@ function initMocks (vm, mocks$$1) {
function
initHooks
(
mpOptions
,
hooks
)
{
hooks
.
forEach
(
hook
=>
{
mpOptions
[
hook
]
=
function
(
args
)
{
return
this
.
$vm
.
__call_hook
(
hook
,
args
)
return
this
.
$vm
&&
this
.
$vm
.
__call_hook
(
hook
,
args
)
};
});
}
function
getData
(
vueOptions
,
context
)
{
function
initVueComponent
(
Vue$$1
,
vueOptions
)
{
vueOptions
=
vueOptions
.
default
||
vueOptions
;
let
VueComponent
;
if
(
isFn
(
vueOptions
))
{
VueComponent
=
vueOptions
;
vueOptions
=
VueComponent
.
extendOptions
;
}
else
{
VueComponent
=
Vue$$1
.
extend
(
vueOptions
);
}
return
[
VueComponent
,
vueOptions
]
}
function
initSlots
(
vm
,
vueSlots
)
{
if
(
Array
.
isArray
(
vueSlots
)
&&
vueSlots
.
length
)
{
const
$slots
=
Object
.
create
(
null
);
vueSlots
.
forEach
(
slotName
=>
{
$slots
[
slotName
]
=
true
;
});
vm
.
$scopedSlots
=
vm
.
$slots
=
$slots
;
}
}
function
initVueIds
(
vueIds
,
mpInstance
)
{
vueIds
=
(
vueIds
||
''
).
split
(
'
,
'
);
const
len
=
vueIds
.
length
;
if
(
len
===
1
)
{
mpInstance
.
_$vueId
=
vueIds
[
0
];
}
else
if
(
len
===
2
)
{
mpInstance
.
_$vueId
=
vueIds
[
0
];
mpInstance
.
_$vuePid
=
vueIds
[
1
];
}
}
function
initData
(
vueOptions
,
context
)
{
let
data
=
vueOptions
.
data
||
{};
const
methods
=
vueOptions
.
methods
||
{};
...
...
@@ -487,7 +475,7 @@ function createObserver (name) {
}
}
function
getBehaviors
(
vueOptions
)
{
function
initBehaviors
(
vueOptions
,
initBehavior
)
{
const
vueBehaviors
=
vueOptions
[
'
behaviors
'
];
const
vueExtends
=
vueOptions
[
'
extends
'
];
const
vueMixins
=
vueOptions
[
'
mixins
'
];
...
...
@@ -516,7 +504,7 @@ function getBehaviors (vueOptions) {
if
(
isPlainObject
(
vueExtends
)
&&
vueExtends
.
props
)
{
behaviors
.
push
(
initBehavior
({
properties
:
ge
tProperties
(
vueExtends
.
props
,
true
)
properties
:
ini
tProperties
(
vueExtends
.
props
,
true
)
})
);
}
...
...
@@ -525,7 +513,7 @@ function getBehaviors (vueOptions) {
if
(
isPlainObject
(
vueMixin
)
&&
vueMixin
.
props
)
{
behaviors
.
push
(
initBehavior
({
properties
:
ge
tProperties
(
vueMixin
.
props
,
true
)
properties
:
ini
tProperties
(
vueMixin
.
props
,
true
)
})
);
}
...
...
@@ -542,9 +530,13 @@ function parsePropType (key, type, defaultValue, file) {
return
type
}
function
ge
tProperties
(
props
,
isBehavior
=
false
,
file
=
''
)
{
function
ini
tProperties
(
props
,
isBehavior
=
false
,
file
=
''
)
{
const
properties
=
{};
if
(
!
isBehavior
)
{
properties
.
vueId
=
{
type
:
String
,
value
:
''
};
properties
.
vueSlots
=
{
// 小程序不能直接定义 $slots 的 props,所以通过 vueSlots 转换到 $slots
type
:
null
,
value
:
[],
...
...
@@ -795,28 +787,14 @@ function handleEvent (event) {
const
hooks
=
[
'
onHide
'
,
'
onError
'
,
'
onPageNotFound
'
,
'
onUniNViewMessage
'
'
onPageNotFound
'
];
function
initVm
(
vm
)
{
if
(
this
.
$vm
)
{
// 百度竟然 onShow 在 onLaunch 之前?
return
}
{
if
(
!
wx
.
canIUse
(
'
nextTick
'
))
{
// 事实 上2.2.3 即可,简单使用 2.3.0 的 nextTick 判断
console
.
error
(
'
当前微信基础库版本过低,请将 微信开发者工具-详情-项目设置-调试基础库版本 更换为`2.3.0`以上
'
);
}
}
this
.
$vm
=
vm
;
this
.
$vm
.
$mp
=
{
app
:
this
};
}
function
createApp
(
vm
)
{
function
parseBaseApp
(
vm
,
{
mocks
,
initRefs
})
{
Vue
.
prototype
.
mpHost
=
"
mp-weixin
"
;
Vue
.
mixin
({
beforeCreate
()
{
...
...
@@ -840,183 +818,175 @@ function createApp (vm) {
initRefs
(
this
);
initMocks
(
this
,
mocks
);
}
},
created
()
{
// 处理 injections
this
.
__init_injections
(
this
);
this
.
__init_provide
(
this
);
}
});
const
appOptions
=
{
onLaunch
(
args
)
{
initVm
.
call
(
this
,
vm
);
{
if
(
!
wx
.
canIUse
(
'
nextTick
'
))
{
// 事实 上2.2.3 即可,简单使用 2.3.0 的 nextTick 判断
console
.
error
(
'
当前微信基础库版本过低,请将 微信开发者工具-详情-项目设置-调试基础库版本 更换为`2.3.0`以上
'
);
}
}
this
.
$vm
=
vm
;
this
.
$vm
.
$mp
=
{
app
:
this
};
this
.
$vm
.
$scope
=
this
;
this
.
$vm
.
_isMounted
=
true
;
this
.
$vm
.
__call_hook
(
'
mounted
'
);
this
.
$vm
.
__call_hook
(
'
mounted
'
,
args
);
this
.
$vm
.
__call_hook
(
'
onLaunch
'
,
args
);
},
onShow
(
args
)
{
initVm
.
call
(
this
,
vm
);
this
.
$vm
.
__call_hook
(
'
onShow
'
,
args
);
}
};
// 兼容旧版本 globalData
appOptions
.
globalData
=
vm
.
$options
.
globalData
||
{};
initHooks
(
appOptions
,
hooks
);
// 延迟执行,因为 App 的注册在 main.js 之前,可能导致生命周期内 Vue 原型上开发者注册的属性无法访问
App
(
appOptions
);
initHooks
(
appOptions
,
hooks
);
return
vm
return
appOptions
}
const
hooks$1
=
[
'
onShow
'
,
'
onHide
'
,
'
onPullDownRefresh
'
,
'
onReachBottom
'
,
'
onShareAppMessage
'
,
'
onPageScroll
'
,
'
onResize
'
,
'
onTabItemTap
'
,
'
onBackPress
'
,
'
onNavigationBarButtonTap
'
,
'
onNavigationBarSearchInputChanged
'
,
'
onNavigationBarSearchInputConfirmed
'
,
'
onNavigationBarSearchInputClicked
'
];
const
mocks
=
[
'
__route__
'
,
'
__wxExparserNodeId__
'
,
'
__wxWebviewId__
'
];
function
initVm$1
(
VueComponent
)
{
// 百度的 onLoad 触发在 attached 之前
if
(
this
.
$vm
)
{
return
function
findVmByVueId
(
vm
,
vuePid
)
{
const
$children
=
vm
.
$children
;
// 优先查找直属
let
parentVm
=
$children
.
find
(
childVm
=>
childVm
.
$scope
.
_$vueId
===
vuePid
);
if
(
parentVm
)
{
return
parentVm
}
// 反向递归查找
for
(
let
i
=
$children
.
length
-
1
;
i
>=
0
;
i
--
)
{
parentVm
=
findVmByVueId
(
$children
[
i
],
vuePid
);
if
(
parentVm
)
{
return
parentVm
}
}
}
this
.
$vm
=
new
VueComponent
({
mpType
:
'
page
'
,
mpInstance
:
this
});
function
initBehavior
(
options
)
{
return
Behavior
(
options
)
}
this
.
$vm
.
__call_hook
(
'
created
'
);
this
.
$vm
.
$mount
();
function
isPage
()
{
return
!!
this
.
route
}
function
createPage
(
vueOptions
)
{
vueOptions
=
vueOptions
.
default
||
vueOptions
;
let
VueComponent
;
if
(
isFn
(
vueOptions
))
{
VueComponent
=
vueOptions
;
vueOptions
=
VueComponent
.
extendOptions
;
}
else
{
VueComponent
=
Vue
.
extend
(
vueOptions
);
}
const
pageOptions
=
{
options
:
{
multipleSlots
:
true
,
addGlobalClass
:
true
},
data
:
getData
(
vueOptions
,
Vue
.
prototype
),
lifetimes
:
{
// 当页面作为组件时
attached
()
{
initVm$1
.
call
(
this
,
VueComponent
);
},
ready
()
{
this
.
$vm
.
__call_hook
(
'
beforeMount
'
);
this
.
$vm
.
_isMounted
=
true
;
this
.
$vm
.
__call_hook
(
'
mounted
'
);
this
.
$vm
.
__call_hook
(
'
onReady
'
);
},
detached
()
{
this
.
$vm
.
$destroy
();
function
initRelation
(
detail
)
{
this
.
triggerEvent
(
'
__l
'
,
detail
);
}
function
initRefs
(
vm
)
{
const
mpInstance
=
vm
.
$scope
;
Object
.
defineProperty
(
vm
,
'
$refs
'
,
{
get
()
{
const
$refs
=
{};
const
components
=
mpInstance
.
selectAllComponents
(
'
.vue-ref
'
);
components
.
forEach
(
component
=>
{
const
ref
=
component
.
dataset
.
ref
;
$refs
[
ref
]
=
component
.
$vm
||
component
;
});
const
forComponents
=
mpInstance
.
selectAllComponents
(
'
.vue-ref-in-for
'
);
forComponents
.
forEach
(
component
=>
{
const
ref
=
component
.
dataset
.
ref
;
if
(
!
$refs
[
ref
])
{
$refs
[
ref
]
=
[];
}
},
methods
:
{
// 作为页面时
onLoad
(
args
)
{
initVm$1
.
call
(
this
,
VueComponent
);
this
.
$vm
.
$mp
.
query
=
args
;
// 又要兼容 mpvue
this
.
$vm
.
__call_hook
(
'
onLoad
'
,
args
);
// 开发者可能会在 onLoad 时赋值,提前到 mount 之前
},
onUnload
()
{
this
.
$vm
.
__call_hook
(
'
onUnload
'
);
},
__e
:
handleEvent
,
__l
:
handleLink
$refs
[
ref
].
push
(
component
.
$vm
||
component
);
});
return
$refs
}
};
initHooks
(
pageOptions
.
methods
,
hooks$1
);
return
initPage
(
pageOptions
,
vueOptions
)
});
}
function
initVm$2
(
VueComponent
)
{
if
(
this
.
$vm
)
{
return
}
function
handleLink
(
event
)
{
const
{
vuePid
,
vueOptions
}
=
event
.
detail
||
event
.
value
;
// detail 是微信,value 是百度(dipatch)
const
properties
=
this
.
properties
;
let
parentVm
;
const
options
=
{
mpType
:
'
component
'
,
mpInstance
:
this
,
propsData
:
properties
};
// 初始化 vue 实例
this
.
$vm
=
new
VueComponent
(
options
);
if
(
vuePid
)
{
parentVm
=
findVmByVueId
(
this
.
$vm
,
vuePid
);
}
// 处理$slots,$scopedSlots(暂不支持动态变化$slots)
const
vueSlots
=
properties
.
vueSlots
;
if
(
Array
.
isArray
(
vueSlots
)
&&
vueSlots
.
length
)
{
const
$slots
=
Object
.
create
(
null
);
vueSlots
.
forEach
(
slotName
=>
{
$slots
[
slotName
]
=
true
;
});
this
.
$vm
.
$scopedSlots
=
this
.
$vm
.
$slots
=
$slots
;
if
(
!
parentVm
)
{
parentVm
=
this
.
$vm
;
}
// 性能优先,mount 提前到 attached 中,保证组件首次渲染数据被合并
// 导致与标准 Vue 的差异,data 和 computed 中不能使用$parent,provide等组件属性
this
.
$vm
.
$mount
();
}
function
createComponent
(
vueOptions
)
{
vueOptions
=
vueOptions
.
default
||
vueOptions
;
vueOptions
.
parent
=
parentVm
;
}
let
VueComponent
;
if
(
isFn
(
vueOptions
))
{
VueComponent
=
vueOptions
;
// TODO form-field props.name,props.value
vueOptions
=
VueComponent
.
extendOptions
;
}
else
{
VueComponent
=
Vue
.
extend
(
vueOptions
);
}
function
parseApp
(
vm
)
{
return
parseBaseApp
(
vm
,
{
mocks
,
initRefs
})
}
const
behaviors
=
getBehaviors
(
vueOptions
);
function
createApp
(
vm
)
{
App
(
parseApp
(
vm
));
return
vm
}
const
properties
=
getProperties
(
vueOptions
.
props
,
false
,
vueOptions
.
__file
);
function
parseBaseComponent
(
vueComponentOptions
,
{
isPage
:
isPage$$1
,
initRelation
:
initRelation$$1
}
=
{})
{
let
[
VueComponent
,
vueOptions
]
=
initVueComponent
(
Vue
,
vueComponentOptions
);
const
componentOptions
=
{
options
:
{
multipleSlots
:
true
,
addGlobalClass
:
true
},
data
:
ge
tData
(
vueOptions
,
Vue
.
prototype
),
behaviors
,
properties
,
data
:
ini
tData
(
vueOptions
,
Vue
.
prototype
),
behaviors
:
initBehaviors
(
vueOptions
,
initBehavior
)
,
properties
:
initProperties
(
vueOptions
.
props
,
false
,
vueOptions
.
__file
)
,
lifetimes
:
{
attached
()
{
initVm$2
.
call
(
this
,
VueComponent
);
const
properties
=
this
.
properties
;
const
options
=
{
mpType
:
isPage$$1
.
call
(
this
)
?
'
page
'
:
'
component
'
,
mpInstance
:
this
,
propsData
:
properties
};
initVueIds
(
properties
.
vueId
,
this
);
// 处理父子关系
initRelation$$1
.
call
(
this
,
{
vuePid
:
this
.
_$vuePid
,
vueOptions
:
options
});
// 初始化 vue 实例
this
.
$vm
=
new
VueComponent
(
options
);
// 处理$slots,$scopedSlots(暂不支持动态变化$slots)
initSlots
(
this
.
$vm
,
properties
.
vueSlots
);
// 触发首次 setData
this
.
$vm
.
$mount
();
},
ready
()
{
initVm$2
.
call
(
this
,
VueComponent
);
// 目前发现部分情况小程序 attached 不触发
triggerLink
(
this
);
// 处理 parent,children
// 补充生命周期
this
.
$vm
.
__call_hook
(
'
created
'
);
this
.
$vm
.
__call_hook
(
'
beforeMount
'
);
// 当组件 props 默认值为 true,初始化时传入 false 会导致 created,ready 触发, 但 attached 不触发
// https://developers.weixin.qq.com/community/develop/doc/00066ae2844cc0f8eb883e2a557800
if
(
this
.
$vm
)
{
this
.
$vm
.
_isMounted
=
true
;
this
.
$vm
.
__call_hook
(
'
mounted
'
);
this
.
$vm
.
__call_hook
(
'
onReady
'
);
}
else
{
this
.
is
&&
console
.
warn
(
this
.
is
+
'
is not attached
'
);
}
},
detached
()
{
this
.
$vm
.
$destroy
();
...
...
@@ -1024,7 +994,7 @@ function createComponent (vueOptions) {
},
pageLifetimes
:
{
show
(
args
)
{
this
.
$vm
.
__call_hook
(
'
onPageShow
'
,
args
);
this
.
$vm
&&
this
.
$vm
.
__call_hook
(
'
onPageShow
'
,
args
);
},
hide
()
{
this
.
$vm
&&
this
.
$vm
.
__call_hook
(
'
onPageHide
'
);
...
...
@@ -1034,12 +1004,68 @@ function createComponent (vueOptions) {
}
},
methods
:
{
__e
:
handleEvent
,
__l
:
handleLink
__l
:
handleLink
,
__e
:
handleEvent
}
};
if
(
isPage$$1
)
{
return
componentOptions
}
return
[
componentOptions
,
VueComponent
]
}
function
parseComponent
(
vueComponentOptions
)
{
return
parseBaseComponent
(
vueComponentOptions
,
{
isPage
,
initRelation
})
}
const
hooks$1
=
[
'
onShow
'
,
'
onHide
'
,
'
onUnload
'
];
hooks$1
.
push
(...
PAGE_EVENT_HOOKS
);
function
parseBasePage
(
vuePageOptions
,
{
isPage
,
initRelation
})
{
const
pageOptions
=
parseComponent
(
vuePageOptions
,
{
isPage
,
initRelation
});
initHooks
(
pageOptions
.
methods
,
hooks$1
);
pageOptions
.
methods
.
onLoad
=
function
(
args
)
{
this
.
$vm
.
$mp
.
query
=
args
;
// 兼容 mpvue
this
.
$vm
.
__call_hook
(
'
onLoad
'
,
args
);
};
return
initComponent
(
componentOptions
,
vueOptions
)
return
pageOptions
}
function
parsePage
(
vuePageOptions
)
{
return
parseBasePage
(
vuePageOptions
,
{
isPage
,
initRelation
})
}
function
createPage
(
vuePageOptions
)
{
{
return
Component
(
parsePage
(
vuePageOptions
))
}
}
function
createComponent
(
vueOptions
)
{
{
return
Component
(
parseComponent
(
vueOptions
))
}
}
todos
.
forEach
(
todoApi
=>
{
...
...
src/core/runtime/wrapper/create-app.js
浏览文件 @
5bef921d
import
'
uni-platform/runtime/index
'
import
Vue
from
'
vue
'
import
{
mocks
,
initRefs
}
from
'
uni-platform/runtime/wrapper/index
'
import
{
initHooks
,
initMocks
}
from
'
./util
'
const
hooks
=
[
'
onHide
'
,
'
onError
'
,
'
onPageNotFound
'
,
'
onUniNViewMessage
'
]
function
initVm
(
vm
)
{
if
(
this
.
$vm
)
{
// 百度竟然 onShow 在 onLaunch 之前?
return
}
if
(
__PLATFORM__
===
'
mp-weixin
'
)
{
if
(
!
wx
.
canIUse
(
'
nextTick
'
))
{
// 事实 上2.2.3 即可,简单使用 2.3.0 的 nextTick 判断
console
.
error
(
'
当前微信基础库版本过低,请将 微信开发者工具-详情-项目设置-调试基础库版本 更换为`2.3.0`以上
'
)
}
}
this
.
$vm
=
vm
this
.
$vm
.
$mp
=
{
app
:
this
}
}
import
parseApp
from
'
uni-platform/runtime/wrapper/app-parser
'
export
function
createApp
(
vm
)
{
// 外部初始化时 Vue 还未初始化,放到 createApp 内部初始化 mixin
if
(
__PLATFORM__
===
'
mp-alipay
'
)
{
Object
.
defineProperty
(
Vue
.
prototype
,
'
$slots
'
,
{
get
()
{
return
this
.
$scope
&&
this
.
$scope
.
props
.
$slots
},
set
()
{
}
})
Object
.
defineProperty
(
Vue
.
prototype
,
'
$scopedSlots
'
,
{
get
()
{
return
this
.
$scope
&&
this
.
$scope
.
props
.
$scopedSlots
},
set
()
{
}
})
}
Vue
.
mixin
({
beforeCreate
()
{
if
(
!
this
.
$options
.
mpType
)
{
return
}
this
.
mpType
=
this
.
$options
.
mpType
this
.
$mp
=
{
data
:
{},
[
this
.
mpType
]:
this
.
$options
.
mpInstance
}
this
.
$scope
=
this
.
$options
.
mpInstance
delete
this
.
$options
.
mpType
delete
this
.
$options
.
mpInstance
if
(
this
.
mpType
!==
'
app
'
)
{
initRefs
(
this
)
initMocks
(
this
,
mocks
)
}
},
created
()
{
// 处理 injections
this
.
__init_injections
(
this
)
this
.
__init_provide
(
this
)
}
})
const
appOptions
=
{
onLaunch
(
args
)
{
initVm
.
call
(
this
,
vm
)
this
.
$vm
.
_isMounted
=
true
this
.
$vm
.
__call_hook
(
'
mounted
'
)
this
.
$vm
.
__call_hook
(
'
onLaunch
'
,
args
)
},
onShow
(
args
)
{
initVm
.
call
(
this
,
vm
)
this
.
$vm
.
__call_hook
(
'
onShow
'
,
args
)
}
}
// 兼容旧版本 globalData
appOptions
.
globalData
=
vm
.
$options
.
globalData
||
{}
initHooks
(
appOptions
,
hooks
)
// 延迟执行,因为 App 的注册在 main.js 之前,可能导致生命周期内 Vue 原型上开发者注册的属性无法访问
App
(
appOptions
)
App
(
parseApp
(
vm
))
return
vm
}
src/core/runtime/wrapper/create-component.js
浏览文件 @
5bef921d
import
Vue
from
'
vue
'
import
{
isFn
}
from
'
uni-shared
'
import
{
handleLink
,
triggerLink
,
initComponent
}
from
'
uni-platform/runtime/wrapper/index
'
import
{
getData
,
handleEvent
,
getBehaviors
,
getProperties
}
from
'
./util
'
function
initVm
(
VueComponent
)
{
if
(
this
.
$vm
)
{
return
}
const
properties
=
__PLATFORM__
===
'
mp-alipay
'
?
this
.
props
:
this
.
properties
const
options
=
{
mpType
:
'
component
'
,
mpInstance
:
this
,
propsData
:
properties
}
// 初始化 vue 实例
this
.
$vm
=
new
VueComponent
(
options
)
// 处理$slots,$scopedSlots(暂不支持动态变化$slots)
const
vueSlots
=
properties
.
vueSlots
if
(
Array
.
isArray
(
vueSlots
)
&&
vueSlots
.
length
)
{
const
$slots
=
Object
.
create
(
null
)
vueSlots
.
forEach
(
slotName
=>
{
$slots
[
slotName
]
=
true
})
this
.
$vm
.
$scopedSlots
=
this
.
$vm
.
$slots
=
$slots
}
// 性能优先,mount 提前到 attached 中,保证组件首次渲染数据被合并
// 导致与标准 Vue 的差异,data 和 computed 中不能使用$parent,provide等组件属性
this
.
$vm
.
$mount
()
}
import
parseComponent
from
'
uni-platform/runtime/wrapper/component-parser
'
export
function
createComponent
(
vueOptions
)
{
vueOptions
=
vueOptions
.
default
||
vueOptions
let
VueComponent
if
(
isFn
(
vueOptions
))
{
VueComponent
=
vueOptions
// TODO form-field props.name,props.value
vueOptions
=
VueComponent
.
extendOptions
if
(
__PLATFORM__
===
'
mp-alipay
'
)
{
return
my
.
createComponent
(
parseComponent
(
vueOptions
))
}
else
{
VueComponent
=
Vue
.
extend
(
vueOptions
)
}
const
behaviors
=
getBehaviors
(
vueOptions
)
const
properties
=
getProperties
(
vueOptions
.
props
,
false
,
vueOptions
.
__file
)
const
componentOptions
=
{
options
:
{
multipleSlots
:
true
,
addGlobalClass
:
true
},
data
:
getData
(
vueOptions
,
Vue
.
prototype
),
behaviors
,
properties
,
lifetimes
:
{
attached
()
{
initVm
.
call
(
this
,
VueComponent
)
},
ready
()
{
initVm
.
call
(
this
,
VueComponent
)
// 目前发现部分情况小程序 attached 不触发
triggerLink
(
this
)
// 处理 parent,children
// 补充生命周期
this
.
$vm
.
__call_hook
(
'
created
'
)
this
.
$vm
.
__call_hook
(
'
beforeMount
'
)
this
.
$vm
.
_isMounted
=
true
this
.
$vm
.
__call_hook
(
'
mounted
'
)
this
.
$vm
.
__call_hook
(
'
onReady
'
)
},
detached
()
{
this
.
$vm
.
$destroy
()
}
},
pageLifetimes
:
{
show
(
args
)
{
this
.
$vm
.
__call_hook
(
'
onPageShow
'
,
args
)
},
hide
()
{
this
.
$vm
&&
this
.
$vm
.
__call_hook
(
'
onPageHide
'
)
},
resize
(
size
)
{
this
.
$vm
&&
this
.
$vm
.
__call_hook
(
'
onPageResize
'
,
size
)
}
},
methods
:
{
__e
:
handleEvent
,
__l
:
handleLink
return
Component
(
parseComponent
(
vueOptions
))
}
}
return
initComponent
(
componentOptions
,
vueOptions
)
}
src/core/runtime/wrapper/create-page.js
浏览文件 @
5bef921d
import
Vue
from
'
vue
'
import
parsePage
from
'
uni-platform/runtime/wrapper/page-parser
'
import
{
isFn
}
from
'
uni-shared
'
import
{
initPage
,
handleLink
}
from
'
uni-platform/runtime/wrapper/index
'
import
{
getData
,
initHooks
,
handleEvent
,
baiduPageDestroy
}
from
'
./util
'
const
hooks
=
[
'
onShow
'
,
'
onHide
'
,
'
onPullDownRefresh
'
,
'
onReachBottom
'
,
'
onShareAppMessage
'
,
'
onPageScroll
'
,
'
onResize
'
,
'
onTabItemTap
'
,
'
onBackPress
'
,
'
onNavigationBarButtonTap
'
,
'
onNavigationBarSearchInputChanged
'
,
'
onNavigationBarSearchInputConfirmed
'
,
'
onNavigationBarSearchInputClicked
'
]
function
initVm
(
VueComponent
)
{
// 百度的 onLoad 触发在 attached 之前
if
(
this
.
$vm
)
{
return
}
this
.
$vm
=
new
VueComponent
({
mpType
:
'
page
'
,
mpInstance
:
this
})
if
(
__PLATFORM__
===
'
mp-baidu
'
)
{
this
.
$vm
.
$baiduComponentInstances
=
Object
.
create
(
null
)
}
this
.
$vm
.
__call_hook
(
'
created
'
)
this
.
$vm
.
$mount
()
}
export
function
createPage
(
vueOptions
)
{
vueOptions
=
vueOptions
.
default
||
vueOptions
let
VueComponent
if
(
isFn
(
vueOptions
))
{
VueComponent
=
vueOptions
vueOptions
=
VueComponent
.
extendOptions
export
function
createPage
(
vuePageOptions
)
{
if
(
__PLATFORM__
===
'
mp-alipay
'
)
{
return
Page
(
parsePage
(
vuePageOptions
))
}
else
{
VueComponent
=
Vue
.
extend
(
vueOptions
)
}
const
pageOptions
=
{
options
:
{
multipleSlots
:
true
,
addGlobalClass
:
true
},
data
:
getData
(
vueOptions
,
Vue
.
prototype
),
lifetimes
:
{
// 当页面作为组件时
attached
()
{
initVm
.
call
(
this
,
VueComponent
)
},
ready
()
{
this
.
$vm
.
__call_hook
(
'
beforeMount
'
)
this
.
$vm
.
_isMounted
=
true
this
.
$vm
.
__call_hook
(
'
mounted
'
)
this
.
$vm
.
__call_hook
(
'
onReady
'
)
},
detached
()
{
this
.
$vm
.
$destroy
()
}
},
methods
:
{
// 作为页面时
onLoad
(
args
)
{
initVm
.
call
(
this
,
VueComponent
)
if
(
__PLATFORM__
===
'
mp-baidu
'
)
{
// 百度当组件作为页面时 pageinstancce 不是原来组件的 instance
this
.
pageinstance
.
$vm
=
this
.
$vm
}
this
.
$vm
.
$mp
.
query
=
args
// 又要兼容 mpvue
this
.
$vm
.
__call_hook
(
'
onLoad
'
,
args
)
// 开发者可能会在 onLoad 时赋值,提前到 mount 之前
},
onUnload
()
{
this
.
$vm
.
__call_hook
(
'
onUnload
'
)
if
(
__PLATFORM__
===
'
mp-baidu
'
)
{
// 百度组件不会在页面 unload 时触发 detached
baiduPageDestroy
(
this
.
$vm
)
return
Component
(
parsePage
(
vuePageOptions
))
}
},
__e
:
handleEvent
,
__l
:
handleLink
}
}
initHooks
(
pageOptions
.
methods
,
hooks
)
return
initPage
(
pageOptions
,
vueOptions
)
}
src/core/runtime/wrapper/util.js
浏览文件 @
5bef921d
...
...
@@ -5,9 +5,14 @@ import {
isPlainObject
}
from
'
uni-shared
'
import
{
initBehavior
}
from
'
uni-platform/runtime/wrapper/index
'
export
const
PAGE_EVENT_HOOKS
=
[
'
onPullDownRefresh
'
,
'
onReachBottom
'
,
'
onShareAppMessage
'
,
'
onPageScroll
'
,
'
onResize
'
,
'
onTabItemTap
'
]
export
function
initMocks
(
vm
,
mocks
)
{
const
mpInstance
=
vm
.
$mp
[
vm
.
mpType
]
...
...
@@ -21,12 +26,46 @@ export function initMocks (vm, mocks) {
export
function
initHooks
(
mpOptions
,
hooks
)
{
hooks
.
forEach
(
hook
=>
{
mpOptions
[
hook
]
=
function
(
args
)
{
return
this
.
$vm
.
__call_hook
(
hook
,
args
)
return
this
.
$vm
&&
this
.
$vm
.
__call_hook
(
hook
,
args
)
}
})
}
export
function
getData
(
vueOptions
,
context
)
{
export
function
initVueComponent
(
Vue
,
vueOptions
)
{
vueOptions
=
vueOptions
.
default
||
vueOptions
let
VueComponent
if
(
isFn
(
vueOptions
))
{
VueComponent
=
vueOptions
vueOptions
=
VueComponent
.
extendOptions
}
else
{
VueComponent
=
Vue
.
extend
(
vueOptions
)
}
return
[
VueComponent
,
vueOptions
]
}
export
function
initSlots
(
vm
,
vueSlots
)
{
if
(
Array
.
isArray
(
vueSlots
)
&&
vueSlots
.
length
)
{
const
$slots
=
Object
.
create
(
null
)
vueSlots
.
forEach
(
slotName
=>
{
$slots
[
slotName
]
=
true
})
vm
.
$scopedSlots
=
vm
.
$slots
=
$slots
}
}
export
function
initVueIds
(
vueIds
,
mpInstance
)
{
vueIds
=
(
vueIds
||
''
).
split
(
'
,
'
)
const
len
=
vueIds
.
length
if
(
len
===
1
)
{
mpInstance
.
_$vueId
=
vueIds
[
0
]
}
else
if
(
len
===
2
)
{
mpInstance
.
_$vueId
=
vueIds
[
0
]
mpInstance
.
_$vuePid
=
vueIds
[
1
]
}
}
export
function
initData
(
vueOptions
,
context
)
{
let
data
=
vueOptions
.
data
||
{}
const
methods
=
vueOptions
.
methods
||
{}
...
...
@@ -68,7 +107,7 @@ function createObserver (name) {
}
}
export
function
getBehaviors
(
vueOptions
)
{
export
function
initBehaviors
(
vueOptions
,
initBehavior
)
{
const
vueBehaviors
=
vueOptions
[
'
behaviors
'
]
const
vueExtends
=
vueOptions
[
'
extends
'
]
const
vueMixins
=
vueOptions
[
'
mixins
'
]
...
...
@@ -97,7 +136,7 @@ export function getBehaviors (vueOptions) {
if
(
isPlainObject
(
vueExtends
)
&&
vueExtends
.
props
)
{
behaviors
.
push
(
initBehavior
({
properties
:
ge
tProperties
(
vueExtends
.
props
,
true
)
properties
:
ini
tProperties
(
vueExtends
.
props
,
true
)
})
)
}
...
...
@@ -106,7 +145,7 @@ export function getBehaviors (vueOptions) {
if
(
isPlainObject
(
vueMixin
)
&&
vueMixin
.
props
)
{
behaviors
.
push
(
initBehavior
({
properties
:
ge
tProperties
(
vueMixin
.
props
,
true
)
properties
:
ini
tProperties
(
vueMixin
.
props
,
true
)
})
)
}
...
...
@@ -139,9 +178,13 @@ function parsePropType (key, type, defaultValue, file) {
return
type
}
export
function
ge
tProperties
(
props
,
isBehavior
=
false
,
file
=
''
)
{
export
function
ini
tProperties
(
props
,
isBehavior
=
false
,
file
=
''
)
{
const
properties
=
{}
if
(
!
isBehavior
)
{
properties
.
vueId
=
{
type
:
String
,
value
:
''
}
properties
.
vueSlots
=
{
// 小程序不能直接定义 $slots 的 props,所以通过 vueSlots 转换到 $slots
type
:
null
,
value
:
[],
...
...
@@ -398,17 +441,3 @@ export function handleEvent (event) {
}
})
}
function
baiduComponentDestroy
(
$vm
)
{
$vm
.
$children
.
forEach
(
childVm
=>
{
childVm
.
$mp
.
component
.
detached
()
})
$vm
.
$mp
.
component
.
detached
()
}
export
function
baiduPageDestroy
(
$vm
)
{
$vm
.
$destroy
()
$vm
.
$children
.
forEach
(
childVm
=>
{
baiduComponentDestroy
(
childVm
)
})
}
src/platforms/app-plus/runtime/wrapper/app-parser.js
0 → 100644
浏览文件 @
5bef921d
import
{
initHooks
}
from
'
uni-wrapper/util
'
import
parseBaseApp
from
'
../../../mp-weixin/runtime/wrapper/app-parser
'
const
hooks
=
[
'
onUniNViewMessage
'
]
export
default
function
parseApp
(
vm
)
{
const
appOptions
=
parseBaseApp
(
vm
)
initHooks
(
appOptions
,
hooks
)
return
appOptions
}
src/platforms/app-plus/runtime/wrapper/component-parser.js
0 → 100644
浏览文件 @
5bef921d
import
parseBaseComponent
from
'
../../../mp-weixin/runtime/wrapper/component-parser
'
export
default
function
parseComponent
(
vueComponentOptions
)
{
const
componentOptions
=
parseBaseComponent
(
vueComponentOptions
)
componentOptions
.
methods
.
$getAppWebview
=
function
()
{
return
plus
.
webview
.
getWebviewById
(
`
${
this
.
__wxWebviewId__
}
`
)
}
return
componentOptions
}
src/platforms/app-plus/runtime/wrapper/index.js
已删除
100644 → 0
浏览文件 @
63fa0d5e
export
{
mocks
,
initRefs
,
handleLink
,
triggerLink
,
initBehavior
}
from
'
../../../mp-weixin/runtime/wrapper/index
'
export
function
initPage
(
pageOptions
)
{
return
initComponent
(
pageOptions
)
}
export
function
initComponent
(
componentOptions
)
{
componentOptions
.
methods
.
$getAppWebview
=
function
()
{
return
plus
.
webview
.
getWebviewById
(
`
${
this
.
__wxWebviewId__
}
`
)
}
return
Component
(
componentOptions
)
}
src/platforms/app-plus/runtime/wrapper/page-parser.js
0 → 100644
浏览文件 @
5bef921d
import
{
initHooks
}
from
'
uni-wrapper/util
'
import
parseBasePage
from
'
../../../mp-weixin/runtime/wrapper/page-parser
'
const
hooks
=
[
'
onBackPress
'
,
'
onNavigationBarButtonTap
'
,
'
onNavigationBarSearchInputChanged
'
,
'
onNavigationBarSearchInputConfirmed
'
,
'
onNavigationBarSearchInputClicked
'
]
export
default
function
parsePage
(
vuePageOptions
)
{
const
pageOptions
=
parseBasePage
(
vuePageOptions
)
initHooks
(
pageOptions
.
methods
,
hooks
)
return
pageOptions
}
src/platforms/mp-alipay/runtime/wrapper/app-parser.js
0 → 100644
浏览文件 @
5bef921d
import
Vue
from
'
vue
'
import
parseBaseApp
from
'
../../../mp-weixin/runtime/wrapper/app-base-parser
'
import
{
mocks
,
initRefs
}
from
'
./util
'
export
default
function
parseApp
(
vm
)
{
Object
.
defineProperty
(
Vue
.
prototype
,
'
$slots
'
,
{
get
()
{
return
this
.
$scope
&&
this
.
$scope
.
props
.
$slots
},
set
()
{
}
})
Object
.
defineProperty
(
Vue
.
prototype
,
'
$scopedSlots
'
,
{
get
()
{
return
this
.
$scope
&&
this
.
$scope
.
props
.
$scopedSlots
},
set
()
{
}
})
return
parseBaseApp
(
vm
,
{
mocks
,
initRefs
})
}
src/platforms/mp-alipay/runtime/wrapper/component-parser.js
0 → 100644
浏览文件 @
5bef921d
import
Vue
from
'
vue
'
import
{
initData
,
initVueIds
,
handleEvent
,
initBehaviors
,
initProperties
,
initVueComponent
}
from
'
uni-wrapper/util
'
import
{
handleRef
,
handleLink
,
initBehavior
,
initRelation
,
triggerEvent
,
createObserver
,
isComponent2
,
initChildVues
}
from
'
./util
'
function
initVm
(
VueComponent
)
{
if
(
this
.
$vm
)
{
return
}
const
properties
=
this
.
props
const
options
=
{
mpType
:
'
component
'
,
mpInstance
:
this
,
propsData
:
properties
}
initVueIds
(
properties
.
vueId
,
this
)
if
(
isComponent2
)
{
// 处理父子关系
initRelation
.
call
(
this
,
{
vuePid
:
this
.
_$vuePid
,
vueOptions
:
options
})
// 初始化 vue 实例
this
.
$vm
=
new
VueComponent
(
options
)
// 触发首次 setData
this
.
$vm
.
$mount
()
}
else
{
initChildVues
(
this
)
// 处理父子关系
initRelation
.
call
(
this
,
{
vuePid
:
this
.
_$vuePid
,
vueOptions
:
options
,
VueComponent
,
mpInstance
:
this
})
if
(
options
.
parent
)
{
// 父组件已经初始化,直接初始化子,否则放到父组件的 didMount 中处理
// 初始化 vue 实例
this
.
$vm
=
new
VueComponent
(
options
)
handleRef
.
call
(
options
.
parent
.
$scope
,
this
)
// 触发首次 setData
this
.
$vm
.
$mount
()
this
.
$vm
.
_isMounted
=
true
this
.
$vm
.
__call_hook
(
'
mounted
'
)
this
.
$vm
.
__call_hook
(
'
onReady
'
)
}
}
}
export
default
function
parseComponent
(
vueComponentOptions
)
{
let
[
VueComponent
,
vueOptions
]
=
initVueComponent
(
Vue
,
vueComponentOptions
)
const
properties
=
initProperties
(
vueOptions
.
props
,
false
,
vueOptions
.
__file
)
const
props
=
{
onVueInit
:
function
()
{}
}
Object
.
keys
(
properties
).
forEach
(
key
=>
{
if
(
key
!==
'
vueSlots
'
)
{
props
[
key
]
=
properties
[
key
].
value
}
})
const
componentOptions
=
{
mixins
:
initBehaviors
(
vueOptions
,
initBehavior
),
data
:
initData
(
vueOptions
,
Vue
.
prototype
),
props
,
didMount
()
{
initVm
.
call
(
this
,
VueComponent
)
if
(
isComponent2
)
{
this
.
$vm
.
_isMounted
=
true
this
.
$vm
.
__call_hook
(
'
mounted
'
)
this
.
$vm
.
__call_hook
(
'
onReady
'
)
}
},
didUnmount
()
{
this
.
$vm
.
$destroy
()
},
methods
:
{
__r
:
handleRef
,
__e
:
handleEvent
,
__l
:
handleLink
,
triggerEvent
}
}
if
(
isComponent2
)
{
componentOptions
.
onInit
=
function
onInit
()
{
initVm
.
call
(
this
,
VueComponent
)
}
componentOptions
.
deriveDataFromProps
=
createObserver
()
}
else
{
componentOptions
.
didUpdate
=
createObserver
(
true
)
}
if
(
vueOptions
.
methods
&&
vueOptions
.
methods
.
formReset
)
{
componentOptions
.
methods
.
formReset
=
vueOptions
.
methods
.
formReset
}
return
componentOptions
}
src/platforms/mp-alipay/runtime/wrapper/page-parser.js
0 → 100644
浏览文件 @
5bef921d
import
Vue
from
'
vue
'
import
{
initData
,
initHooks
,
handleEvent
,
initBehaviors
,
initVueComponent
,
PAGE_EVENT_HOOKS
}
from
'
uni-wrapper/util
'
import
{
handleRef
,
handleLink
,
initBehavior
,
initChildVues
}
from
'
./util
'
const
hooks
=
[
'
onShow
'
,
'
onHide
'
,
// mp-alipay 特有
'
onTitleClick
'
,
'
onOptionMenuClick
'
,
'
onPopMenuClick
'
,
'
onPullIntercept
'
]
hooks
.
push
(...
PAGE_EVENT_HOOKS
)
export
default
function
parsePage
(
vuePageOptions
)
{
let
[
VueComponent
,
vueOptions
]
=
initVueComponent
(
Vue
,
vuePageOptions
)
const
pageOptions
=
{
mixins
:
initBehaviors
(
vueOptions
,
initBehavior
),
data
:
initData
(
vueOptions
,
Vue
.
prototype
),
onLoad
(
args
)
{
const
properties
=
this
.
props
const
options
=
{
mpType
:
'
page
'
,
mpInstance
:
this
,
propsData
:
properties
}
// 初始化 vue 实例
this
.
$vm
=
new
VueComponent
(
options
)
// 触发首次 setData
this
.
$vm
.
$mount
()
this
.
$vm
.
$mp
.
query
=
args
// 兼容 mpvue
this
.
$vm
.
__call_hook
(
'
onLoad
'
,
args
)
},
onReady
()
{
initChildVues
(
this
)
this
.
$vm
.
_isMounted
=
true
this
.
$vm
.
__call_hook
(
'
mounted
'
)
this
.
$vm
.
__call_hook
(
'
onReady
'
)
},
onUnload
()
{
this
.
$vm
.
__call_hook
(
'
onUnload
'
)
this
.
$vm
.
$destroy
()
},
__r
:
handleRef
,
__e
:
handleEvent
,
__l
:
handleLink
}
initHooks
(
pageOptions
,
hooks
)
return
pageOptions
}
src/platforms/mp-alipay/runtime/wrapper/
index
.js
→
src/platforms/mp-alipay/runtime/wrapper/
util
.js
浏览文件 @
5bef921d
...
...
@@ -4,6 +4,10 @@ import {
camelize
}
from
'
uni-shared
'
import
{
handleLink
as
handleBaseLink
}
from
'
../../../mp-weixin/runtime/wrapper/util
'
import
deepEqual
from
'
./deep-equal
'
const
customizeRE
=
/:/g
...
...
@@ -12,56 +16,75 @@ const customize = cached((str) => {
return
camelize
(
str
.
replace
(
customizeRE
,
'
-
'
))
})
export
const
isComponent2
=
my
.
canIUse
(
'
component2
'
)
export
const
mocks
=
[
'
$id
'
]
export
function
initRefs
()
{
}
function
handleRef
(
ref
)
{
if
(
!
ref
)
{
return
}
const
refName
=
ref
.
props
[
'
data-ref
'
]
const
refInForName
=
ref
.
props
[
'
data-ref-in-for
'
]
if
(
refName
)
{
this
.
$vm
.
$refs
[
refName
]
=
ref
.
$vm
||
ref
}
else
if
(
refInForName
)
{
this
.
$vm
.
$refs
[
refInForName
]
=
[
ref
.
$vm
||
ref
]
}
}
export
function
initBehavior
({
properties
})
{
const
props
=
{}
export
function
initPage
(
pageOptions
,
vueOptions
)
{
const
{
lifetimes
,
methods
}
=
pageOptions
Object
.
keys
(
properties
).
forEach
(
key
=>
{
props
[
key
]
=
properties
[
key
].
value
})
pageOptions
.
onReady
=
lifetimes
.
ready
pageOptions
.
onUnload
=
function
()
{
lifetimes
.
detached
.
call
(
this
)
methods
.
onUnload
.
call
(
this
)
return
{
props
}
}
export
function
initRelation
(
detail
)
{
this
.
props
.
onVueInit
(
detail
)
}
Object
.
keys
(
methods
).
forEach
(
method
=>
{
if
(
method
!==
'
onUnload
'
)
{
pageOptions
[
method
]
=
methods
[
method
]
export
function
initChildVues
(
mpInstance
)
{
mpInstance
.
_$childVues
&&
mpInstance
.
_$childVues
.
forEach
(({
vuePid
,
vueOptions
,
VueComponent
,
mpInstance
:
childMPInstance
})
=>
{
// 父子关系
handleBaseLink
.
call
(
mpInstance
,
{
detail
:
{
vuePid
,
vueOptions
}
})
pageOptions
[
'
__r
'
]
=
handleRef
childMPInstance
.
$vm
=
new
VueComponent
(
vueOptions
)
if
(
vueOptions
.
methods
&&
vueOptions
.
methods
.
formReset
)
{
pageOptions
[
'
formReset
'
]
=
vueOptions
.
methods
.
formReset
}
handleRef
.
call
(
vueOptions
.
parent
.
$scope
,
childMPInstance
)
childMPInstance
.
$vm
.
$mount
()
childMPInstance
.
$vm
.
_isMounted
=
true
childMPInstance
.
$vm
.
__call_hook
(
'
mounted
'
)
childMPInstance
.
$vm
.
__call_hook
(
'
onReady
'
)
})
delete
pageOptions
.
lifetim
es
delete
pageOptions
.
methods
delete
mpInstance
.
_$childVu
es
}
return
Page
(
pageOptions
)
export
function
handleRef
(
ref
)
{
if
(
!
ref
)
{
return
}
const
refName
=
ref
.
props
[
'
data-ref
'
]
const
refInForName
=
ref
.
props
[
'
data-ref-in-for
'
]
if
(
refName
)
{
this
.
$vm
.
$refs
[
refName
]
=
ref
.
$vm
||
ref
}
else
if
(
refInForName
)
{
this
.
$vm
.
$refs
[
refInForName
]
=
[
ref
.
$vm
||
ref
]
}
}
function
triggerEvent
(
type
,
detail
,
options
)
{
export
function
triggerEvent
(
type
,
detail
,
options
)
{
const
handler
=
this
.
props
[
customize
(
'
on-
'
+
type
)]
if
(
!
handler
)
{
return
...
...
@@ -85,7 +108,7 @@ function triggerEvent (type, detail, options) {
const
IGNORES
=
[
'
$slots
'
,
'
$scopedSlots
'
]
function
createObserver
(
isDidUpdate
)
{
export
function
createObserver
(
isDidUpdate
)
{
return
function
observe
(
props
)
{
const
prevProps
=
isDidUpdate
?
props
:
this
.
props
const
nextProps
=
isDidUpdate
?
this
.
props
:
props
...
...
@@ -104,92 +127,24 @@ function createObserver (isDidUpdate) {
}
}
export
function
initComponent
(
componentOptions
,
vueOptions
)
{
const
{
lifetimes
,
properties
,
behaviors
}
=
componentOptions
componentOptions
.
mixins
=
behaviors
const
props
=
{
onTriggerLink
:
function
()
{}
}
Object
.
keys
(
properties
).
forEach
(
key
=>
{
if
(
key
!==
'
vueSlots
'
)
{
props
[
key
]
=
properties
[
key
].
value
}
export
const
handleLink
=
(
function
()
{
if
(
isComponent2
)
{
return
function
handleLink
(
detail
)
{
return
handleBaseLink
.
call
(
this
,
{
detail
})
componentOptions
.
props
=
props
if
(
my
.
canIUse
(
'
component2
'
))
{
componentOptions
.
onInit
=
lifetimes
.
attached
}
componentOptions
.
didMount
=
lifetimes
.
ready
componentOptions
.
didUnmount
=
lifetimes
.
detached
if
(
my
.
canIUse
(
'
component2
'
))
{
componentOptions
.
deriveDataFromProps
=
createObserver
()
// nextProps
}
else
{
componentOptions
.
didUpdate
=
createObserver
(
true
)
// prevProps
}
if
(
!
componentOptions
.
methods
)
{
componentOptions
.
methods
=
{}
}
if
(
vueOptions
.
methods
&&
vueOptions
.
methods
.
formReset
)
{
componentOptions
.
methods
[
'
formReset
'
]
=
vueOptions
.
methods
.
formReset
return
function
handleLink
(
detail
)
{
if
(
this
.
$vm
)
{
// 父已初始化
return
handleBaseLink
.
call
(
this
,
{
detail
:
{
vuePid
:
detail
.
vuePid
,
vueOptions
:
detail
.
vueOptions
}
componentOptions
.
methods
[
'
__r
'
]
=
handleRef
componentOptions
.
methods
.
triggerEvent
=
triggerEvent
delete
componentOptions
.
properties
delete
componentOptions
.
behaviors
delete
componentOptions
.
lifetimes
delete
componentOptions
.
pageLifetimes
return
my
.
createComponent
(
componentOptions
)
}
export
function
initBehavior
({
properties
})
{
const
props
=
{}
Object
.
keys
(
properties
).
forEach
(
key
=>
{
props
[
key
]
=
properties
[
key
].
value
})
return
{
props
}
}
export
function
triggerLink
(
mpInstance
,
vueOptions
)
{
mpInstance
.
props
.
onTriggerLink
(
mpInstance
.
$vm
||
vueOptions
)
}
export
function
handleLink
(
detail
)
{
if
(
detail
.
$mp
)
{
// vm
if
(
!
detail
.
$parent
)
{
detail
.
$parent
=
this
.
$vm
if
(
detail
.
$parent
)
{
detail
.
$parent
.
$children
.
push
(
detail
)
detail
.
$root
=
this
.
$vm
.
$root
if
(
!
my
.
canIUse
(
'
component2
'
))
{
handleRef
.
call
(
this
,
detail
.
$scope
)
// 支付宝通过 didMount 来实现,先子后父,故等父 ready 之后,统一初始化
(
this
.
_$childVues
||
(
this
.
_$childVues
=
[])).
unshift
(
detail
)
}
}
}
}
else
{
// vueOptions
if
(
!
detail
.
parent
)
{
detail
.
parent
=
this
.
$vm
}
}
}
})()
src/platforms/mp-baidu/runtime/wrapper/app-parser.js
0 → 100644
浏览文件 @
5bef921d
import
parseBaseApp
from
'
../../../mp-weixin/runtime/wrapper/app-base-parser
'
import
{
initRefs
}
from
'
../../../mp-weixin/runtime/wrapper/util
'
import
{
mocks
}
from
'
./util
'
export
default
function
parseApp
(
vm
)
{
return
parseBaseApp
(
vm
,
{
mocks
,
initRefs
})
}
src/platforms/mp-baidu/runtime/wrapper/component-parser.js
0 → 100644
浏览文件 @
5bef921d
import
{
isPage
,
initRelation
}
from
'
./util
'
import
parseBaseComponent
from
'
../../../mp-weixin/runtime/wrapper/component-base-parser
'
export
default
function
parseComponent
(
vueOptions
)
{
const
componentOptions
=
parseBaseComponent
(
vueOptions
,
{
isPage
,
initRelation
})
const
oldAttached
=
componentOptions
.
lifetimes
.
attached
componentOptions
.
lifetimes
.
attached
=
function
attached
()
{
oldAttached
.
call
(
this
)
if
(
isPage
.
call
(
this
))
{
// 百度 onLoad 在 attached 之前触发
// 百度 当组件作为页面时 pageinstancce 不是原来组件的 instance
this
.
pageinstance
.
$vm
=
this
.
$vm
this
.
$vm
.
$mp
.
query
=
this
.
pageinstance
.
_$args
// 兼容 mpvue
this
.
$vm
.
__call_hook
(
'
onLoad
'
,
this
.
pageinstance
.
_$args
)
}
}
componentOptions
.
messages
=
{
'
__l
'
:
componentOptions
.
methods
[
'
__l
'
]
}
delete
componentOptions
.
methods
[
'
__l
'
]
return
componentOptions
}
src/platforms/mp-baidu/runtime/wrapper/index.js
已删除
100644 → 0
浏览文件 @
63fa0d5e
export
{
initRefs
,
initBehavior
}
from
'
../../../mp-weixin/runtime/wrapper/index
'
export
const
mocks
=
[
'
nodeId
'
]
export
function
initPage
(
pageOptions
)
{
return
initComponent
(
pageOptions
)
}
export
function
initComponent
(
componentOptions
)
{
componentOptions
.
messages
=
{
'
__l
'
:
handleLink
}
return
Component
(
componentOptions
)
}
export
function
triggerLink
(
mpInstance
,
vueOptions
)
{
mpInstance
.
dispatch
(
'
__l
'
,
mpInstance
.
$vm
||
vueOptions
)
}
export
function
handleLink
(
event
)
{
const
target
=
event
.
value
if
(
target
.
$mp
)
{
if
(
!
target
.
$parent
)
{
target
.
$parent
=
this
.
$vm
target
.
$parent
.
$children
.
push
(
target
)
target
.
$root
=
this
.
$vm
.
$root
}
}
else
{
if
(
!
target
.
parent
)
{
target
.
parent
=
this
.
$vm
}
}
}
src/platforms/mp-baidu/runtime/wrapper/page-parser.js
0 → 100644
浏览文件 @
5bef921d
import
{
isPage
,
initRelation
}
from
'
./util
'
import
parseBasePage
from
'
../../../mp-weixin/runtime/wrapper/page-base-parser
'
function
detached
(
$vm
)
{
$vm
.
$children
.
forEach
(
childVm
=>
{
childVm
.
$scope
.
detached
()
})
$vm
.
$scope
.
detached
()
}
function
onPageUnload
(
$vm
)
{
$vm
.
$destroy
()
$vm
.
$children
.
forEach
(
childVm
=>
{
detached
(
childVm
)
})
}
export
default
function
parsePage
(
vuePageOptions
)
{
const
pageOptions
=
parseBasePage
(
vuePageOptions
,
{
isPage
,
initRelation
})
pageOptions
.
methods
.
onLoad
=
function
onLoad
(
args
)
{
// 百度 onLoad 在 attached 之前触发,先存储 args, 在 attached 里边触发 onLoad
this
.
pageinstance
.
_$args
=
args
}
pageOptions
.
methods
.
onUnload
=
function
onUnload
()
{
this
.
$vm
.
__call_hook
(
'
onUnload
'
)
onPageUnload
(
this
.
$vm
)
}
return
pageOptions
}
src/platforms/mp-baidu/runtime/wrapper/util.js
0 → 100644
浏览文件 @
5bef921d
export
const
mocks
=
[
'
nodeId
'
]
export
function
isPage
()
{
return
!
this
.
ownerId
}
export
function
initRelation
(
detail
)
{
this
.
dispatch
(
'
__l
'
,
detail
)
}
src/platforms/mp-toutiao/runtime/wrapper/app-parser.js
0 → 100644
浏览文件 @
5bef921d
import
Vue
from
'
vue
'
import
parseBaseApp
from
'
../../../mp-weixin/runtime/wrapper/app-base-parser
'
import
{
mocks
,
initRefs
}
from
'
./util
'
export
default
function
parseApp
(
vm
)
{
Vue
.
prototype
.
_$fallback
=
true
// 降级(调整原 vue 的部分生命周期,如 created,beforeMount,inject,provide)
Vue
.
mixin
({
created
()
{
// 处理 injections,头条 triggerEvent 是异步,且触发时机很慢,故延迟 relation 设置
if
(
this
.
mpType
!==
'
app
'
)
{
initRefs
(
this
)
this
.
__init_injections
(
this
)
this
.
__init_provide
(
this
)
}
}
})
return
parseBaseApp
(
vm
,
{
mocks
,
initRefs
:
function
()
{}
// attached 时,可能查询不到
})
}
src/platforms/mp-toutiao/runtime/wrapper/component-parser.js
0 → 100644
浏览文件 @
5bef921d
import
{
isPage
,
initRelation
,
handleLink
}
from
'
./util
'
import
{
initSlots
,
initVueIds
}
from
'
uni-wrapper/util
'
import
parseBaseComponent
from
'
../../../mp-weixin/runtime/wrapper/component-base-parser
'
export
default
function
parseComponent
(
vueOptions
)
{
const
[
componentOptions
,
VueComponent
]
=
parseBaseComponent
(
vueOptions
)
componentOptions
.
lifetimes
.
attached
=
function
attached
()
{
const
properties
=
this
.
properties
const
options
=
{
mpType
:
isPage
.
call
(
this
)
?
'
page
'
:
'
component
'
,
mpInstance
:
this
,
propsData
:
properties
}
initVueIds
(
properties
.
vueId
,
this
)
// 初始化 vue 实例
this
.
$vm
=
new
VueComponent
(
options
)
// 处理$slots,$scopedSlots(暂不支持动态变化$slots)
initSlots
(
this
.
$vm
,
properties
.
vueSlots
)
// 处理父子关系
initRelation
.
call
(
this
,
{
vuePid
:
this
.
_$vuePid
,
mpInstance
:
this
})
// 触发首次 setData
this
.
$vm
.
$mount
()
}
// ready 比 handleLink 还早,初始化逻辑放到 handleLink 中
delete
componentOptions
.
lifetimes
.
ready
componentOptions
.
methods
.
__l
=
handleLink
return
componentOptions
}
src/platforms/mp-toutiao/runtime/wrapper/page-parser.js
0 → 100644
浏览文件 @
5bef921d
import
{
isPage
,
initRelation
}
from
'
./util
'
import
parseBasePage
from
'
../../../mp-weixin/runtime/wrapper/page-base-parser
'
export
default
function
parsePage
(
vuePageOptions
)
{
const
pageOptions
=
parseBasePage
(
vuePageOptions
,
{
isPage
,
initRelation
})
// 页面需要在 ready 中触发,其他组件是在 handleLink 中触发
pageOptions
.
lifetimes
.
ready
=
function
ready
()
{
if
(
this
.
$vm
&&
this
.
$vm
.
mpType
===
'
page
'
)
{
this
.
$vm
.
__call_hook
(
'
created
'
)
this
.
$vm
.
__call_hook
(
'
beforeMount
'
)
this
.
$vm
.
_isMounted
=
true
this
.
$vm
.
__call_hook
(
'
mounted
'
)
this
.
$vm
.
__call_hook
(
'
onReady
'
)
}
else
{
this
.
is
&&
console
.
warn
(
this
.
is
+
'
is not ready
'
)
}
}
return
pageOptions
}
src/platforms/mp-toutiao/runtime/wrapper/
index
.js
→
src/platforms/mp-toutiao/runtime/wrapper/
util
.js
浏览文件 @
5bef921d
export
{
initBehavior
}
from
'
../../../mp-weixin/runtime/wrapper/index
'
const
instances
=
Object
.
create
(
null
)
import
{
findVmByVueId
}
from
'
../../../mp-weixin/runtime/wrapper/util
'
export
const
mocks
=
[
'
__route__
'
,
'
__webviewId__
'
,
'
__nodeid__
'
]
export
const
mocks
=
[
'
__route__
'
,
'
__webviewId__
'
,
'
__nodeid__
'
,
'
__nodeId__
'
]
export
function
initPage
(
pageOptions
)
{
return
initComponent
(
pageOptions
)
}
export
function
initComponent
(
componentOptions
)
{
if
(
componentOptions
.
properties
)
{
// ref
componentOptions
.
properties
.
vueRef
=
{
type
:
String
,
value
:
''
}
}
return
Component
(
componentOptions
)
export
function
isPage
()
{
return
this
.
__nodeid__
===
0
||
this
.
__nodeId__
===
0
}
export
function
initRefs
(
vm
)
{
const
mpInstance
=
vm
.
$scope
mpInstance
.
selectAllComponents
(
'
.vue-ref
'
,
(
components
)
=>
{
components
.
forEach
(
component
=>
{
const
ref
=
component
.
data
.
vueRef
// 头条的组件 dataset 竟然是空的
const
ref
=
component
.
data
set
.
ref
vm
.
$refs
[
ref
]
=
component
.
$vm
||
component
})
})
mpInstance
.
selectAllComponents
(
'
.vue-ref-in-for
'
,
(
forComponents
)
=>
{
forComponents
.
forEach
(
component
=>
{
const
ref
=
component
.
data
.
vueR
ef
const
ref
=
component
.
data
set
.
r
ef
if
(
!
vm
.
$refs
[
ref
])
{
vm
.
$refs
[
ref
]
=
[]
}
...
...
@@ -40,32 +27,54 @@ export function initRefs (vm) {
})
}
export
function
triggerLink
(
mpInstance
)
{
const
nodeId
=
mpInstance
.
__nodeid__
+
''
const
instances
=
Object
.
create
(
null
)
export
function
initRelation
({
vuePid
,
mpInstance
})
{
// 头条 triggerEvent 后,接收事件时机特别晚,已经到了 ready 之后
const
nodeId
=
(
mpInstance
.
__nodeId__
||
mpInstance
.
__nodeid__
)
+
''
const
webviewId
=
mpInstance
.
__webviewId__
+
''
instances
[
webviewId
+
'
_
'
+
nodeId
]
=
mpInstance
.
$vm
mpInstance
.
triggerEvent
(
'
__l
'
,
{
this
.
triggerEvent
(
'
__l
'
,
{
vuePid
,
nodeId
,
webviewId
},
{
bubbles
:
true
,
composed
:
true
})
}
// TODO 目前有 bug,composed 不生效
export
function
handleLink
(
event
)
{
const
nodeId
=
event
.
detail
.
nodeId
const
webviewId
=
event
.
detail
.
webviewId
const
childVm
=
instances
[
webviewId
+
'
_
'
+
nodeId
]
export
function
handleLink
({
detail
:
{
vuePid
,
nodeId
,
webviewId
}
})
{
const
vm
=
instances
[
webviewId
+
'
_
'
+
nodeId
]
if
(
!
vm
)
{
return
}
if
(
childVm
)
{
childVm
.
$parent
=
this
.
$vm
childVm
.
$parent
.
$children
.
push
(
event
.
detail
)
let
parentVm
childVm
.
$root
=
this
.
$vm
.
$root
delete
instances
[
webviewId
+
'
_
'
+
nodeId
]
if
(
vuePid
)
{
parentVm
=
findVmByVueId
(
this
.
$vm
,
vuePid
)
}
if
(
!
parentVm
)
{
parentVm
=
this
.
$vm
}
vm
.
$parent
=
parentVm
vm
.
$root
=
parentVm
.
$root
parentVm
.
$children
.
push
(
vm
)
vm
.
__call_hook
(
'
created
'
)
vm
.
__call_hook
(
'
beforeMount
'
)
vm
.
_isMounted
=
true
vm
.
__call_hook
(
'
mounted
'
)
vm
.
__call_hook
(
'
onReady
'
)
}
src/platforms/mp-weixin/runtime/wrapper/app-base-parser.js
0 → 100644
浏览文件 @
5bef921d
此差异已折叠。
点击以展开。
src/platforms/mp-weixin/runtime/wrapper/app-parser.js
0 → 100644
浏览文件 @
5bef921d
import
parseBaseApp
from
'
./app-base-parser
'
import
{
mocks
,
initRefs
}
from
'
./util
'
export
default
function
parseApp
(
vm
)
{
return
parseBaseApp
(
vm
,
{
mocks
,
initRefs
})
}
src/platforms/mp-weixin/runtime/wrapper/component-base-parser.js
0 → 100644
浏览文件 @
5bef921d
此差异已折叠。
点击以展开。
src/platforms/mp-weixin/runtime/wrapper/component-parser.js
0 → 100644
浏览文件 @
5bef921d
import
parseBaseComponent
from
'
./component-base-parser
'
import
{
isPage
,
initRelation
}
from
'
./util
'
export
default
function
parseComponent
(
vueComponentOptions
)
{
return
parseBaseComponent
(
vueComponentOptions
,
{
isPage
,
initRelation
})
}
src/platforms/mp-weixin/runtime/wrapper/page-base-parser.js
0 → 100644
浏览文件 @
5bef921d
import
{
initHooks
,
PAGE_EVENT_HOOKS
}
from
'
uni-wrapper/util
'
import
parseComponent
from
'
uni-platform/runtime/wrapper/component-parser
'
const
hooks
=
[
'
onShow
'
,
'
onHide
'
,
'
onUnload
'
]
hooks
.
push
(...
PAGE_EVENT_HOOKS
)
export
default
function
parseBasePage
(
vuePageOptions
,
{
isPage
,
initRelation
})
{
const
pageOptions
=
parseComponent
(
vuePageOptions
,
{
isPage
,
initRelation
})
initHooks
(
pageOptions
.
methods
,
hooks
)
pageOptions
.
methods
.
onLoad
=
function
(
args
)
{
this
.
$vm
.
$mp
.
query
=
args
// 兼容 mpvue
this
.
$vm
.
__call_hook
(
'
onLoad
'
,
args
)
}
return
pageOptions
}
src/platforms/mp-weixin/runtime/wrapper/page-parser.js
0 → 100644
浏览文件 @
5bef921d
import
parseBasePage
from
'
./page-base-parser
'
import
{
isPage
,
initRelation
}
from
'
./util
'
export
default
function
parsePage
(
vuePageOptions
)
{
return
parseBasePage
(
vuePageOptions
,
{
isPage
,
initRelation
})
}
src/platforms/mp-weixin/runtime/wrapper/
index
.js
→
src/platforms/mp-weixin/runtime/wrapper/
util
.js
浏览文件 @
5bef921d
此差异已折叠。
点击以展开。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录