提交 aae4ab63 编写于 作者: X xiaoyucoding

Merge branch 'dev'

......@@ -41,6 +41,7 @@ module.exports = {
replace({
__GLOBAL__: platform.prefix,
__PLATFORM_TITLE__: platform.title,
__PLATFORM_PREFIX__: JSON.stringify(platform.prefix),
__PLATFORM__: JSON.stringify(process.env.UNI_PLATFORM)
})
],
......
......@@ -76,7 +76,8 @@
"__PLATFORM__": true,
"__VERSION__": true,
"__GLOBAL__": true,
"__PLATFORM_TITLE__": true
"__PLATFORM_TITLE__": true,
"__PLATFORM_PREFIX__":true
},
"rules": {
"no-tabs": 0,
......
......@@ -173,7 +173,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) {
......@@ -309,11 +309,43 @@ Component = function (options = {}) {
return MPComponent(options)
};
const MOCKS = ['__route__', '__wxExparserNodeId__', '__wxWebviewId__', '__webviewId__'];
const mocks = ['__route__', '__wxExparserNodeId__', '__wxWebviewId__'];
function initMocks (vm) {
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;
}
}
}
function initPage$1 (pageOptions) {
initComponent$1(pageOptions);
}
function initComponent$1 (componentOptions) {
componentOptions.methods.$getAppWebview = function () {
return plus.webview.getWebviewById(`${this.__wxWebviewId__}`)
};
}
function initMocks (vm, mocks) {
const mpInstance = vm.$mp[vm.mpType];
MOCKS.forEach(mock => {
mocks.forEach(mock => {
if (hasOwn(mpInstance, mock)) {
vm[mock] = mpInstance[mock];
}
......@@ -347,6 +379,10 @@ function getData (vueOptions, context) {
} 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];
......@@ -366,9 +402,65 @@ function createObserver (name) {
}
}
function getProperties (props) {
const properties = {
vueSlots: { // 小程序不能直接定义 $slots 的 props,所以通过 vueSlots 转换到 $slots
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://', `${"wx"}://`));
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(
Behavior({
properties: getProperties(vueExtends.props, true)
})
);
}
if (Array.isArray(vueMixins)) {
vueMixins.forEach(vueMixin => {
if (isPlainObject(vueMixin) && vueMixin.props) {
behaviors.push(
Behavior({
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) {
......@@ -380,8 +472,8 @@ function getProperties (props) {
$slots
});
}
}
};
};
}
if (Array.isArray(props)) { // ['title']
props.forEach(key => {
properties[key] = {
......@@ -397,14 +489,18 @@ function getProperties (props) {
if (isFn(value)) {
value = value();
}
opts.type = parsePropType(key, opts.type, value, file);
properties[key] = {
type: PROP_TYPES.includes(opts.type) ? opts.type : null,
type: PROP_TYPES.indexOf(opts.type) !== -1 ? opts.type : null,
value,
observer: createObserver(key)
};
} else { // content:String
const type = parsePropType(key, opts, null, file);
properties[key] = {
type: PROP_TYPES.includes(opts) ? opts : null,
type: PROP_TYPES.indexOf(type) !== -1 ? type : null,
observer: createObserver(key)
};
}
......@@ -414,6 +510,11 @@ function getProperties (props) {
}
function wrapper$1 (event) {
// TODO 又得兼容 mpvue 的 mp 对象
try {
event.mp = JSON.parse(JSON.stringify(event));
} catch (e) {}
event.stopPropagation = noop;
event.preventDefault = noop;
......@@ -423,9 +524,6 @@ function wrapper$1 (event) {
event.detail = {};
}
// TODO 又得兼容 mpvue 的 mp 对象
event.mp = event;
if (isPlainObject(event.detail)) {
event.target = Object.assign({}, event.target, event.detail);
}
......@@ -470,7 +568,7 @@ function getExtraValue (vm, dataPathsArray) {
return context
}
function processEventExtra (vm, extra) {
function processEventExtra (vm, extra, event) {
const extraObj = {};
if (Array.isArray(extra) && extra.length) {
......@@ -490,7 +588,13 @@ function processEventExtra (vm, extra) {
if (!dataPath) { // model,prop.sync
extraObj['$' + index] = vm;
} else {
extraObj['$' + index] = vm.__get_value(dataPath);
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);
......@@ -501,6 +605,15 @@ function processEventExtra (vm, extra) {
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) { // 自定义事件
......@@ -515,7 +628,7 @@ function processEventArgs (vm, event, args = [], extra = [], isCustom, methodNam
}
}
const extraObj = processEventExtra(vm, extra);
const extraObj = processEventExtra(vm, extra, event);
const ret = [];
args.forEach(arg => {
......@@ -530,7 +643,9 @@ function processEventArgs (vm, event, args = [], extra = [], isCustom, methodNam
}
}
} else {
if (typeof arg === 'string' && hasOwn(extraObj, arg)) {
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);
......@@ -653,7 +768,7 @@ function createApp (vm) {
{ // 头条的 selectComponent 竟然是异步的
initRefs(this);
}
initMocks(this);
initMocks(this, mocks);
}
},
created () { // 处理 injections
......@@ -688,38 +803,6 @@ function createApp (vm) {
return vm
}
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;
}
}
}
function initPage$1 (pageOptions) {
initComponent$1(pageOptions);
}
function initComponent$1 (componentOptions) {
componentOptions.methods.$getAppWebview = function () {
return plus.webview.getWebviewById(`${this.__wxWebviewId__}`)
};
}
const hooks$1 = [
'onShow',
'onHide',
......@@ -830,7 +913,9 @@ function initVm$2 (VueComponent) {
function createComponent (vueOptions) {
vueOptions = vueOptions.default || vueOptions;
const properties = getProperties(vueOptions.props);
const behaviors = getBehaviors(vueOptions);
const properties = getProperties(vueOptions.props, false, vueOptions.__file);
const VueComponent = Vue.extend(vueOptions);
......@@ -840,6 +925,7 @@ function createComponent (vueOptions) {
addGlobalClass: true
},
data: getData(vueOptions, Vue.prototype),
behaviors,
properties,
lifetimes: {
attached () {
......
{
"name": "@dcloudio/uni-app-plus",
"version": "0.0.218",
"version": "0.0.228",
"description": "uni-app app-plus",
"main": "dist/index.js",
"scripts": {
......
......@@ -270,7 +270,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) {
......@@ -444,11 +444,41 @@ Component = function (options = {}) {
return MPComponent(options)
};
const MOCKS = ['__route__', '__wxExparserNodeId__', '__wxWebviewId__', '__webviewId__'];
const mocks = ['nodeId'];
function initMocks (vm) {
function initPage (pageOptions) {
initComponent(pageOptions);
}
function initComponent (componentOptions) {
componentOptions.messages = {
'__l': handleLink
};
}
function triggerLink (mpInstance, vueOptions) {
mpInstance.dispatch('__l', mpInstance.$vm || vueOptions);
}
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;
}
}
}
function initMocks (vm, mocks) {
const mpInstance = vm.$mp[vm.mpType];
MOCKS.forEach(mock => {
mocks.forEach(mock => {
if (hasOwn(mpInstance, mock)) {
vm[mock] = mpInstance[mock];
}
......@@ -482,6 +512,10 @@ function getData (vueOptions, context) {
} 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];
......@@ -501,9 +535,81 @@ function createObserver (name) {
}
}
function getProperties (props) {
const properties = {
vueSlots: { // 小程序不能直接定义 $slots 的 props,所以通过 vueSlots 转换到 $slots
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://', `${"swan"}://`));
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(
Behavior({
properties: getProperties(vueExtends.props, true)
})
);
}
if (Array.isArray(vueMixins)) {
vueMixins.forEach(vueMixin => {
if (isPlainObject(vueMixin) && vueMixin.props) {
behaviors.push(
Behavior({
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]
}
{
if (
defaultValue === false &&
Array.isArray(type) &&
type.length === 2 &&
type.indexOf(String) !== -1 &&
type.indexOf(Boolean) !== -1
) { // [String,Boolean]=>Boolean
if (file) {
console.warn(
`props.${key}.type should use Boolean instead of [String,Boolean] at ${file}`
);
}
return Boolean
}
}
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) {
......@@ -515,8 +621,8 @@ function getProperties (props) {
$slots
});
}
}
};
};
}
if (Array.isArray(props)) { // ['title']
props.forEach(key => {
properties[key] = {
......@@ -532,14 +638,18 @@ function getProperties (props) {
if (isFn(value)) {
value = value();
}
opts.type = parsePropType(key, opts.type, value, file);
properties[key] = {
type: PROP_TYPES.includes(opts.type) ? opts.type : null,
type: PROP_TYPES.indexOf(opts.type) !== -1 ? opts.type : null,
value,
observer: createObserver(key)
};
} else { // content:String
const type = parsePropType(key, opts, null, file);
properties[key] = {
type: PROP_TYPES.includes(opts) ? opts : null,
type: PROP_TYPES.indexOf(type) !== -1 ? type : null,
observer: createObserver(key)
};
}
......@@ -549,6 +659,11 @@ function getProperties (props) {
}
function wrapper$1 (event) {
// TODO 又得兼容 mpvue 的 mp 对象
try {
event.mp = JSON.parse(JSON.stringify(event));
} catch (e) {}
event.stopPropagation = noop;
event.preventDefault = noop;
......@@ -568,9 +683,6 @@ function wrapper$1 (event) {
}
}
// TODO 又得兼容 mpvue 的 mp 对象
event.mp = event;
if (isPlainObject(event.detail)) {
event.target = Object.assign({}, event.target, event.detail);
}
......@@ -615,7 +727,7 @@ function getExtraValue (vm, dataPathsArray) {
return context
}
function processEventExtra (vm, extra) {
function processEventExtra (vm, extra, event) {
const extraObj = {};
if (Array.isArray(extra) && extra.length) {
......@@ -635,7 +747,13 @@ function processEventExtra (vm, extra) {
if (!dataPath) { // model,prop.sync
extraObj['$' + index] = vm;
} else {
extraObj['$' + index] = vm.__get_value(dataPath);
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);
......@@ -646,6 +764,15 @@ function processEventExtra (vm, extra) {
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) { // 自定义事件
......@@ -660,7 +787,7 @@ function processEventArgs (vm, event, args = [], extra = [], isCustom, methodNam
}
}
const extraObj = processEventExtra(vm, extra);
const extraObj = processEventExtra(vm, extra, event);
const ret = [];
args.forEach(arg => {
......@@ -675,7 +802,9 @@ function processEventArgs (vm, event, args = [], extra = [], isCustom, methodNam
}
}
} else {
if (typeof arg === 'string' && hasOwn(extraObj, arg)) {
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);
......@@ -812,7 +941,7 @@ function createApp (vm) {
{ // 头条的 selectComponent 竟然是异步的
initRefs(this);
}
initMocks(this);
initMocks(this, mocks);
}
},
created () { // 处理 injections
......@@ -847,36 +976,6 @@ function createApp (vm) {
return vm
}
function initPage (pageOptions) {
initComponent(pageOptions);
}
function initComponent (componentOptions) {
componentOptions.messages = {
'__l': handleLink
};
}
function triggerLink (mpInstance, vueOptions) {
mpInstance.dispatch('__l', mpInstance.$vm || vueOptions);
}
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;
}
}
}
const hooks$1 = [
'onShow',
'onHide',
......@@ -997,7 +1096,9 @@ function initVm$2 (VueComponent) {
function createComponent (vueOptions) {
vueOptions = vueOptions.default || vueOptions;
const properties = getProperties(vueOptions.props);
const behaviors = getBehaviors(vueOptions);
const properties = getProperties(vueOptions.props, false, vueOptions.__file);
const VueComponent = Vue.extend(vueOptions);
......@@ -1007,6 +1108,7 @@ function createComponent (vueOptions) {
addGlobalClass: true
},
data: getData(vueOptions, Vue.prototype),
behaviors,
properties,
lifetimes: {
attached () {
......
{
"name": "@dcloudio/uni-mp-baidu",
"version": "0.0.813",
"version": "0.0.825",
"description": "uni-app mp-baidu",
"main": "dist/index.js",
"scripts": {
......
......@@ -331,7 +331,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) {
......@@ -489,11 +489,80 @@ Component = function (options = {}) {
return MPComponent(options)
};
const MOCKS = ['__route__', '__wxExparserNodeId__', '__wxWebviewId__', '__webviewId__'];
const instances = Object.create(null);
const mocks = ['__route__', '__webviewId__', '__nodeid__'];
function initPage (pageOptions) {
initComponent(pageOptions);
}
function initComponent (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);
};
}
function initRefs () {
this.selectAllComponents('.vue-ref', (components) => {
components.forEach(component => {
const ref = component.data.vueRef; // 头条的组件 dataset 竟然是空的
this.$vm.$refs[ref] = component.$vm || component;
});
});
this.selectAllComponents('.vue-ref-in-for', (forComponents) => {
forComponents.forEach(component => {
const ref = component.data.vueRef;
if (!this.$vm.$refs[ref]) {
this.$vm.$refs[ref] = [];
}
this.$vm.$refs[ref].push(component.$vm || component);
});
});
}
function triggerLink (mpInstance) {
const nodeId = mpInstance.__nodeid__ + '';
const webviewId = mpInstance.__webviewId__ + '';
instances[webviewId + '_' + nodeId] = mpInstance.$vm;
function initMocks (vm) {
mpInstance.triggerEvent('__l', {
nodeId,
webviewId
}, {
bubbles: true,
composed: true
});
}
// TODO 目前有 bug,composed 不生效
function handleLink (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];
}
}
function initMocks (vm, mocks) {
const mpInstance = vm.$mp[vm.mpType];
MOCKS.forEach(mock => {
mocks.forEach(mock => {
if (hasOwn(mpInstance, mock)) {
vm[mock] = mpInstance[mock];
}
......@@ -527,6 +596,10 @@ function getData (vueOptions, context) {
} 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];
......@@ -546,9 +619,65 @@ function createObserver (name) {
}
}
function getProperties (props) {
const properties = {
vueSlots: { // 小程序不能直接定义 $slots 的 props,所以通过 vueSlots 转换到 $slots
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://', `${"tt"}://`));
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(
Behavior({
properties: getProperties(vueExtends.props, true)
})
);
}
if (Array.isArray(vueMixins)) {
vueMixins.forEach(vueMixin => {
if (isPlainObject(vueMixin) && vueMixin.props) {
behaviors.push(
Behavior({
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) {
......@@ -560,8 +689,8 @@ function getProperties (props) {
$slots
});
}
}
};
};
}
if (Array.isArray(props)) { // ['title']
props.forEach(key => {
properties[key] = {
......@@ -577,14 +706,18 @@ function getProperties (props) {
if (isFn(value)) {
value = value();
}
opts.type = parsePropType(key, opts.type, value, file);
properties[key] = {
type: PROP_TYPES.includes(opts.type) ? opts.type : null,
type: PROP_TYPES.indexOf(opts.type) !== -1 ? opts.type : null,
value,
observer: createObserver(key)
};
} else { // content:String
const type = parsePropType(key, opts, null, file);
properties[key] = {
type: PROP_TYPES.includes(opts) ? opts : null,
type: PROP_TYPES.indexOf(type) !== -1 ? type : null,
observer: createObserver(key)
};
}
......@@ -594,6 +727,11 @@ function getProperties (props) {
}
function wrapper$1 (event) {
// TODO 又得兼容 mpvue 的 mp 对象
try {
event.mp = JSON.parse(JSON.stringify(event));
} catch (e) {}
event.stopPropagation = noop;
event.preventDefault = noop;
......@@ -603,9 +741,6 @@ function wrapper$1 (event) {
event.detail = {};
}
// TODO 又得兼容 mpvue 的 mp 对象
event.mp = event;
if (isPlainObject(event.detail)) {
event.target = Object.assign({}, event.target, event.detail);
}
......@@ -650,7 +785,7 @@ function getExtraValue (vm, dataPathsArray) {
return context
}
function processEventExtra (vm, extra) {
function processEventExtra (vm, extra, event) {
const extraObj = {};
if (Array.isArray(extra) && extra.length) {
......@@ -670,7 +805,13 @@ function processEventExtra (vm, extra) {
if (!dataPath) { // model,prop.sync
extraObj['$' + index] = vm;
} else {
extraObj['$' + index] = vm.__get_value(dataPath);
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);
......@@ -681,6 +822,15 @@ function processEventExtra (vm, extra) {
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) { // 自定义事件
......@@ -695,7 +845,7 @@ function processEventArgs (vm, event, args = [], extra = [], isCustom, methodNam
}
}
const extraObj = processEventExtra(vm, extra);
const extraObj = processEventExtra(vm, extra, event);
const ret = [];
args.forEach(arg => {
......@@ -710,7 +860,9 @@ function processEventArgs (vm, event, args = [], extra = [], isCustom, methodNam
}
}
} else {
if (typeof arg === 'string' && hasOwn(extraObj, arg)) {
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);
......@@ -807,7 +959,7 @@ function createApp (vm) {
delete this.$options.mpInstance;
if (this.mpType !== 'app') {
initMocks(this);
initMocks(this, mocks);
}
},
created () { // 处理 injections
......@@ -842,75 +994,6 @@ function createApp (vm) {
return vm
}
const instances = Object.create(null);
function initPage (pageOptions) {
initComponent(pageOptions);
}
function initComponent (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$1.call(this);
};
}
function initRefs$1 () {
this.selectAllComponents('.vue-ref', (components) => {
components.forEach(component => {
const ref = component.data.vueRef; // 头条的组件 dataset 竟然是空的
this.$vm.$refs[ref] = component.$vm || component;
});
});
this.selectAllComponents('.vue-ref-in-for', (forComponents) => {
forComponents.forEach(component => {
const ref = component.data.vueRef;
if (!this.$vm.$refs[ref]) {
this.$vm.$refs[ref] = [];
}
this.$vm.$refs[ref].push(component.$vm || component);
});
});
}
function triggerLink (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 (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 hooks$1 = [
'onShow',
'onHide',
......@@ -1021,7 +1104,9 @@ function initVm$2 (VueComponent) {
function createComponent (vueOptions) {
vueOptions = vueOptions.default || vueOptions;
const properties = getProperties(vueOptions.props);
const behaviors = getBehaviors(vueOptions);
const properties = getProperties(vueOptions.props, false, vueOptions.__file);
const VueComponent = Vue.extend(vueOptions);
......@@ -1031,6 +1116,7 @@ function createComponent (vueOptions) {
addGlobalClass: true
},
data: getData(vueOptions, Vue.prototype),
behaviors,
properties,
lifetimes: {
attached () {
......
{
"name": "@dcloudio/uni-mp-toutiao",
"version": "0.0.313",
"version": "0.0.323",
"description": "uni-app mp-toutiao",
"main": "dist/index.js",
"scripts": {
......
......@@ -173,7 +173,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) {
......@@ -336,11 +336,33 @@ Component = function (options = {}) {
return MPComponent(options)
};
const MOCKS = ['__route__', '__wxExparserNodeId__', '__wxWebviewId__', '__webviewId__'];
const mocks = ['__route__', '__wxExparserNodeId__', '__wxWebviewId__'];
function initMocks (vm) {
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;
}
}
}
function initMocks (vm, mocks) {
const mpInstance = vm.$mp[vm.mpType];
MOCKS.forEach(mock => {
mocks.forEach(mock => {
if (hasOwn(mpInstance, mock)) {
vm[mock] = mpInstance[mock];
}
......@@ -374,6 +396,10 @@ function getData (vueOptions, context) {
} 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];
......@@ -393,9 +419,65 @@ function createObserver (name) {
}
}
function getProperties (props) {
const properties = {
vueSlots: { // 小程序不能直接定义 $slots 的 props,所以通过 vueSlots 转换到 $slots
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://', `${"wx"}://`));
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(
Behavior({
properties: getProperties(vueExtends.props, true)
})
);
}
if (Array.isArray(vueMixins)) {
vueMixins.forEach(vueMixin => {
if (isPlainObject(vueMixin) && vueMixin.props) {
behaviors.push(
Behavior({
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) {
......@@ -407,8 +489,8 @@ function getProperties (props) {
$slots
});
}
}
};
};
}
if (Array.isArray(props)) { // ['title']
props.forEach(key => {
properties[key] = {
......@@ -424,14 +506,18 @@ function getProperties (props) {
if (isFn(value)) {
value = value();
}
opts.type = parsePropType(key, opts.type, value, file);
properties[key] = {
type: PROP_TYPES.includes(opts.type) ? opts.type : null,
type: PROP_TYPES.indexOf(opts.type) !== -1 ? opts.type : null,
value,
observer: createObserver(key)
};
} else { // content:String
const type = parsePropType(key, opts, null, file);
properties[key] = {
type: PROP_TYPES.includes(opts) ? opts : null,
type: PROP_TYPES.indexOf(type) !== -1 ? type : null,
observer: createObserver(key)
};
}
......@@ -441,6 +527,11 @@ function getProperties (props) {
}
function wrapper$1 (event) {
// TODO 又得兼容 mpvue 的 mp 对象
try {
event.mp = JSON.parse(JSON.stringify(event));
} catch (e) {}
event.stopPropagation = noop;
event.preventDefault = noop;
......@@ -450,9 +541,6 @@ function wrapper$1 (event) {
event.detail = {};
}
// TODO 又得兼容 mpvue 的 mp 对象
event.mp = event;
if (isPlainObject(event.detail)) {
event.target = Object.assign({}, event.target, event.detail);
}
......@@ -497,7 +585,7 @@ function getExtraValue (vm, dataPathsArray) {
return context
}
function processEventExtra (vm, extra) {
function processEventExtra (vm, extra, event) {
const extraObj = {};
if (Array.isArray(extra) && extra.length) {
......@@ -517,7 +605,13 @@ function processEventExtra (vm, extra) {
if (!dataPath) { // model,prop.sync
extraObj['$' + index] = vm;
} else {
extraObj['$' + index] = vm.__get_value(dataPath);
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);
......@@ -528,6 +622,15 @@ function processEventExtra (vm, extra) {
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) { // 自定义事件
......@@ -542,7 +645,7 @@ function processEventArgs (vm, event, args = [], extra = [], isCustom, methodNam
}
}
const extraObj = processEventExtra(vm, extra);
const extraObj = processEventExtra(vm, extra, event);
const ret = [];
args.forEach(arg => {
......@@ -557,7 +660,9 @@ function processEventArgs (vm, event, args = [], extra = [], isCustom, methodNam
}
}
} else {
if (typeof arg === 'string' && hasOwn(extraObj, arg)) {
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);
......@@ -685,7 +790,7 @@ function createApp (vm) {
{ // 头条的 selectComponent 竟然是异步的
initRefs(this);
}
initMocks(this);
initMocks(this, mocks);
}
},
created () { // 处理 injections
......@@ -720,28 +825,6 @@ function createApp (vm) {
return vm
}
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 hooks$1 = [
'onShow',
'onHide',
......@@ -850,7 +933,9 @@ function initVm$2 (VueComponent) {
function createComponent (vueOptions) {
vueOptions = vueOptions.default || vueOptions;
const properties = getProperties(vueOptions.props);
const behaviors = getBehaviors(vueOptions);
const properties = getProperties(vueOptions.props, false, vueOptions.__file);
const VueComponent = Vue.extend(vueOptions);
......@@ -860,6 +945,7 @@ function createComponent (vueOptions) {
addGlobalClass: true
},
data: getData(vueOptions, Vue.prototype),
behaviors,
properties,
lifetimes: {
attached () {
......
{
"name": "@dcloudio/uni-mp-weixin",
"version": "0.0.937",
"version": "0.0.947",
"description": "uni-app mp-weixin",
"main": "dist/index.js",
"scripts": {
......
const pixelRatio = (function () {
const canvas = document.createElement('canvas')
const context = canvas.getContext('2d')
const backingStore = context.backingStorePixelRatio ||
context.webkitBackingStorePixelRatio ||
context.mozBackingStorePixelRatio ||
context.msBackingStorePixelRatio ||
context.oBackingStorePixelRatio ||
context.backingStorePixelRatio || 1
return (window.devicePixelRatio || 1) / backingStore
})()
const forEach = function (obj, func) {
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
func(obj[key], key)
}
}
}
const ratioArgs = {
'fillRect': 'all',
'clearRect': 'all',
'strokeRect': 'all',
'moveTo': 'all',
'lineTo': 'all',
'arc': [0, 1, 2],
'arcTo': 'all',
'bezierCurveTo': 'all',
'isPointinPath': 'all',
'isPointinStroke': 'all',
'quadraticCurveTo': 'all',
'rect': 'all',
'translate': 'all',
'createRadialGradient': 'all',
'createLinearGradient': 'all',
'setTransform': [4, 5]
}
if (pixelRatio !== 1) {
const proto = CanvasRenderingContext2D.prototype
forEach(ratioArgs, function (value, key) {
proto[key] = (function (_super) {
return function () {
if (this.__ignore__) {
return _super.apply(this, arguments)
}
let args = Array.prototype.slice.call(arguments)
if (value === 'all') {
args = args.map(function (a) {
return a * pixelRatio
})
} else if (Array.isArray(value)) {
for (let i = 0; i < value.length; i++) {
args[value[i]] *= pixelRatio
}
}
return _super.apply(this, args)
}
})(proto[key])
})
proto.stroke = (function (_super) {
return function () {
if (this.__ignore__) {
return _super.apply(this, arguments)
}
this.lineWidth *= pixelRatio
_super.apply(this, arguments)
this.lineWidth /= pixelRatio
}
})(proto.stroke)
proto.fillText = (function (_super) {
return function () {
if (this.__ignore__) {
return _super.apply(this, arguments)
}
const args = Array.prototype.slice.call(arguments)
args[1] *= pixelRatio
args[2] *= pixelRatio
this.font = this.font.replace(
/(\d+)(px|em|rem|pt)/g,
function (w, m, u) {
return (m * pixelRatio) + u
}
)
_super.apply(this, args)
this.font = this.font.replace(
/(\d+)(px|em|rem|pt)/g,
function (w, m, u) {
return (m / pixelRatio) + u
}
)
}
})(proto.fillText)
proto.strokeText = (function (_super) {
return function () {
if (this.__ignore__) {
return _super.apply(this, arguments)
}
var args = Array.prototype.slice.call(arguments)
args[1] *= pixelRatio // x
args[2] *= pixelRatio // y
this.font = this.font.replace(
/(\d+)(px|em|rem|pt)/g,
function (w, m, u) {
return (m * pixelRatio) + u
}
)
_super.apply(this, args)
this.font = this.font.replace(
/(\d+)(px|em|rem|pt)/g,
function (w, m, u) {
return (m / pixelRatio) + u
}
)
}
})(proto.strokeText)
proto.drawImageByCanvas = (function (_super) {
return function (canvas, srcx, srcy, srcw, srch, desx, desy, desw, desh, isScale) {
if (this.__ignore__) {
return _super.apply(this, arguments)
}
srcx *= pixelRatio
srcy *= pixelRatio
srcw *= pixelRatio
srch *= pixelRatio
desx *= pixelRatio
desy *= pixelRatio
desw = isScale ? desw * pixelRatio : desw
desh = isScale ? desh * pixelRatio : desh
_super.call(this, canvas, srcx, srcy, srcw, srch, desx, desy, desw, desh)
}
})(proto.drawImage)
proto.drawImage = (function (_super) {
return function () {
if (this.__ignore__) {
return _super.apply(this, arguments)
}
this.scale(pixelRatio, pixelRatio)
_super.apply(this, arguments)
this.scale(1 / pixelRatio, 1 / pixelRatio)
}
})(proto.drawImage)
}
export function wrapper (canvas) {
canvas.style.height = canvas.height + 'px'
canvas.style.width = canvas.width + 'px'
canvas.width *= pixelRatio
canvas.height *= pixelRatio
console.log(canvas.width)
console.log(canvas.height)
}
......@@ -39,7 +39,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) {
......
import 'uni-platform/runtime/index'
import Vue from 'vue'
import {
mocks
} from 'uni-platform/runtime/wrapper/index'
import {
initRefs,
......@@ -51,7 +55,7 @@ export function createApp (vm) {
if (__PLATFORM__ !== 'mp-toutiao') { // 头条的 selectComponent 竟然是异步的
initRefs(this)
}
initMocks(this)
initMocks(this, mocks)
}
},
created () { // 处理 injections
......
......@@ -9,6 +9,7 @@ import {
import {
getData,
handleEvent,
getBehaviors,
getProperties
} from './util'
......@@ -42,7 +43,9 @@ function initVm (VueComponent) {
export function createComponent (vueOptions) {
vueOptions = vueOptions.default || vueOptions
const properties = getProperties(vueOptions.props)
const behaviors = getBehaviors(vueOptions)
const properties = getProperties(vueOptions.props, false, vueOptions.__file)
const VueComponent = Vue.extend(vueOptions)
......@@ -52,6 +55,7 @@ export function createComponent (vueOptions) {
addGlobalClass: true
},
data: getData(vueOptions, Vue.prototype),
behaviors,
properties,
lifetimes: {
attached () {
......
......@@ -5,11 +5,9 @@ import {
isPlainObject
} from 'uni-shared'
const MOCKS = ['__route__', '__wxExparserNodeId__', '__wxWebviewId__', '__webviewId__']
export function initMocks (vm) {
export function initMocks (vm, mocks) {
const mpInstance = vm.$mp[vm.mpType]
MOCKS.forEach(mock => {
mocks.forEach(mock => {
if (hasOwn(mpInstance, mock)) {
vm[mock] = mpInstance[mock]
}
......@@ -43,6 +41,10 @@ export function getData (vueOptions, context) {
} 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]
......@@ -62,9 +64,81 @@ function createObserver (name) {
}
}
export function getProperties (props) {
const properties = {
vueSlots: { // 小程序不能直接定义 $slots 的 props,所以通过 vueSlots 转换到 $slots
export 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://', `${__PLATFORM_PREFIX__}://`))
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(
Behavior({
properties: getProperties(vueExtends.props, true)
})
)
}
if (Array.isArray(vueMixins)) {
vueMixins.forEach(vueMixin => {
if (isPlainObject(vueMixin) && vueMixin.props) {
behaviors.push(
Behavior({
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]
}
if (__PLATFORM__ === 'mp-baidu') {
if (
defaultValue === false &&
Array.isArray(type) &&
type.length === 2 &&
type.indexOf(String) !== -1 &&
type.indexOf(Boolean) !== -1
) { // [String,Boolean]=>Boolean
if (file) {
console.warn(
`props.${key}.type should use Boolean instead of [String,Boolean] at ${file}`
)
}
return Boolean
}
}
return type
}
export function getProperties (props, isBehavior = false, file = '') {
const properties = {}
if (!isBehavior) {
properties.vueSlots = { // 小程序不能直接定义 $slots 的 props,所以通过 vueSlots 转换到 $slots
type: null,
value: [],
observer: function (newVal, oldVal) {
......@@ -93,14 +167,18 @@ export function getProperties (props) {
if (isFn(value)) {
value = value()
}
opts.type = parsePropType(key, opts.type, value, file)
properties[key] = {
type: PROP_TYPES.includes(opts.type) ? opts.type : null,
type: PROP_TYPES.indexOf(opts.type) !== -1 ? opts.type : null,
value,
observer: createObserver(key)
}
} else { // content:String
const type = parsePropType(key, opts, null, file)
properties[key] = {
type: PROP_TYPES.includes(opts) ? opts : null,
type: PROP_TYPES.indexOf(type) !== -1 ? type : null,
observer: createObserver(key)
}
}
......@@ -110,6 +188,11 @@ export function getProperties (props) {
}
function wrapper (event) {
// TODO 又得兼容 mpvue 的 mp 对象
try {
event.mp = JSON.parse(JSON.stringify(event))
} catch (e) {}
event.stopPropagation = noop
event.preventDefault = noop
......@@ -129,9 +212,6 @@ function wrapper (event) {
}
}
// TODO 又得兼容 mpvue 的 mp 对象
event.mp = event
if (isPlainObject(event.detail)) {
event.target = Object.assign({}, event.target, event.detail)
}
......@@ -176,7 +256,7 @@ function getExtraValue (vm, dataPathsArray) {
return context
}
function processEventExtra (vm, extra) {
function processEventExtra (vm, extra, event) {
const extraObj = {}
if (Array.isArray(extra) && extra.length) {
......@@ -196,7 +276,13 @@ function processEventExtra (vm, extra) {
if (!dataPath) { // model,prop.sync
extraObj['$' + index] = vm
} else {
extraObj['$' + index] = vm.__get_value(dataPath)
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)
......@@ -207,6 +293,15 @@ function processEventExtra (vm, extra) {
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) { // 自定义事件
......@@ -221,7 +316,7 @@ function processEventArgs (vm, event, args = [], extra = [], isCustom, methodNam
}
}
const extraObj = processEventExtra(vm, extra)
const extraObj = processEventExtra(vm, extra, event)
const ret = []
args.forEach(arg => {
......@@ -236,7 +331,9 @@ function processEventArgs (vm, event, args = [], extra = [], isCustom, methodNam
}
}
} else {
if (typeof arg === 'string' && hasOwn(extraObj, arg)) {
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)
......
import createCallbacks from 'uni-helpers/callbacks'
import { wrapper } from 'uni-helpers/hidpi'
const canvasEventCallbacks = createCallbacks('canvasEvent')
......@@ -257,6 +258,7 @@ var tempCanvas
function getTempCanvas () {
if (!tempCanvas) {
tempCanvas = document.createElement('canvas')
wrapper(tempCanvas)
}
return tempCanvas
}
......@@ -816,7 +818,7 @@ export function canvasToTempFilePath ({
pageId = app.$route.params.__id__
} else {
invoke(callbackId, {
errMsg: 'canvasPutImageData:fail'
errMsg: 'canvasToTempFilePath:fail'
})
return
}
......@@ -840,20 +842,24 @@ export function canvasToTempFilePath ({
canvas.width = data.width
canvas.height = data.height
var c2d = canvas.getContext('2d')
c2d.putImageData(imgData, 0, 0)
var base64 = canvas.toDataURL('image/png')
var img = new Image()
img.onload = function () {
canvas.width = destWidth || imgData.width
canvas.height = destHeight || imgData.height
c2d.drawImage(img, 0, 0)
base64 = canvas.toDataURL(`image/${fileType.toLowerCase()}`, qualit)
invoke(callbackId, {
errMsg: 'canvasToTempFilePath:ok',
tempFilePath: base64
})
}
img.src = base64
c2d.putImageData(imgData, 0, 0, 0, 0, destWidth || imgData.width, destHeight || imgData.height)
var base64 = canvas.toDataURL(`image/${fileType.toLowerCase()}`, qualit)
invoke(callbackId, {
errMsg: 'canvasToTempFilePath:ok',
tempFilePath: base64
})
// var img = new Image()
// img.onload = function () {
// canvas.width = destWidth || imgData.width
// canvas.height = destHeight || imgData.height
// c2d.drawImage(img, 0, 0)
// base64 = canvas.toDataURL(`image/${fileType.toLowerCase()}`, qualit)
// invoke(callbackId, {
// errMsg: 'canvasToTempFilePath:ok',
// tempFilePath: base64
// })
// }
// img.src = base64
})
operateCanvas(canvasId, pageId, 'getImageData', {
x,
......
......@@ -15,7 +15,28 @@ function removeKeepAliveInclude (componentName) {
}
}
function switchTab (routes) {
let positionStore = Object.create(null)
export function getTabBarScrollPosition (id) {
return positionStore[id]
}
function saveTabBarScrollPosition (id) {
positionStore[id] = {
x: window.pageXOffset,
y: window.pageYOffset
}
}
function switchTab (routes, to, from) {
if (
to &&
from &&
to.meta.isTabBar &&
from.meta.isTabBar
) { // tabbar 跳 tabbar
saveTabBarScrollPosition(from.params.__id__)
}
// 关闭非 tabBar 页面
const pages = getCurrentPages()
for (let i = pages.length - 1; i >= 0; i--) {
......@@ -33,11 +54,13 @@ function reLaunch (toName) {
// 关闭所有页面
const pages = getCurrentPages(true)
for (let i = pages.length - 1; i >= 0; i--) {
callPageHook(pages[i], 'onUnload')
// 重新reLaunch至首页可能会被keepAlive,先手动强制destroy
callPageHook(pages[i], 'onUnload')
// 重新reLaunch至首页可能会被keepAlive,先手动强制destroy
pages[i].$destroy()
}
this.keepAliveInclude = []
this.keepAliveInclude = []
// 清空 positionStore
positionStore = Object.create(null)
}
let currentPages = []
......@@ -65,7 +88,7 @@ function beforeEach (to, from, next, routes) {
removeKeepAliveInclude.call(this, fromName)
if (from.meta) {
if (from.meta.isQuit) { // 如果 redirectTo 的前一个页面是 quit 类型,则新打开的页面也是 quit
to.meta.isQuit = true
to.meta.isQuit = true
to.meta.isEntry = !!from.meta.isEntry
}
if (from.meta.isTabBar) { // 如果是 tabBar,需要更新系统组件 tabBar 内的 list 数据
......@@ -78,7 +101,7 @@ function beforeEach (to, from, next, routes) {
break
case 'switchTab':
switchTab.call(this, routes)
switchTab.call(this, routes, to, from)
break
case 'reLaunch':
reLaunch.call(this, toName)
......
......@@ -16,6 +16,10 @@ import {
createPageMixin
} from './page'
import {
getTabBarScrollPosition
} from './app/router-guard'
function getMinId (routes) {
let minId = 0
routes.forEach(route => {
......@@ -62,6 +66,17 @@ export default {
if (savedPosition) {
return savedPosition
} else {
if (
to &&
from &&
to.meta.isTabBar &&
from.meta.isTabBar
) { // tabbar 跳 tabbar
const position = getTabBarScrollPosition(to.params.__id__)
if (position) {
return position
}
}
return {
x: 0,
y: 0
......@@ -101,7 +116,9 @@ export default {
const appMixin = createAppMixin(routes, entryRoute)
// mixin app hooks
Object.keys(appMixin).forEach(hook => {
options[hook] = options[hook] ? [].concat(appMixin[hook], options[hook]) : [appMixin[hook]]
options[hook] = options[hook] ? [].concat(appMixin[hook], options[hook]) : [
appMixin[hook]
]
})
// router
......@@ -117,7 +134,9 @@ export default {
const pageMixin = createPageMixin()
// mixin page hooks
Object.keys(pageMixin).forEach(hook => {
options[hook] = options[hook] ? [].concat(pageMixin[hook], options[hook]) : [pageMixin[hook]]
options[hook] = options[hook] ? [].concat(pageMixin[hook], options[hook]) : [
pageMixin[hook]
]
})
} else {
if (this.$parent && this.$parent.__page__) {
......
......@@ -166,6 +166,11 @@ export default {
passive: false
} : false)
},
activated () {
// 还原 scroll-view 滚动位置
this.scrollY && (this.$refs.main.scrollTop = this.lastScrollTop)
this.scrollX && (this.$refs.main.scrollLeft = this.lastScrollLeft)
},
beforeDestroy () {
this.$refs.main.removeEventListener('touchstart', this.__handleTouchStart, passiveOptions)
this.$refs.main.removeEventListener('touchmove', this.__handleTouchMove, passiveOptions)
......
/**
* uni://form-field
*/
import {
hasOwn
} from 'uni-shared'
import {
emitter
} from 'uni-mixins'
function created () {
this.$dispatch('Form', 'uni-form-group-update', {
type: 'add',
vm: this
})
}
function beforeDestroy () {
this.$dispatch('Form', 'uni-form-group-update', {
type: 'remove',
vm: this
})
}
export default {
name: 'uni://form-field',
init (options, vm) {
if (
!vm.constructor.options.props.name ||
!vm.constructor.options.props.value
) { // 未初始化 props
if (!vm.constructor.options.props.name) {
vm.constructor.options.props.name = options.props.name = {
type: String
}
}
if (!vm.constructor.options.props.value) {
vm.constructor.options.props.value = options.props.value = {
type: null
}
}
}
if (!options.propsData) {
options.propsData = {}
}
const $vnode = vm.$vnode
if ($vnode && $vnode.data && $vnode.data.attrs) {
if (hasOwn($vnode.data.attrs, 'name')) {
options.propsData.name = $vnode.data.attrs.name
}
if (hasOwn($vnode.data.attrs, 'value')) {
options.propsData.value = $vnode.data.attrs.value
}
}
if (
!vm.constructor.options.methods ||
!vm.constructor.options.methods._getFormData
) { // 未初始化 methods
if (!vm.constructor.options.methods) {
vm.constructor.options.methods = {}
}
if (!options.methods) {
options.methods = {}
}
const formMethods = {
_getFormData () {
return this.name ? {
key: this.name,
value: this.value
} : {}
},
_resetFormData () {
this.value = ''
}
}
Object.assign(vm.constructor.options.methods, formMethods)
Object.assign(options.methods, formMethods)
// add $dispatch
Object.assign(vm.constructor.options.methods, emitter.methods)
Object.assign(options.methods, emitter.methods)
const createdHooks = options['created']
vm.constructor.options['created'] = options['created'] =
createdHooks ? [].concat(created, createdHooks) : [
created
]
const beforeDestroyHooks = options['beforeDestroy']
vm.constructor.options['beforeDestroy'] = options['beforeDestroy'] =
beforeDestroyHooks ? [].concat(beforeDestroy, beforeDestroyHooks) : [
beforeDestroy
]
}
}
}
import formField from './form-field'
const behaviors = {
[formField.name]: formField
}
export default function initBehaviors (options, vm) {
options.behaviors.forEach(name => {
const behavior = behaviors[name]
behavior && behavior.init(options, vm)
})
}
......@@ -7,6 +7,8 @@ import {
processEvent
} from './events'
import initBehaviors from './behaviors'
function pageMounted () {
// 通知 Service,View 层已 ready
UniViewJSBridge.publishHandler('onPageReady', {}, this.$page.id)
......@@ -34,13 +36,18 @@ export default {
}
}
$event = processEvent.call(this, $event.type, $event, {}, target || $event.target, $event.currentTarget)
}
}
return $event
}
Vue.mixin({
beforeCreate () {
const options = this.$options
if (options.behaviors && options.behaviors.length) {
initBehaviors(options, this)
}
if (isPage(this)) {
options.mounted = options.mounted ? [].concat(pageMounted, options.mounted) : [pageMounted]
}
......
export {
mocks,
handleLink,
triggerLink
}
......
......@@ -3,9 +3,7 @@
<uni-modal
v-show="visible"
@touchmove.prevent>
<div
class="uni-mask"
@click="_close('mask')" />
<div class="uni-mask"/>
<div class="uni-modal">
<div
v-if="title"
......
......@@ -4,7 +4,8 @@
</div>
</template>
<style>
.uni-async-loading {
.uni-async-loading {
box-sizing: border-box;
width: 100%;
padding: 50px;
text-align: center;
......
......@@ -43,9 +43,6 @@ export default {
</script>
<style>
div {
box-sizing: border-box;
}
.system-header {
position: relative;
......@@ -57,6 +54,11 @@ div {
text-align: center;
line-height: 44px;
font-size: 16px;
box-sizing: border-box;
}
.system-header * {
box-sizing: border-box;
}
.header-text {
......
export default [
'saveImageToPhotosAlbum',
'getRecorderManager',
'getBackgroundAudioManager',
'saveVideoToPhotosAlbum',
'createCameraContext',
'createLivePlayerContext',
'saveFile',
'getSavedFileList',
'getSavedFileInfo',
'removeSavedFileInfo',
'getFileInfo',
'onMemoryWarning',
'onGyroscopeChange',
'startGyroscope',
'stopGyroscope',
'scanCode',
'setClipboardData',
'getClipboardData',
'setScreenBrightness',
'getScreenBrightness',
'setKeepScreenOn',
'onUserCaptureScreen',
'addPhoneContact',
'saveImageToPhotosAlbum',
'saveVideoToPhotosAlbum',
'setClipboardData',
'getClipboardData',
'getRecorderManager',
'openBluetoothAdapter',
'startBluetoothDevicesDiscovery',
'onBluetoothDeviceFound',
'stopBluetoothDevicesDiscovery',
'onBluetoothAdapterStateChange',
'getConnectedBluetoothDevices',
'getBluetoothDevices',
'getBluetoothAdapterState',
'closeBluetoothAdapter',
'writeBLECharacteristicValue',
'readBLECharacteristicValue',
'onBLEConnectionStateChange',
'onBLECharacteristicValueChange',
'notifyBLECharacteristicValueChange',
'getBLEDeviceServices',
'getBLEDeviceCharacteristics',
'createBLEConnection',
'closeBLEConnection',
'onBeaconServiceChange',
'onBeaconUpdate',
'getBeacons',
'startBeaconDiscovery',
'stopBeaconDiscovery',
'setBackgroundColor',
'setBackgroundTextStyle',
'createAnimation',
'loadFontFace',
'createIntersectionObserver',
'getProvider',
'login',
'checkSession',
'getUserInfo',
'share',
'onShareAppMessage',
'showShareMenu',
'hideShareMenu',
'requestPayment',
'subscribePush',
'unsubscribePush',
......
......@@ -15,7 +15,9 @@ const _createInput = function (options) {
'visibility': 'hidden',
'z-index': -999,
'width': 0,
'height': 0
'height': 0,
'top': 0,
'left': 0
})
inputEl.accept = 'image/*'
if (options.count > 1) {
......
......@@ -15,7 +15,9 @@ const _createInput = function (options) {
'visibility': 'hidden',
'z-index': -999,
'width': 0,
'height': 0
'height': 0,
'top': 0,
'left': 0
})
inputEl.accept = 'video/*'
// 经过测试,仅能限制只通过相机拍摄,不能限制只允许从相册选择。
......
......@@ -81,7 +81,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 = {}
......
export const mocks = ['nodeId']
export function initPage (pageOptions) {
initComponent(pageOptions)
}
......
const instances = Object.create(null)
export const mocks = ['__route__', '__webviewId__', '__nodeid__']
export function initPage (pageOptions) {
initComponent(pageOptions)
}
......
export const mocks = ['__route__', '__wxExparserNodeId__', '__wxWebviewId__']
export function initPage () {
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册