提交 39f98c73 编写于 作者: fxy060608's avatar fxy060608

build uni runtime(mp-alipay usingComponents)

上级 ac4bd265
......@@ -282,8 +282,7 @@ function initTriggerEvent (mpInstance) {
};
}
Page = function (options = {}) {
const name = 'onLoad';
function initHook (name, options) {
const oldHook = options[name];
if (!oldHook) {
options[name] = function () {
......@@ -295,22 +294,45 @@ Page = function (options = {}) {
return oldHook.apply(this, args)
};
}
}
Page = function (options = {}) {
initHook('onLoad', options);
return MPPage(options)
};
const behavior = Behavior({
created () {
initTriggerEvent(this);
}
});
Component = function (options = {}) {
(options.behaviors || (options.behaviors = [])).unshift(behavior);
initHook('created', options);
return MPComponent(options)
};
const mocks = ['__route__', '__wxExparserNodeId__', '__wxWebviewId__'];
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,
......@@ -334,18 +356,19 @@ function handleLink (event) {
}
function initPage$1 (pageOptions) {
initComponent$1(pageOptions);
return initComponent$1(pageOptions)
}
function initComponent$1 (componentOptions) {
componentOptions.methods.$getAppWebview = function () {
return plus.webview.getWebviewById(`${this.__wxWebviewId__}`)
};
return Component(componentOptions)
}
function initMocks (vm, mocks) {
function initMocks (vm, mocks$$1) {
const mpInstance = vm.$mp[vm.mpType];
mocks.forEach(mock => {
mocks$$1.forEach(mock => {
if (hasOwn(mpInstance, mock)) {
vm[mock] = mpInstance[mock];
}
......@@ -402,7 +425,7 @@ function createObserver (name) {
}
}
function getBehaviors (vueOptions) {
function getBehaviors (vueOptions) {
const vueBehaviors = vueOptions['behaviors'];
const vueExtends = vueOptions['extends'];
const vueMixins = vueOptions['mixins'];
......@@ -430,7 +453,7 @@ function getBehaviors (vueOptions) {
}
if (isPlainObject(vueExtends) && vueExtends.props) {
behaviors.push(
Behavior({
initBehavior({
properties: getProperties(vueExtends.props, true)
})
);
......@@ -439,7 +462,7 @@ function getBehaviors (vueOptions) {
vueMixins.forEach(vueMixin => {
if (isPlainObject(vueMixin) && vueMixin.props) {
behaviors.push(
Behavior({
initBehavior({
properties: getProperties(vueMixin.props, true)
})
);
......@@ -705,29 +728,6 @@ function handleEvent (event) {
});
}
});
}
function initRefs (vm) {
const mpInstance = vm.$mp[vm.mpType];
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 hooks = [
......@@ -750,24 +750,27 @@ function initVm (vm) {
}
function createApp (vm) {
// 外部初始化时 Vue 还未初始化,放到 createApp 内部初始化 mixin
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') {
{ // 头条的 selectComponent 竟然是异步的
initRefs(this);
}
initRefs(this);
initMocks(this, mocks);
}
},
......@@ -878,9 +881,7 @@ function createPage (vueOptions) {
initHooks(pageOptions.methods, hooks$1);
initPage$1(pageOptions);
return Component(pageOptions)
return initPage$1(pageOptions, vueOptions)
}
function initVm$2 (VueComponent) {
......@@ -888,16 +889,18 @@ function initVm$2 (VueComponent) {
return
}
const properties = this.properties;
const options = {
mpType: 'component',
mpInstance: this,
propsData: this.properties
propsData: properties
};
// 初始化 vue 实例
this.$vm = new VueComponent(options);
// 处理$slots,$scopedSlots(暂不支持动态变化$slots)
const vueSlots = this.properties.vueSlots;
const vueSlots = properties.vueSlots;
if (Array.isArray(vueSlots) && vueSlots.length) {
const $slots = Object.create(null);
vueSlots.forEach(slotName => {
......@@ -907,18 +910,24 @@ function initVm$2 (VueComponent) {
}
// 性能优先,mount 提前到 attached 中,保证组件首次渲染数据被合并
// 导致与标准 Vue 的差异,data 和 computed 中不能使用$parent,provide等组件属性
this.$vm.$mount();
this.$vm.$mount();
}
function createComponent (vueOptions) {
vueOptions = vueOptions.default || vueOptions;
let VueComponent;
if (isFn(vueOptions)) {
VueComponent = vueOptions; // TODO form-field props.name,props.value
vueOptions = VueComponent.extendOptions;
} else {
VueComponent = Vue.extend(vueOptions);
}
const behaviors = getBehaviors(vueOptions);
const properties = getProperties(vueOptions.props, false, vueOptions.__file);
const VueComponent = Vue.extend(vueOptions);
const componentOptions = {
options: {
multipleSlots: true,
......@@ -963,9 +972,7 @@ function createComponent (vueOptions) {
}
};
initComponent$1(componentOptions);
return Component(componentOptions)
return initComponent$1(componentOptions, vueOptions)
}
let uni = {};
......
{
"name": "@dcloudio/uni-app-plus",
"version": "0.0.229",
"version": "0.0.230",
"description": "uni-app app-plus",
"main": "dist/index.js",
"scripts": {
......
import Vue from 'vue';
const _toString = Object.prototype.toString;
const hasOwnProperty = Object.prototype.hasOwnProperty;
......@@ -15,9 +17,30 @@ function isPlainObject (obj) {
function hasOwn (obj, key) {
return hasOwnProperty.call(obj, key)
}
}
function noop () {}
/**
* Create a cached version of a pure function.
*/
function cached (fn) {
const cache = Object.create(null);
return function cachedFn (str) {
const hit = cache[str];
return hit || (cache[str] = fn(str))
}
}
/**
* Camelize a hyphen-delimited string.
*/
const camelizeRE = /-(\w)/g;
const camelize = cached((str) => {
return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : '')
});
const SYNC_API_RE = /hideKeyboard|upx2px|canIUse|^create|Sync$|Manager$/;
const SYNC_API_RE = /requireNativePlugin|upx2px|hideKeyboard|canIUse|^create|Sync$|Manager$/;
const CONTEXT_API_RE = /^create|Manager$/;
......@@ -42,10 +65,11 @@ function handlePromise (promise) {
}
function shouldPromise (name) {
if (isSyncApi(name)) {
return false
}
if (isCallbackApi(name)) {
if (
isContextApi(name) ||
isSyncApi(name) ||
isCallbackApi(name)
) {
return false
}
return true
......@@ -203,7 +227,7 @@ const protocols = { // 需要做转换的 API 列表
return res
},
request: {
name: 'httpRequest',
name: my.canIUse('request') ? 'request' : 'httpRequest',
args (fromArgs) {
if (!fromArgs.header) { // 默认增加 header 参数,方便格式化 content-type
fromArgs.header = {};
......@@ -461,6 +485,23 @@ const protocols = { // 需要做转换的 API 列表
},
getSystemInfoSync: {
returnValue: _handleSystemInfo
},
// 文档没提到,但是实测可用。
canvasToTempFilePath: {
returnValue (result) {
// 真机的情况下会有 tempFilePath 这个值,因此需要主动修改。
result.tempFilePath = result.apFilePath;
}
},
setScreenBrightness: {
args: {
value: 'brightness'
}
},
getScreenBrightness: {
returnValue: {
brightness: 'value'
}
}
};
......@@ -495,7 +536,7 @@ function processArgs (methodName, fromArgs, argsOption = {}, returnValue = {}, k
} else if (isPlainObject(keyOption)) { // {name:newName,value:value}可重新指定参数 key:value
toArgs[keyOption.name ? keyOption.name : key] = keyOption.value;
}
} else if (CALLBACKS.includes(key)) {
} else if (CALLBACKS.indexOf(key) !== -1) {
toArgs[key] = processCallback(methodName, fromArgs[key], returnValue);
} else {
if (!keepFromArgs) {
......@@ -646,6 +687,862 @@ var api = /*#__PURE__*/Object.freeze({
startGyroscope: startGyroscope
});
const isArray = Array.isArray;
const keyList = Object.keys;
function equal (a, b) {
if (a === b) return true
if (a && b && typeof a === 'object' && typeof b === 'object') {
const arrA = isArray(a);
const arrB = isArray(b);
let i, length, key;
if (arrA && arrB) {
length = a.length;
if (length !== b.length) return false
for (i = length; i-- !== 0;) {
if (!equal(a[i], b[i])) return false
}
return true
}
if (arrA !== arrB) return false
const dateA = a instanceof Date;
const dateB = b instanceof Date;
if (dateA !== dateB) return false
if (dateA && dateB) return a.getTime() === b.getTime()
const regexpA = a instanceof RegExp;
const regexpB = b instanceof RegExp;
if (regexpA !== regexpB) return false
if (regexpA && regexpB) return a.toString() === b.toString()
const keys = keyList(a);
length = keys.length;
if (length !== keyList(b).length) {
return false
}
for (i = length; i-- !== 0;) {
if (!hasOwn.call(b, keys[i])) return false
}
for (i = length; i-- !== 0;) {
key = keys[i];
if (!equal(a[key], b[key])) return false
}
return true
}
return false
}
const customizeRE = /:/g;
const customize = cached((str) => {
return camelize(str.replace(customizeRE, '-'))
});
const mocks = ['$id'];
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 initPage (pageOptions, vueOptions) {
const {
lifetimes,
methods
} = pageOptions;
pageOptions.onReady = lifetimes.ready;
pageOptions.onUnload = function () {
lifetimes.detached.call(this);
methods.onUnload.call(this);
};
Object.keys(methods).forEach(method => {
if (method !== 'onUnload') {
pageOptions[method] = methods[method];
}
});
pageOptions['__r'] = handleRef;
if (vueOptions.methods && vueOptions.methods.formReset) {
pageOptions['formReset'] = vueOptions.methods.formReset;
}
delete pageOptions.lifetimes;
delete pageOptions.methods;
return Page(pageOptions)
}
function triggerEvent (type, detail, options) {
const handler = this.props[customize('on-' + type)];
if (!handler) {
return
}
const eventOpts = this.props['data-event-opts'];
const target = {
dataset: {
eventOpts
}
};
handler({
type: customize(type),
target,
currentTarget: target,
detail
});
}
const IGNORES = ['$slots', '$scopedSlots'];
function createObserver (isDidUpdate) {
return function observe (props) {
const prevProps = isDidUpdate ? props : this.props;
const nextProps = isDidUpdate ? this.props : props;
if (equal(prevProps, nextProps)) {
return
}
Object.keys(prevProps).forEach(name => {
if (IGNORES.indexOf(name) === -1) {
const prevValue = prevProps[name];
const nextValue = nextProps[name];
if (!isFn(prevValue) && !isFn(nextValue) && !equal(prevValue, nextValue)) {
this.$vm[name] = nextProps[name];
}
}
});
}
}
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;
}
});
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;
}
componentOptions.methods['__r'] = handleRef;
componentOptions.methods.triggerEvent = triggerEvent;
delete componentOptions.properties;
delete componentOptions.behaviors;
delete componentOptions.lifetimes;
delete componentOptions.pageLifetimes;
return Component(componentOptions)
}
function initBehavior ({
properties
}) {
const props = {};
Object.keys(properties).forEach(key => {
props[key] = properties[key].value;
});
return {
props
}
}
function triggerLink (mpInstance, vueOptions) {
mpInstance.props.onTriggerLink(mpInstance.$vm || vueOptions);
}
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;
}
}
} else { // vueOptions
if (!detail.parent) {
detail.parent = this.$vm;
}
}
}
function initMocks (vm, mocks$$1) {
const mpInstance = vm.$mp[vm.mpType];
mocks$$1.forEach(mock => {
if (hasOwn(mpInstance, mock)) {
vm[mock] = mpInstance[mock];
}
});
}
function initHooks (mpOptions, hooks) {
hooks.forEach(hook => {
mpOptions[hook] = function (args) {
return this.$vm.__call_hook(hook, args)
};
});
}
function getData (vueOptions, context) {
let data = vueOptions.data || {};
const methods = vueOptions.methods || {};
if (typeof data === 'function') {
try {
data = data.call(context); // 支持 Vue.prototype 上挂的数据
} catch (e) {
if (process.env.VUE_APP_DEBUG) {
console.warn('根据 Vue 的 data 函数初始化小程序 data 失败,请尽量确保 data 函数中不访问 vm 对象,否则可能影响首次数据渲染速度。', data);
}
}
} else {
try {
// 对 data 格式化
data = JSON.parse(JSON.stringify(data));
} catch (e) {}
}
if (!isPlainObject(data)) {
data = {};
}
Object.keys(methods).forEach(methodName => {
if (context.__lifecycle_hooks__.indexOf(methodName) === -1 && !hasOwn(data, methodName)) {
data[methodName] = methods[methodName];
}
});
return data
}
const PROP_TYPES = [String, Number, Boolean, Object, Array, null];
function createObserver$1 (name) {
return function observer (newVal, oldVal) {
if (this.$vm) {
this.$vm[name] = newVal; // 为了触发其他非 render watcher
}
}
}
function getBehaviors (vueOptions) {
const vueBehaviors = vueOptions['behaviors'];
const vueExtends = vueOptions['extends'];
const vueMixins = vueOptions['mixins'];
let vueProps = vueOptions['props'];
if (!vueProps) {
vueOptions['props'] = vueProps = [];
}
const behaviors = [];
if (Array.isArray(vueBehaviors)) {
vueBehaviors.forEach(behavior => {
behaviors.push(behavior.replace('uni://', `${"my"}://`));
if (behavior === 'uni://form-field') {
if (Array.isArray(vueProps)) {
vueProps.push('name');
vueProps.push('value');
} else {
vueProps['name'] = String;
vueProps['value'] = null;
}
}
});
}
if (isPlainObject(vueExtends) && vueExtends.props) {
behaviors.push(
initBehavior({
properties: getProperties(vueExtends.props, true)
})
);
}
if (Array.isArray(vueMixins)) {
vueMixins.forEach(vueMixin => {
if (isPlainObject(vueMixin) && vueMixin.props) {
behaviors.push(
initBehavior({
properties: getProperties(vueMixin.props, true)
})
);
}
});
}
return behaviors
}
function parsePropType (key, type, defaultValue, file) {
// [String]=>String
if (Array.isArray(type) && type.length === 1) {
return type[0]
}
return type
}
function getProperties (props, isBehavior = false, file = '') {
const properties = {};
if (!isBehavior) {
properties.vueSlots = { // 小程序不能直接定义 $slots 的 props,所以通过 vueSlots 转换到 $slots
type: null,
value: [],
observer: function (newVal, oldVal) {
const $slots = Object.create(null);
newVal.forEach(slotName => {
$slots[slotName] = true;
});
this.setData({
$slots
});
}
};
}
if (Array.isArray(props)) { // ['title']
props.forEach(key => {
properties[key] = {
type: null,
observer: createObserver$1(key)
};
});
} else if (isPlainObject(props)) { // {title:{type:String,default:''},content:String}
Object.keys(props).forEach(key => {
const opts = props[key];
if (isPlainObject(opts)) { // title:{type:String,default:''}
let value = opts['default'];
if (isFn(value)) {
value = value();
}
opts.type = parsePropType(key, opts.type, value, file);
properties[key] = {
type: PROP_TYPES.indexOf(opts.type) !== -1 ? opts.type : null,
value,
observer: createObserver$1(key)
};
} else { // content:String
const type = parsePropType(key, opts, null, file);
properties[key] = {
type: PROP_TYPES.indexOf(type) !== -1 ? type : null,
observer: createObserver$1(key)
};
}
});
}
return properties
}
function wrapper$1 (event) {
// TODO 又得兼容 mpvue 的 mp 对象
try {
event.mp = JSON.parse(JSON.stringify(event));
} catch (e) {}
event.stopPropagation = noop;
event.preventDefault = noop;
event.target = event.target || {};
if (!hasOwn(event, 'detail')) {
event.detail = {};
}
if (isPlainObject(event.detail)) {
event.target = Object.assign({}, event.target, event.detail);
}
return event
}
function getExtraValue (vm, dataPathsArray) {
let context = vm;
dataPathsArray.forEach(dataPathArray => {
const dataPath = dataPathArray[0];
const value = dataPathArray[2];
if (dataPath || typeof value !== 'undefined') { // ['','',index,'disable']
const propPath = dataPathArray[1];
const valuePath = dataPathArray[3];
const vFor = dataPath ? vm.__get_value(dataPath, context) : context;
if (Number.isInteger(vFor)) {
context = value;
} else if (!propPath) {
context = vFor[value];
} else {
if (Array.isArray(vFor)) {
context = vFor.find(vForItem => {
return vm.__get_value(propPath, vForItem) === value
});
} else if (isPlainObject(vFor)) {
context = Object.keys(vFor).find(vForKey => {
return vm.__get_value(propPath, vFor[vForKey]) === value
});
} else {
console.error('v-for 暂不支持循环数据:', vFor);
}
}
if (valuePath) {
context = vm.__get_value(valuePath, context);
}
}
});
return context
}
function processEventExtra (vm, extra, event) {
const extraObj = {};
if (Array.isArray(extra) && extra.length) {
/**
*[
* ['data.items', 'data.id', item.data.id],
* ['metas', 'id', meta.id]
*],
*[
* ['data.items', 'data.id', item.data.id],
* ['metas', 'id', meta.id]
*],
*'test'
*/
extra.forEach((dataPath, index) => {
if (typeof dataPath === 'string') {
if (!dataPath) { // model,prop.sync
extraObj['$' + index] = vm;
} else {
if (dataPath === '$event') { // $event
extraObj['$' + index] = event;
} else if (dataPath.indexOf('$event.') === 0) { // $event.target.value
extraObj['$' + index] = vm.__get_value(dataPath.replace('$event.', ''), event);
} else {
extraObj['$' + index] = vm.__get_value(dataPath);
}
}
} else {
extraObj['$' + index] = getExtraValue(vm, dataPath);
}
});
}
return extraObj
}
function getObjByArray (arr) {
const obj = {};
for (let i = 1; i < arr.length; i++) {
const element = arr[i];
obj[element[0]] = element[1];
}
return obj
}
function processEventArgs (vm, event, args = [], extra = [], isCustom, methodName) {
let isCustomMPEvent = false; // wxcomponent 组件,传递原始 event 对象
if (isCustom) { // 自定义事件
isCustomMPEvent = event.currentTarget &&
event.currentTarget.dataset &&
event.currentTarget.dataset.comType === 'wx';
if (!args.length) { // 无参数,直接传入 event 或 detail 数组
if (isCustomMPEvent) {
return [event]
}
return event.detail.__args__ || event.detail
}
}
const extraObj = processEventExtra(vm, extra, event);
const ret = [];
args.forEach(arg => {
if (arg === '$event') {
if (methodName === '__set_model' && !isCustom) { // input v-model value
ret.push(event.target.value);
} else {
if (isCustom && !isCustomMPEvent) {
ret.push(event.detail.__args__[0]);
} else { // wxcomponent 组件或内置组件
ret.push(event);
}
}
} else {
if (Array.isArray(arg) && arg[0] === 'o') {
ret.push(getObjByArray(arg));
} else if (typeof arg === 'string' && hasOwn(extraObj, arg)) {
ret.push(extraObj[arg]);
} else {
ret.push(arg);
}
}
});
return ret
}
const ONCE = '~';
const CUSTOM = '^';
function handleEvent (event) {
event = wrapper$1(event);
// [['tap',[['handle',[1,2,a]],['handle1',[1,2,a]]]]]
const eventOpts = (event.currentTarget || event.target).dataset.eventOpts;
if (!eventOpts) {
return console.warn(`事件信息不存在`)
}
// [['handle',[1,2,a]],['handle1',[1,2,a]]]
const eventType = event.type;
eventOpts.forEach(eventOpt => {
let type = eventOpt[0];
const eventsArray = eventOpt[1];
const isCustom = type.charAt(0) === CUSTOM;
type = isCustom ? type.slice(1) : type;
const isOnce = type.charAt(0) === ONCE;
type = isOnce ? type.slice(1) : type;
if (eventsArray && eventType === type) {
eventsArray.forEach(eventArray => {
const methodName = eventArray[0];
if (methodName) {
const handler = this.$vm[methodName];
if (!isFn(handler)) {
throw new Error(` _vm.${methodName} is not a function`)
}
if (isOnce) {
if (handler.once) {
return
}
handler.once = true;
}
handler.apply(this.$vm, processEventArgs(
this.$vm,
event,
eventArray[1],
eventArray[2],
isCustom,
methodName
));
}
});
}
});
}
const hooks = [
'onHide',
'onError',
'onPageNotFound',
'onUniNViewMessage'
];
function initVm (vm) {
if (this.$vm) { // 百度竟然 onShow 在 onLaunch 之前?
return
}
this.$vm = vm;
this.$vm.$mp = {
app: this
};
}
function createApp (vm) {
// 外部初始化时 Vue 还未初始化,放到 createApp 内部初始化 mixin
{
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') {
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);
return vm
}
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
}
this.$vm = new VueComponent({
mpType: 'page',
mpInstance: this
});
this.$vm.__call_hook('created');
this.$vm.$mount();
}
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);
this.$vm.$mp.query = args; // 又要兼容 mpvue
this.$vm.__call_hook('onLoad', args); // 开发者可能会在 onLoad 时赋值,提前到 mount 之前
},
onUnload () {
this.$vm.__call_hook('onUnload');
},
__e: handleEvent,
__l: handleLink
}
};
initHooks(pageOptions.methods, hooks$1);
return initPage(pageOptions, vueOptions)
}
function initVm$2 (VueComponent) {
if (this.$vm) {
return
}
const properties = this.props;
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();
}
function createComponent (vueOptions) {
vueOptions = vueOptions.default || vueOptions;
let VueComponent;
if (isFn(vueOptions)) {
VueComponent = vueOptions; // TODO form-field props.name,props.value
vueOptions = VueComponent.extendOptions;
} 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$2.call(this, VueComponent);
},
ready () {
initVm$2.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 initComponent(componentOptions, vueOptions)
}
let uni = {};
if (typeof Proxy !== 'undefined') {
......@@ -656,12 +1553,14 @@ if (typeof Proxy !== 'undefined') {
}
if (api[name]) {
return promisify(name, api[name])
}
if (extraApi[name]) {
return promisify(name, extraApi[name])
}
if (todoApis[name]) {
return promisify(name, todoApis[name])
}
{
if (extraApi[name]) {
return promisify(name, extraApi[name])
}
if (todoApis[name]) {
return promisify(name, todoApis[name])
}
}
if (!hasOwn(my, name) && !hasOwn(protocols, name)) {
return
......@@ -672,13 +1571,14 @@ if (typeof Proxy !== 'undefined') {
} else {
uni.upx2px = upx2px;
Object.keys(todoApis).forEach(name => {
uni[name] = promisify(name, todoApis[name]);
});
Object.keys(extraApi).forEach(name => {
uni[name] = promisify(name, todoApis[name]);
});
{
Object.keys(todoApis).forEach(name => {
uni[name] = promisify(name, todoApis[name]);
});
Object.keys(extraApi).forEach(name => {
uni[name] = promisify(name, todoApis[name]);
});
}
Object.keys(api).forEach(name => {
uni[name] = promisify(name, api[name]);
......@@ -694,3 +1594,4 @@ if (typeof Proxy !== 'undefined') {
var uni$1 = uni;
export default uni$1;
export { createApp, createPage, createComponent };
{
"name": "@dcloudio/uni-mp-alipay",
"version": "0.0.8",
"version": "0.0.801",
"description": "uni-app mp-alipay",
"main": "dist/index.js",
"scripts": {
......
......@@ -417,8 +417,7 @@ function initTriggerEvent (mpInstance) {
};
}
Page = function (options = {}) {
const name = 'onLoad';
function initHook (name, options) {
const oldHook = options[name];
if (!oldHook) {
options[name] = function () {
......@@ -430,37 +429,62 @@ Page = function (options = {}) {
return oldHook.apply(this, args)
};
}
}
Page = function (options = {}) {
initHook('onLoad', options);
return MPPage(options)
};
const behavior = Behavior({
created () {
initTriggerEvent(this);
}
});
Component = function (options = {}) {
(options.behaviors || (options.behaviors = [])).unshift(behavior);
initHook('created', options);
return MPComponent(options)
};
const mocks = ['nodeId'];
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 (pageOptions) {
initComponent(pageOptions);
function initPage$1 (pageOptions) {
return initComponent$1(pageOptions)
}
function initComponent (componentOptions) {
function initComponent$1 (componentOptions) {
componentOptions.messages = {
'__l': handleLink
'__l': handleLink$1
};
return Component(componentOptions)
}
function triggerLink (mpInstance, vueOptions) {
function triggerLink$1 (mpInstance, vueOptions) {
mpInstance.dispatch('__l', mpInstance.$vm || vueOptions);
}
function handleLink (event) {
function handleLink$1 (event) {
const target = event.value;
if (target.$mp) {
if (!target.$parent) {
......@@ -535,7 +559,7 @@ function createObserver (name) {
}
}
function getBehaviors (vueOptions) {
function getBehaviors (vueOptions) {
const vueBehaviors = vueOptions['behaviors'];
const vueExtends = vueOptions['extends'];
const vueMixins = vueOptions['mixins'];
......@@ -563,7 +587,7 @@ function getBehaviors (vueOptions) {
}
if (isPlainObject(vueExtends) && vueExtends.props) {
behaviors.push(
Behavior({
initBehavior({
properties: getProperties(vueExtends.props, true)
})
);
......@@ -572,7 +596,7 @@ function getBehaviors (vueOptions) {
vueMixins.forEach(vueMixin => {
if (isPlainObject(vueMixin) && vueMixin.props) {
behaviors.push(
Behavior({
initBehavior({
properties: getProperties(vueMixin.props, true)
})
);
......@@ -866,29 +890,6 @@ function handleEvent (event) {
});
}
function initRefs (vm) {
const mpInstance = vm.$mp[vm.mpType];
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 baiduComponentDestroy ($vm) {
$vm.$children.forEach(childVm => {
childVm.$mp.component.detached();
......@@ -923,25 +924,28 @@ function initVm (vm) {
}
function createApp (vm) {
// 外部初始化时 Vue 还未初始化,放到 createApp 内部初始化 mixin
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') {
{ // 头条的 selectComponent 竟然是异步的
initRefs(this);
}
initMocks(this, mocks);
initRefs(this);
initMocks(this, mocks$1);
}
},
created () { // 处理 injections
......@@ -1055,15 +1059,13 @@ function createPage (vueOptions) {
}
},
__e: handleEvent,
__l: handleLink
__l: handleLink$1
}
};
initHooks(pageOptions.methods, hooks$1);
initPage(pageOptions);
return Component(pageOptions)
return initPage$1(pageOptions, vueOptions)
}
function initVm$2 (VueComponent) {
......@@ -1071,16 +1073,18 @@ function initVm$2 (VueComponent) {
return
}
const properties = this.properties;
const options = {
mpType: 'component',
mpInstance: this,
propsData: this.properties
propsData: properties
};
// 初始化 vue 实例
this.$vm = new VueComponent(options);
// 处理$slots,$scopedSlots(暂不支持动态变化$slots)
const vueSlots = this.properties.vueSlots;
const vueSlots = properties.vueSlots;
if (Array.isArray(vueSlots) && vueSlots.length) {
const $slots = Object.create(null);
vueSlots.forEach(slotName => {
......@@ -1090,18 +1094,24 @@ function initVm$2 (VueComponent) {
}
// 性能优先,mount 提前到 attached 中,保证组件首次渲染数据被合并
// 导致与标准 Vue 的差异,data 和 computed 中不能使用$parent,provide等组件属性
this.$vm.$mount();
this.$vm.$mount();
}
function createComponent (vueOptions) {
vueOptions = vueOptions.default || vueOptions;
let VueComponent;
if (isFn(vueOptions)) {
VueComponent = vueOptions; // TODO form-field props.name,props.value
vueOptions = VueComponent.extendOptions;
} else {
VueComponent = Vue.extend(vueOptions);
}
const behaviors = getBehaviors(vueOptions);
const properties = getProperties(vueOptions.props, false, vueOptions.__file);
const VueComponent = Vue.extend(vueOptions);
const componentOptions = {
options: {
multipleSlots: true,
......@@ -1116,7 +1126,7 @@ function createComponent (vueOptions) {
},
ready () {
initVm$2.call(this, VueComponent); // 目前发现部分情况小程序 attached 不触发
triggerLink(this); // 处理 parent,children
triggerLink$1(this); // 处理 parent,children
// 补充生命周期
this.$vm.__call_hook('created');
......@@ -1142,13 +1152,11 @@ function createComponent (vueOptions) {
},
methods: {
__e: handleEvent,
__l: handleLink
__l: handleLink$1
}
};
initComponent(componentOptions);
return Component(componentOptions)
return initComponent$1(componentOptions, vueOptions)
}
let uni = {};
......
{
"name": "@dcloudio/uni-mp-baidu",
"version": "0.0.826",
"version": "0.0.827",
"description": "uni-app mp-baidu",
"main": "dist/index.js",
"scripts": {
......
......@@ -462,8 +462,7 @@ function initTriggerEvent (mpInstance) {
};
}
Page = function (options = {}) {
const name = 'onLoad';
function initHook (name, options) {
const oldHook = options[name];
if (!oldHook) {
options[name] = function () {
......@@ -475,62 +474,60 @@ Page = function (options = {}) {
return oldHook.apply(this, args)
};
}
}
Page = function (options = {}) {
initHook('onLoad', options);
return MPPage(options)
};
const behavior = Behavior({
created () {
initTriggerEvent(this);
}
});
Component = function (options = {}) {
(options.behaviors || (options.behaviors = [])).unshift(behavior);
initHook('created', options);
return MPComponent(options)
};
function initBehavior (options) {
return Behavior(options)
}
const instances = Object.create(null);
const mocks = ['__route__', '__webviewId__', '__nodeid__'];
const mocks$1 = ['__route__', '__webviewId__', '__nodeid__'];
function initPage (pageOptions) {
initComponent(pageOptions);
function initPage$1 (pageOptions) {
return initComponent$1(pageOptions)
}
function initComponent (componentOptions) {
function initComponent$1 (componentOptions) {
if (componentOptions.properties) { // ref
componentOptions.properties.vueRef = {
type: String,
value: ''
};
}
const oldAttached = componentOptions.lifetimes.attached;
componentOptions.lifetimes.attached = function () {
oldAttached.call(this);
// TODO 需要处理动态变化后的 refs
initRefs.call(this);
};
return Component(componentOptions)
}
function initRefs () {
this.selectAllComponents('.vue-ref', (components) => {
function initRefs$1 (vm) {
const mpInstance = vm.$scope;
mpInstance.selectAllComponents('.vue-ref', (components) => {
components.forEach(component => {
const ref = component.data.vueRef; // 头条的组件 dataset 竟然是空的
this.$vm.$refs[ref] = component.$vm || component;
vm.$refs[ref] = component.$vm || component;
});
});
this.selectAllComponents('.vue-ref-in-for', (forComponents) => {
mpInstance.selectAllComponents('.vue-ref-in-for', (forComponents) => {
forComponents.forEach(component => {
const ref = component.data.vueRef;
if (!this.$vm.$refs[ref]) {
this.$vm.$refs[ref] = [];
if (!vm.$refs[ref]) {
vm.$refs[ref] = [];
}
this.$vm.$refs[ref].push(component.$vm || component);
vm.$refs[ref].push(component.$vm || component);
});
});
}
function triggerLink (mpInstance) {
function triggerLink$1 (mpInstance) {
const nodeId = mpInstance.__nodeid__ + '';
const webviewId = mpInstance.__webviewId__ + '';
......@@ -545,7 +542,7 @@ function triggerLink (mpInstance) {
});
}
// TODO 目前有 bug,composed 不生效
function handleLink (event) {
function handleLink$1 (event) {
const nodeId = event.detail.nodeId;
const webviewId = event.detail.webviewId;
......@@ -619,7 +616,7 @@ function createObserver (name) {
}
}
function getBehaviors (vueOptions) {
function getBehaviors (vueOptions) {
const vueBehaviors = vueOptions['behaviors'];
const vueExtends = vueOptions['extends'];
const vueMixins = vueOptions['mixins'];
......@@ -647,7 +644,7 @@ function getBehaviors (vueOptions) {
}
if (isPlainObject(vueExtends) && vueExtends.props) {
behaviors.push(
Behavior({
initBehavior({
properties: getProperties(vueExtends.props, true)
})
);
......@@ -656,7 +653,7 @@ function getBehaviors (vueOptions) {
vueMixins.forEach(vueMixin => {
if (isPlainObject(vueMixin) && vueMixin.props) {
behaviors.push(
Behavior({
initBehavior({
properties: getProperties(vueMixin.props, true)
})
);
......@@ -944,22 +941,28 @@ function initVm (vm) {
}
function createApp (vm) {
// 外部初始化时 Vue 还未初始化,放到 createApp 内部初始化 mixin
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') {
initMocks(this, mocks);
initRefs$1(this);
initMocks(this, mocks$1);
}
},
created () { // 处理 injections
......@@ -1063,15 +1066,13 @@ function createPage (vueOptions) {
this.$vm.__call_hook('onUnload');
},
__e: handleEvent,
__l: handleLink
__l: handleLink$1
}
};
initHooks(pageOptions.methods, hooks$1);
initPage(pageOptions);
return Component(pageOptions)
return initPage$1(pageOptions, vueOptions)
}
function initVm$2 (VueComponent) {
......@@ -1079,16 +1080,18 @@ function initVm$2 (VueComponent) {
return
}
const properties = this.properties;
const options = {
mpType: 'component',
mpInstance: this,
propsData: this.properties
propsData: properties
};
// 初始化 vue 实例
this.$vm = new VueComponent(options);
// 处理$slots,$scopedSlots(暂不支持动态变化$slots)
const vueSlots = this.properties.vueSlots;
const vueSlots = properties.vueSlots;
if (Array.isArray(vueSlots) && vueSlots.length) {
const $slots = Object.create(null);
vueSlots.forEach(slotName => {
......@@ -1098,18 +1101,24 @@ function initVm$2 (VueComponent) {
}
// 性能优先,mount 提前到 attached 中,保证组件首次渲染数据被合并
// 导致与标准 Vue 的差异,data 和 computed 中不能使用$parent,provide等组件属性
this.$vm.$mount();
this.$vm.$mount();
}
function createComponent (vueOptions) {
vueOptions = vueOptions.default || vueOptions;
let VueComponent;
if (isFn(vueOptions)) {
VueComponent = vueOptions; // TODO form-field props.name,props.value
vueOptions = VueComponent.extendOptions;
} else {
VueComponent = Vue.extend(vueOptions);
}
const behaviors = getBehaviors(vueOptions);
const properties = getProperties(vueOptions.props, false, vueOptions.__file);
const VueComponent = Vue.extend(vueOptions);
const componentOptions = {
options: {
multipleSlots: true,
......@@ -1124,7 +1133,7 @@ function createComponent (vueOptions) {
},
ready () {
initVm$2.call(this, VueComponent); // 目前发现部分情况小程序 attached 不触发
triggerLink(this); // 处理 parent,children
triggerLink$1(this); // 处理 parent,children
// 补充生命周期
this.$vm.__call_hook('created');
......@@ -1150,13 +1159,11 @@ function createComponent (vueOptions) {
},
methods: {
__e: handleEvent,
__l: handleLink
__l: handleLink$1
}
};
initComponent(componentOptions);
return Component(componentOptions)
return initComponent$1(componentOptions, vueOptions)
}
let uni = {};
......
{
"name": "@dcloudio/uni-mp-toutiao",
"version": "0.0.324",
"version": "0.0.325",
"description": "uni-app mp-toutiao",
"main": "dist/index.js",
"scripts": {
......
......@@ -309,8 +309,7 @@ function initTriggerEvent (mpInstance) {
};
}
Page = function (options = {}) {
const name = 'onLoad';
function initHook (name, options) {
const oldHook = options[name];
if (!oldHook) {
options[name] = function () {
......@@ -322,22 +321,53 @@ Page = function (options = {}) {
return oldHook.apply(this, args)
};
}
}
Page = function (options = {}) {
initHook('onLoad', options);
return MPPage(options)
};
const behavior = Behavior({
created () {
initTriggerEvent(this);
}
});
Component = function (options = {}) {
(options.behaviors || (options.behaviors = [])).unshift(behavior);
initHook('created', 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,
......@@ -360,9 +390,9 @@ function handleLink (event) {
}
}
function initMocks (vm, mocks) {
function initMocks (vm, mocks$$1) {
const mpInstance = vm.$mp[vm.mpType];
mocks.forEach(mock => {
mocks$$1.forEach(mock => {
if (hasOwn(mpInstance, mock)) {
vm[mock] = mpInstance[mock];
}
......@@ -419,7 +449,7 @@ function createObserver (name) {
}
}
function getBehaviors (vueOptions) {
function getBehaviors (vueOptions) {
const vueBehaviors = vueOptions['behaviors'];
const vueExtends = vueOptions['extends'];
const vueMixins = vueOptions['mixins'];
......@@ -447,7 +477,7 @@ function getBehaviors (vueOptions) {
}
if (isPlainObject(vueExtends) && vueExtends.props) {
behaviors.push(
Behavior({
initBehavior({
properties: getProperties(vueExtends.props, true)
})
);
......@@ -456,7 +486,7 @@ function getBehaviors (vueOptions) {
vueMixins.forEach(vueMixin => {
if (isPlainObject(vueMixin) && vueMixin.props) {
behaviors.push(
Behavior({
initBehavior({
properties: getProperties(vueMixin.props, true)
})
);
......@@ -722,29 +752,6 @@ function handleEvent (event) {
});
}
});
}
function initRefs (vm) {
const mpInstance = vm.$mp[vm.mpType];
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 hooks = [
......@@ -772,24 +779,27 @@ function initVm (vm) {
}
function createApp (vm) {
// 外部初始化时 Vue 还未初始化,放到 createApp 内部初始化 mixin
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') {
{ // 头条的 selectComponent 竟然是异步的
initRefs(this);
}
initRefs(this);
initMocks(this, mocks);
}
},
......@@ -900,7 +910,7 @@ function createPage (vueOptions) {
initHooks(pageOptions.methods, hooks$1);
return Component(pageOptions)
return initPage(pageOptions, vueOptions)
}
function initVm$2 (VueComponent) {
......@@ -908,16 +918,18 @@ function initVm$2 (VueComponent) {
return
}
const properties = this.properties;
const options = {
mpType: 'component',
mpInstance: this,
propsData: this.properties
propsData: properties
};
// 初始化 vue 实例
this.$vm = new VueComponent(options);
// 处理$slots,$scopedSlots(暂不支持动态变化$slots)
const vueSlots = this.properties.vueSlots;
const vueSlots = properties.vueSlots;
if (Array.isArray(vueSlots) && vueSlots.length) {
const $slots = Object.create(null);
vueSlots.forEach(slotName => {
......@@ -927,18 +939,24 @@ function initVm$2 (VueComponent) {
}
// 性能优先,mount 提前到 attached 中,保证组件首次渲染数据被合并
// 导致与标准 Vue 的差异,data 和 computed 中不能使用$parent,provide等组件属性
this.$vm.$mount();
this.$vm.$mount();
}
function createComponent (vueOptions) {
vueOptions = vueOptions.default || vueOptions;
let VueComponent;
if (isFn(vueOptions)) {
VueComponent = vueOptions; // TODO form-field props.name,props.value
vueOptions = VueComponent.extendOptions;
} else {
VueComponent = Vue.extend(vueOptions);
}
const behaviors = getBehaviors(vueOptions);
const properties = getProperties(vueOptions.props, false, vueOptions.__file);
const VueComponent = Vue.extend(vueOptions);
const componentOptions = {
options: {
multipleSlots: true,
......@@ -983,7 +1001,7 @@ function createComponent (vueOptions) {
}
};
return Component(componentOptions)
return initComponent(componentOptions, vueOptions)
}
let uni = {};
......
{
"name": "@dcloudio/uni-mp-weixin",
"version": "0.0.948",
"version": "0.0.949",
"description": "uni-app mp-weixin",
"main": "dist/index.js",
"scripts": {
......
import 'uni-platform/runtime/index'
import Vue from 'vue'
import {
mocks
} from 'uni-platform/runtime/wrapper/index'
import {
initRefs,
mocks,
initRefs
} from 'uni-platform/runtime/wrapper/index'
import {
initHooks,
initMocks
} from './util'
......@@ -38,23 +38,45 @@ function initVm (vm) {
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') {
if (__PLATFORM__ !== 'mp-toutiao') { // 头条的 selectComponent 竟然是异步的
initRefs(this)
}
initRefs(this)
initMocks(this, mocks)
}
},
......
import Vue from 'vue'
import {
isFn
} from 'uni-shared'
import {
handleLink,
triggerLink,
......@@ -18,16 +22,20 @@ function initVm (VueComponent) {
return
}
const properties = __PLATFORM__ === 'mp-alipay'
? this.props
: this.properties
const options = {
mpType: 'component',
mpInstance: this,
propsData: this.properties
propsData: properties
}
// 初始化 vue 实例
this.$vm = new VueComponent(options)
// 处理$slots,$scopedSlots(暂不支持动态变化$slots)
const vueSlots = this.properties.vueSlots
const vueSlots = properties.vueSlots
if (Array.isArray(vueSlots) && vueSlots.length) {
const $slots = Object.create(null)
vueSlots.forEach(slotName => {
......@@ -37,18 +45,24 @@ function initVm (VueComponent) {
}
// 性能优先,mount 提前到 attached 中,保证组件首次渲染数据被合并
// 导致与标准 Vue 的差异,data 和 computed 中不能使用$parent,provide等组件属性
this.$vm.$mount()
this.$vm.$mount()
}
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
} else {
VueComponent = Vue.extend(vueOptions)
}
const behaviors = getBehaviors(vueOptions)
const properties = getProperties(vueOptions.props, false, vueOptions.__file)
const VueComponent = Vue.extend(vueOptions)
const componentOptions = {
options: {
multipleSlots: true,
......@@ -93,7 +107,5 @@ export function createComponent (vueOptions) {
}
}
initComponent(componentOptions)
return Component(componentOptions)
return initComponent(componentOptions, vueOptions)
}
......@@ -101,7 +101,5 @@ export function createPage (vueOptions) {
initHooks(pageOptions.methods, hooks)
initPage(pageOptions)
return Component(pageOptions)
return initPage(pageOptions, vueOptions)
}
......@@ -5,6 +5,10 @@ import {
isPlainObject
} from 'uni-shared'
import {
initBehavior
} from 'uni-platform/runtime/wrapper/index'
export function initMocks (vm, mocks) {
const mpInstance = vm.$mp[vm.mpType]
mocks.forEach(mock => {
......@@ -64,7 +68,7 @@ function createObserver (name) {
}
}
export function getBehaviors (vueOptions) {
export function getBehaviors (vueOptions) {
const vueBehaviors = vueOptions['behaviors']
const vueExtends = vueOptions['extends']
const vueMixins = vueOptions['mixins']
......@@ -92,7 +96,7 @@ export function getBehaviors (vueOptions) {
}
if (isPlainObject(vueExtends) && vueExtends.props) {
behaviors.push(
Behavior({
initBehavior({
properties: getProperties(vueExtends.props, true)
})
)
......@@ -101,7 +105,7 @@ export function getBehaviors (vueOptions) {
vueMixins.forEach(vueMixin => {
if (isPlainObject(vueMixin) && vueMixin.props) {
behaviors.push(
Behavior({
initBehavior({
properties: getProperties(vueMixin.props, true)
})
)
......@@ -395,29 +399,6 @@ export function handleEvent (event) {
})
}
export function initRefs (vm) {
const mpInstance = vm.$mp[vm.mpType]
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 baiduComponentDestroy ($vm) {
$vm.$children.forEach(childVm => {
childVm.$mp.component.detached()
......
export {
mocks,
initRefs,
handleLink,
triggerLink
triggerLink,
initBehavior
}
from '../../../mp-weixin/runtime/wrapper/index'
export function initPage (pageOptions) {
initComponent(pageOptions)
return initComponent(pageOptions)
}
export function initComponent (componentOptions) {
componentOptions.methods.$getAppWebview = function () {
return plus.webview.getWebviewById(`${this.__wxWebviewId__}`)
}
return Component(componentOptions)
}
import {
hasOwn
} from 'uni-shared'
const isArray = Array.isArray
const keyList = Object.keys
export default function equal (a, b) {
if (a === b) return true
if (a && b && typeof a === 'object' && typeof b === 'object') {
const arrA = isArray(a)
const arrB = isArray(b)
let i, length, key
if (arrA && arrB) {
length = a.length
if (length !== b.length) return false
for (i = length; i-- !== 0;) {
if (!equal(a[i], b[i])) return false
}
return true
}
if (arrA !== arrB) return false
const dateA = a instanceof Date
const dateB = b instanceof Date
if (dateA !== dateB) return false
if (dateA && dateB) return a.getTime() === b.getTime()
const regexpA = a instanceof RegExp
const regexpB = b instanceof RegExp
if (regexpA !== regexpB) return false
if (regexpA && regexpB) return a.toString() === b.toString()
const keys = keyList(a)
length = keys.length
if (length !== keyList(b).length) {
return false
}
for (i = length; i-- !== 0;) {
if (!hasOwn.call(b, keys[i])) return false
}
for (i = length; i-- !== 0;) {
key = keys[i]
if (!equal(a[key], b[key])) return false
}
return true
}
return false
}
import {
isFn,
cached,
camelize
} from 'uni-shared'
import deepEqual from './deep-equal'
const customizeRE = /:/g
const customize = cached((str) => {
return camelize(str.replace(customizeRE, '-'))
})
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 initPage (pageOptions, vueOptions) {
const {
lifetimes,
methods
} = pageOptions
pageOptions.onReady = lifetimes.ready
pageOptions.onUnload = function () {
lifetimes.detached.call(this)
methods.onUnload.call(this)
}
Object.keys(methods).forEach(method => {
if (method !== 'onUnload') {
pageOptions[method] = methods[method]
}
})
pageOptions['__r'] = handleRef
if (vueOptions.methods && vueOptions.methods.formReset) {
pageOptions['formReset'] = vueOptions.methods.formReset
}
delete pageOptions.lifetimes
delete pageOptions.methods
return Page(pageOptions)
}
function triggerEvent (type, detail, options) {
const handler = this.props[customize('on-' + type)]
if (!handler) {
return
}
const eventOpts = this.props['data-event-opts']
const target = {
dataset: {
eventOpts
}
}
handler({
type: customize(type),
target,
currentTarget: target,
detail
})
}
const IGNORES = ['$slots', '$scopedSlots']
function createObserver (isDidUpdate) {
return function observe (props) {
const prevProps = isDidUpdate ? props : this.props
const nextProps = isDidUpdate ? this.props : props
if (deepEqual(prevProps, nextProps)) {
return
}
Object.keys(prevProps).forEach(name => {
if (IGNORES.indexOf(name) === -1) {
const prevValue = prevProps[name]
const nextValue = nextProps[name]
if (!isFn(prevValue) && !isFn(nextValue) && !deepEqual(prevValue, nextValue)) {
this.$vm[name] = nextProps[name]
}
}
})
}
}
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
}
})
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
}
componentOptions.methods['__r'] = handleRef
componentOptions.methods.triggerEvent = triggerEvent
delete componentOptions.properties
delete componentOptions.behaviors
delete componentOptions.lifetimes
delete componentOptions.pageLifetimes
return Component(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
}
}
} else { // vueOptions
if (!detail.parent) {
detail.parent = this.$vm
}
}
}
export {
initRefs,
initBehavior
}
from '../../../mp-weixin/runtime/wrapper/index'
export const mocks = ['nodeId']
export function initPage (pageOptions) {
initComponent(pageOptions)
return initComponent(pageOptions)
}
export function initComponent (componentOptions) {
componentOptions.messages = {
'__l': handleLink
}
return Component(componentOptions)
}
export function triggerLink (mpInstance, vueOptions) {
......
export {
initBehavior
}
from '../../../mp-weixin/runtime/wrapper/index'
const instances = Object.create(null)
export const mocks = ['__route__', '__webviewId__', '__nodeid__']
export function initPage (pageOptions) {
initComponent(pageOptions)
return initComponent(pageOptions)
}
export function initComponent (componentOptions) {
......@@ -13,28 +18,24 @@ export function initComponent (componentOptions) {
value: ''
}
}
const oldAttached = componentOptions.lifetimes.attached
componentOptions.lifetimes.attached = function () {
oldAttached.call(this)
// TODO 需要处理动态变化后的 refs
initRefs.call(this)
}
return Component(componentOptions)
}
function initRefs () {
this.selectAllComponents('.vue-ref', (components) => {
export function initRefs (vm) {
const mpInstance = vm.$scope
mpInstance.selectAllComponents('.vue-ref', (components) => {
components.forEach(component => {
const ref = component.data.vueRef // 头条的组件 dataset 竟然是空的
this.$vm.$refs[ref] = component.$vm || component
vm.$refs[ref] = component.$vm || component
})
})
this.selectAllComponents('.vue-ref-in-for', (forComponents) => {
mpInstance.selectAllComponents('.vue-ref-in-for', (forComponents) => {
forComponents.forEach(component => {
const ref = component.data.vueRef
if (!this.$vm.$refs[ref]) {
this.$vm.$refs[ref] = []
if (!vm.$refs[ref]) {
vm.$refs[ref] = []
}
this.$vm.$refs[ref].push(component.$vm || component)
vm.$refs[ref].push(component.$vm || component)
})
})
}
......
......@@ -24,8 +24,7 @@ function initTriggerEvent (mpInstance) {
}
}
Page = function (options = {}) {
const name = 'onLoad'
function initHook (name, options) {
const oldHook = options[name]
if (!oldHook) {
options[name] = function () {
......@@ -37,16 +36,14 @@ Page = function (options = {}) {
return oldHook.apply(this, args)
}
}
return MPPage(options)
}
const behavior = Behavior({
created () {
initTriggerEvent(this)
}
})
Page = function (options = {}) {
initHook('onLoad', options)
return MPPage(options)
}
Component = function (options = {}) {
(options.behaviors || (options.behaviors = [])).unshift(behavior)
initHook('created', options)
return MPComponent(options)
}
export const mocks = ['__route__', '__wxExparserNodeId__', '__wxWebviewId__']
export function initPage () {
export function initPage (pageOptions) {
return initComponent(pageOptions)
}
export function initComponent () {
export function initComponent (componentOptions) {
return Component(componentOptions)
}
export function initBehavior (options) {
return Behavior(options)
}
export 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
}
})
}
export function triggerLink (mpInstance, vueOptions) {
mpInstance.triggerEvent('__l', mpInstance.$vm || vueOptions, {
bubbles: true,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册