diff --git a/build/rollup.config.mp.js b/build/rollup.config.mp.js
index 9637e733cdc2a31cfd342a49b203630b45289da5..e6eeba29541ba8362f10d41a75bb2ed3cf9372c4 100644
--- a/build/rollup.config.mp.js
+++ b/build/rollup.config.mp.js
@@ -23,6 +23,10 @@ const PLATFORMS = {
prefix: 'tt',
title: '头条小程序'
},
+ 'mp-kuaishou': {
+ prefix: 'ks',
+ title: '快手小程序'
+ },
'quickapp-webview': {
prefix: 'qa',
title: '快应用(Webview)版'
@@ -73,4 +77,4 @@ module.exports = {
})
],
external: ['vue']
-}
+}
diff --git a/package.json b/package.json
index daddb041072805b75f2b626fb29948ecef39ddcd..67bcb24fb2cd2d209ef3436fb1700e979d8bf736 100644
--- a/package.json
+++ b/package.json
@@ -18,6 +18,7 @@
"build:mp-baidu": "cross-env UNI_PLATFORM=mp-baidu rollup -c build/rollup.config.mp.js",
"build:mp-alipay": "cross-env UNI_PLATFORM=mp-alipay rollup -c build/rollup.config.mp.js",
"build:mp-toutiao": "cross-env UNI_PLATFORM=mp-toutiao rollup -c build/rollup.config.mp.js",
+ "build:mp-kuaishou": "cross-env UNI_PLATFORM=mp-kuaishou rollup -c build/rollup.config.mp.js",
"build:quickapp-webview": "cross-env UNI_PLATFORM=quickapp-webview rollup -c build/rollup.config.mp.js",
"build:mp-weixin:mp": "cross-env UNI_PLATFORM=mp-weixin UNI_MP=true rollup -c build/rollup.config.mp.js",
"build:mp-weixin:wxs": "rollup -c build/rollup.config.wxs.js",
diff --git a/packages/uni-cli-shared/lib/platform.js b/packages/uni-cli-shared/lib/platform.js
index f8f15fed8a7965d5b43e9e88c106aeea5331d9bd..923600ddbec2e4798291b3c83940d3dfd245312d 100644
--- a/packages/uni-cli-shared/lib/platform.js
+++ b/packages/uni-cli-shared/lib/platform.js
@@ -146,4 +146,4 @@ module.exports = {
]
}
}
-}
+}
diff --git a/packages/uni-mp-kuaishou/dist/index.js b/packages/uni-mp-kuaishou/dist/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..2710fb25a9ee4427067f89faec45b4c23583773f
--- /dev/null
+++ b/packages/uni-mp-kuaishou/dist/index.js
@@ -0,0 +1,1505 @@
+import Vue from 'vue';
+
+const _toString = Object.prototype.toString;
+const hasOwnProperty = Object.prototype.hasOwnProperty;
+
+function isFn (fn) {
+ return typeof fn === 'function'
+}
+
+function isStr (str) {
+ return typeof str === 'string'
+}
+
+function isPlainObject (obj) {
+ return _toString.call(obj) === '[object Object]'
+}
+
+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 HOOKS = [
+ 'invoke',
+ 'success',
+ 'fail',
+ 'complete',
+ 'returnValue'
+];
+
+const globalInterceptors = {};
+const scopedInterceptors = {};
+
+function mergeHook (parentVal, childVal) {
+ const res = childVal
+ ? parentVal
+ ? parentVal.concat(childVal)
+ : Array.isArray(childVal)
+ ? childVal : [childVal]
+ : parentVal;
+ return res
+ ? dedupeHooks(res)
+ : res
+}
+
+function dedupeHooks (hooks) {
+ const res = [];
+ for (let i = 0; i < hooks.length; i++) {
+ if (res.indexOf(hooks[i]) === -1) {
+ res.push(hooks[i]);
+ }
+ }
+ return res
+}
+
+function removeHook (hooks, hook) {
+ const index = hooks.indexOf(hook);
+ if (index !== -1) {
+ hooks.splice(index, 1);
+ }
+}
+
+function mergeInterceptorHook (interceptor, option) {
+ Object.keys(option).forEach(hook => {
+ if (HOOKS.indexOf(hook) !== -1 && isFn(option[hook])) {
+ interceptor[hook] = mergeHook(interceptor[hook], option[hook]);
+ }
+ });
+}
+
+function removeInterceptorHook (interceptor, option) {
+ if (!interceptor || !option) {
+ return
+ }
+ Object.keys(option).forEach(hook => {
+ if (HOOKS.indexOf(hook) !== -1 && isFn(option[hook])) {
+ removeHook(interceptor[hook], option[hook]);
+ }
+ });
+}
+
+function addInterceptor (method, option) {
+ if (typeof method === 'string' && isPlainObject(option)) {
+ mergeInterceptorHook(scopedInterceptors[method] || (scopedInterceptors[method] = {}), option);
+ } else if (isPlainObject(method)) {
+ mergeInterceptorHook(globalInterceptors, method);
+ }
+}
+
+function removeInterceptor (method, option) {
+ if (typeof method === 'string') {
+ if (isPlainObject(option)) {
+ removeInterceptorHook(scopedInterceptors[method], option);
+ } else {
+ delete scopedInterceptors[method];
+ }
+ } else if (isPlainObject(method)) {
+ removeInterceptorHook(globalInterceptors, method);
+ }
+}
+
+function wrapperHook (hook) {
+ return function (data) {
+ return hook(data) || data
+ }
+}
+
+function isPromise (obj) {
+ return !!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function'
+}
+
+function queue (hooks, data) {
+ let promise = false;
+ for (let i = 0; i < hooks.length; i++) {
+ const hook = hooks[i];
+ if (promise) {
+ promise = Promise.then(wrapperHook(hook));
+ } else {
+ const res = hook(data);
+ if (isPromise(res)) {
+ promise = Promise.resolve(res);
+ }
+ if (res === false) {
+ return {
+ then () {}
+ }
+ }
+ }
+ }
+ return promise || {
+ then (callback) {
+ return callback(data)
+ }
+ }
+}
+
+function wrapperOptions (interceptor, options = {}) {
+ ['success', 'fail', 'complete'].forEach(name => {
+ if (Array.isArray(interceptor[name])) {
+ const oldCallback = options[name];
+ options[name] = function callbackInterceptor (res) {
+ queue(interceptor[name], res).then((res) => {
+ /* eslint-disable no-mixed-operators */
+ return isFn(oldCallback) && oldCallback(res) || res
+ });
+ };
+ }
+ });
+ return options
+}
+
+function wrapperReturnValue (method, returnValue) {
+ const returnValueHooks = [];
+ if (Array.isArray(globalInterceptors.returnValue)) {
+ returnValueHooks.push(...globalInterceptors.returnValue);
+ }
+ const interceptor = scopedInterceptors[method];
+ if (interceptor && Array.isArray(interceptor.returnValue)) {
+ returnValueHooks.push(...interceptor.returnValue);
+ }
+ returnValueHooks.forEach(hook => {
+ returnValue = hook(returnValue) || returnValue;
+ });
+ return returnValue
+}
+
+function getApiInterceptorHooks (method) {
+ const interceptor = Object.create(null);
+ Object.keys(globalInterceptors).forEach(hook => {
+ if (hook !== 'returnValue') {
+ interceptor[hook] = globalInterceptors[hook].slice();
+ }
+ });
+ const scopedInterceptor = scopedInterceptors[method];
+ if (scopedInterceptor) {
+ Object.keys(scopedInterceptor).forEach(hook => {
+ if (hook !== 'returnValue') {
+ interceptor[hook] = (interceptor[hook] || []).concat(scopedInterceptor[hook]);
+ }
+ });
+ }
+ return interceptor
+}
+
+function invokeApi (method, api, options, ...params) {
+ const interceptor = getApiInterceptorHooks(method);
+ if (interceptor && Object.keys(interceptor).length) {
+ if (Array.isArray(interceptor.invoke)) {
+ const res = queue(interceptor.invoke, options);
+ return res.then((options) => {
+ return api(wrapperOptions(interceptor, options), ...params)
+ })
+ } else {
+ return api(wrapperOptions(interceptor, options), ...params)
+ }
+ }
+ return api(options, ...params)
+}
+
+const promiseInterceptor = {
+ returnValue (res) {
+ if (!isPromise(res)) {
+ return res
+ }
+ return res.then(res => {
+ return res[1]
+ }).catch(res => {
+ return res[0]
+ })
+ }
+};
+
+const SYNC_API_RE =
+ /^\$|restoreGlobal|getCurrentSubNVue|getMenuButtonBoundingClientRect|^report|interceptors|Interceptor$|getSubNVueById|requireNativePlugin|upx2px|hideKeyboard|canIUse|^create|Sync$|Manager$|base64ToArrayBuffer|arrayBufferToBase64/;
+
+const CONTEXT_API_RE = /^create|Manager$/;
+
+const CALLBACK_API_RE = /^on/;
+
+function isContextApi (name) {
+ return CONTEXT_API_RE.test(name)
+}
+function isSyncApi (name) {
+ return SYNC_API_RE.test(name)
+}
+
+function isCallbackApi (name) {
+ return CALLBACK_API_RE.test(name) && name !== 'onPush'
+}
+
+function handlePromise (promise) {
+ return promise.then(data => {
+ return [null, data]
+ })
+ .catch(err => [err])
+}
+
+function shouldPromise (name) {
+ if (
+ isContextApi(name) ||
+ isSyncApi(name) ||
+ isCallbackApi(name)
+ ) {
+ return false
+ }
+ return true
+}
+
+function promisify (name, api) {
+ if (!shouldPromise(name)) {
+ return api
+ }
+ return function promiseApi (options = {}, ...params) {
+ if (isFn(options.success) || isFn(options.fail) || isFn(options.complete)) {
+ return wrapperReturnValue(name, invokeApi(name, api, options, ...params))
+ }
+ return wrapperReturnValue(name, handlePromise(new Promise((resolve, reject) => {
+ invokeApi(name, api, Object.assign({}, options, {
+ success: resolve,
+ fail: reject
+ }), ...params);
+ /* eslint-disable no-extend-native */
+ if (!Promise.prototype.finally) {
+ Promise.prototype.finally = function (callback) {
+ const promise = this.constructor;
+ return this.then(
+ value => promise.resolve(callback()).then(() => value),
+ reason => promise.resolve(callback()).then(() => {
+ throw reason
+ })
+ )
+ };
+ }
+ })))
+ }
+}
+
+const EPS = 1e-4;
+const BASE_DEVICE_WIDTH = 750;
+let isIOS = false;
+let deviceWidth = 0;
+let deviceDPR = 0;
+
+function checkDeviceWidth () {
+ const {
+ platform,
+ pixelRatio,
+ windowWidth
+ } = ks.getSystemInfoSync(); // uni=>ks runtime 编译目标是 uni 对象,内部不允许直接使用 uni
+
+ deviceWidth = windowWidth;
+ deviceDPR = pixelRatio;
+ isIOS = platform === 'ios';
+}
+
+function upx2px (number, newDeviceWidth) {
+ if (deviceWidth === 0) {
+ checkDeviceWidth();
+ }
+
+ number = Number(number);
+ if (number === 0) {
+ return 0
+ }
+ let result = (number / BASE_DEVICE_WIDTH) * (newDeviceWidth || deviceWidth);
+ if (result < 0) {
+ result = -result;
+ }
+ result = Math.floor(result + EPS);
+ if (result === 0) {
+ if (deviceDPR === 1 || !isIOS) {
+ return 1
+ } else {
+ return 0.5
+ }
+ }
+ return number < 0 ? -result : result
+}
+
+const interceptors = {
+ promiseInterceptor
+};
+
+
+
+var baseApi = /*#__PURE__*/Object.freeze({
+ __proto__: null,
+ upx2px: upx2px,
+ interceptors: interceptors,
+ addInterceptor: addInterceptor,
+ removeInterceptor: removeInterceptor
+});
+
+var previewImage = {
+ args (fromArgs) {
+ let currentIndex = parseInt(fromArgs.current);
+ if (isNaN(currentIndex)) {
+ return
+ }
+ const urls = fromArgs.urls;
+ if (!Array.isArray(urls)) {
+ return
+ }
+ const len = urls.length;
+ if (!len) {
+ return
+ }
+ if (currentIndex < 0) {
+ currentIndex = 0;
+ } else if (currentIndex >= len) {
+ currentIndex = len - 1;
+ }
+ if (currentIndex > 0) {
+ fromArgs.current = urls[currentIndex];
+ fromArgs.urls = urls.filter(
+ (item, index) => index < currentIndex ? item !== urls[currentIndex] : true
+ );
+ } else {
+ fromArgs.current = urls[0];
+ }
+ return {
+ indicator: false,
+ loop: false
+ }
+ }
+};
+
+const protocols = {
+ previewImage
+};
+const todos = [
+ 'vibrate'
+];
+const canIUses = [];
+
+const CALLBACKS = ['success', 'fail', 'cancel', 'complete'];
+
+function processCallback (methodName, method, returnValue) {
+ return function (res) {
+ return method(processReturnValue(methodName, res, returnValue))
+ }
+}
+
+function processArgs (methodName, fromArgs, argsOption = {}, returnValue = {}, keepFromArgs = false) {
+ if (isPlainObject(fromArgs)) { // 一般 api 的参数解析
+ const toArgs = keepFromArgs === true ? fromArgs : {}; // returnValue 为 false 时,说明是格式化返回值,直接在返回值对象上修改赋值
+ if (isFn(argsOption)) {
+ argsOption = argsOption(fromArgs, toArgs) || {};
+ }
+ for (let key in fromArgs) {
+ if (hasOwn(argsOption, key)) {
+ let keyOption = argsOption[key];
+ if (isFn(keyOption)) {
+ keyOption = keyOption(fromArgs[key], fromArgs, toArgs);
+ }
+ if (!keyOption) { // 不支持的参数
+ console.warn(`快手小程序 ${methodName}暂不支持${key}`);
+ } else if (isStr(keyOption)) { // 重写参数 key
+ toArgs[keyOption] = fromArgs[key];
+ } else if (isPlainObject(keyOption)) { // {name:newName,value:value}可重新指定参数 key:value
+ toArgs[keyOption.name ? keyOption.name : key] = keyOption.value;
+ }
+ } else if (CALLBACKS.indexOf(key) !== -1) {
+ toArgs[key] = processCallback(methodName, fromArgs[key], returnValue);
+ } else {
+ if (!keepFromArgs) {
+ toArgs[key] = fromArgs[key];
+ }
+ }
+ }
+ return toArgs
+ } else if (isFn(fromArgs)) {
+ fromArgs = processCallback(methodName, fromArgs, returnValue);
+ }
+ return fromArgs
+}
+
+function processReturnValue (methodName, res, returnValue, keepReturnValue = false) {
+ if (isFn(protocols.returnValue)) { // 处理通用 returnValue
+ res = protocols.returnValue(methodName, res);
+ }
+ return processArgs(methodName, res, returnValue, {}, keepReturnValue)
+}
+
+function wrapper (methodName, method) {
+ if (hasOwn(protocols, methodName)) {
+ const protocol = protocols[methodName];
+ if (!protocol) { // 暂不支持的 api
+ return function () {
+ console.error(`快手小程序 暂不支持${methodName}`);
+ }
+ }
+ return function (arg1, arg2) { // 目前 api 最多两个参数
+ let options = protocol;
+ if (isFn(protocol)) {
+ options = protocol(arg1);
+ }
+
+ arg1 = processArgs(methodName, arg1, options.args, options.returnValue);
+
+ const args = [arg1];
+ if (typeof arg2 !== 'undefined') {
+ args.push(arg2);
+ }
+ const returnValue = ks[options.name || methodName].apply(ks, args);
+ if (isSyncApi(methodName)) { // 同步 api
+ return processReturnValue(methodName, returnValue, options.returnValue, isContextApi(methodName))
+ }
+ return returnValue
+ }
+ }
+ return method
+}
+
+const todoApis = Object.create(null);
+
+const TODOS = [
+ 'onTabBarMidButtonTap',
+ 'subscribePush',
+ 'unsubscribePush',
+ 'onPush',
+ 'offPush',
+ 'share'
+];
+
+function createTodoApi (name) {
+ return function todoApi ({
+ fail,
+ complete
+ }) {
+ const res = {
+ errMsg: `${name}:fail:暂不支持 ${name} 方法`
+ };
+ isFn(fail) && fail(res);
+ isFn(complete) && complete(res);
+ }
+}
+
+TODOS.forEach(function (name) {
+ todoApis[name] = createTodoApi(name);
+});
+
+var providers = {
+ oauth: ['kuaishou'],
+ share: ['kuaishou'],
+ payment: ['kspay'],
+ push: ['kuaishou']
+};
+
+function getProvider ({
+ service,
+ success,
+ fail,
+ complete
+}) {
+ let res = false;
+ if (providers[service]) {
+ res = {
+ errMsg: 'getProvider:ok',
+ service,
+ provider: providers[service]
+ };
+ isFn(success) && success(res);
+ } else {
+ res = {
+ errMsg: 'getProvider:fail:服务[' + service + ']不存在'
+ };
+ isFn(fail) && fail(res);
+ }
+ isFn(complete) && complete(res);
+}
+
+var extraApi = /*#__PURE__*/Object.freeze({
+ __proto__: null,
+ getProvider: getProvider
+});
+
+const getEmitter = (function () {
+ if (typeof getUniEmitter === 'function') {
+ /* eslint-disable no-undef */
+ return getUniEmitter
+ }
+ let Emitter;
+ return function getUniEmitter () {
+ if (!Emitter) {
+ Emitter = new Vue();
+ }
+ return Emitter
+ }
+})();
+
+function apply (ctx, method, args) {
+ return ctx[method].apply(ctx, args)
+}
+
+function $on () {
+ return apply(getEmitter(), '$on', [...arguments])
+}
+function $off () {
+ return apply(getEmitter(), '$off', [...arguments])
+}
+function $once () {
+ return apply(getEmitter(), '$once', [...arguments])
+}
+function $emit () {
+ return apply(getEmitter(), '$emit', [...arguments])
+}
+
+var eventApi = /*#__PURE__*/Object.freeze({
+ __proto__: null,
+ $on: $on,
+ $off: $off,
+ $once: $once,
+ $emit: $emit
+});
+
+
+
+var api = /*#__PURE__*/Object.freeze({
+ __proto__: null
+});
+
+const MPPage = Page;
+const MPComponent = Component;
+
+const customizeRE = /:/g;
+
+const customize = cached((str) => {
+ return camelize(str.replace(customizeRE, '-'))
+});
+
+function initTriggerEvent (mpInstance) {
+ const oldTriggerEvent = mpInstance.triggerEvent;
+ mpInstance.triggerEvent = function (event, ...args) {
+ return oldTriggerEvent.apply(mpInstance, [customize(event), ...args])
+ };
+}
+
+function initHook (name, options) {
+ const oldHook = options[name];
+ if (!oldHook) {
+ options[name] = function () {
+ initTriggerEvent(this);
+ };
+ } else {
+ options[name] = function (...args) {
+ initTriggerEvent(this);
+ return oldHook.apply(this, args)
+ };
+ }
+}
+
+Page = function (options = {}) {
+ initHook('onLoad', options);
+ return MPPage(options)
+};
+
+Component = function (options = {}) {
+ initHook('created', options);
+ return MPComponent(options)
+};
+
+const PAGE_EVENT_HOOKS = [
+ 'onPullDownRefresh',
+ 'onReachBottom',
+ 'onShareAppMessage',
+ 'onPageScroll',
+ 'onResize',
+ 'onTabItemTap'
+];
+
+function initMocks (vm, mocks) {
+ const mpInstance = vm.$mp[vm.mpType];
+ mocks.forEach(mock => {
+ if (hasOwn(mpInstance, mock)) {
+ vm[mock] = mpInstance[mock];
+ }
+ });
+}
+
+function hasHook (hook, vueOptions) {
+ if (!vueOptions) {
+ return true
+ }
+
+ if (Vue.options && Array.isArray(Vue.options[hook])) {
+ return true
+ }
+
+ vueOptions = vueOptions.default || vueOptions;
+
+ if (isFn(vueOptions)) {
+ if (isFn(vueOptions.extendOptions[hook])) {
+ return true
+ }
+ if (vueOptions.super &&
+ vueOptions.super.options &&
+ Array.isArray(vueOptions.super.options[hook])) {
+ return true
+ }
+ return false
+ }
+
+ if (isFn(vueOptions[hook])) {
+ return true
+ }
+ const mixins = vueOptions.mixins;
+ if (Array.isArray(mixins)) {
+ return !!mixins.find(mixin => hasHook(hook, mixin))
+ }
+}
+
+function initHooks (mpOptions, hooks, vueOptions) {
+ hooks.forEach(hook => {
+ if (hasHook(hook, vueOptions)) {
+ mpOptions[hook] = function (args) {
+ return this.$vm && this.$vm.__call_hook(hook, args)
+ };
+ }
+ });
+}
+
+function initVueComponent (Vue, vueOptions) {
+ vueOptions = vueOptions.default || vueOptions;
+ let VueComponent;
+ if (isFn(vueOptions)) {
+ VueComponent = vueOptions;
+ vueOptions = VueComponent.extendOptions;
+ } else {
+ VueComponent = Vue.extend(vueOptions);
+ }
+ return [VueComponent, vueOptions]
+}
+
+function initSlots (vm, vueSlots) {
+ if (Array.isArray(vueSlots) && vueSlots.length) {
+ const $slots = Object.create(null);
+ vueSlots.forEach(slotName => {
+ $slots[slotName] = true;
+ });
+ vm.$scopedSlots = vm.$slots = $slots;
+ }
+}
+
+function initVueIds (vueIds, mpInstance) {
+ vueIds = (vueIds || '').split(',');
+ const len = vueIds.length;
+
+ if (len === 1) {
+ mpInstance._$vueId = vueIds[0];
+ } else if (len === 2) {
+ mpInstance._$vueId = vueIds[0];
+ mpInstance._$vuePid = vueIds[1];
+ }
+}
+
+function initData (vueOptions, context) {
+ let data = vueOptions.data || {};
+ const methods = vueOptions.methods || {};
+
+ 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 (name) {
+ return function observer (newVal, oldVal) {
+ if (this.$vm) {
+ this.$vm[name] = newVal; // 为了触发其他非 render watcher
+ }
+ }
+}
+
+function initBehaviors (vueOptions, initBehavior) {
+ 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://', `${"ks"}://`));
+ if (behavior === 'uni://form-field') {
+ if (Array.isArray(vueProps)) {
+ vueProps.push('name');
+ vueProps.push('value');
+ } else {
+ vueProps['name'] = {
+ type: String,
+ default: ''
+ };
+ vueProps['value'] = {
+ type: [String, Number, Boolean, Array, Object, Date],
+ default: ''
+ };
+ }
+ }
+ });
+ }
+ if (isPlainObject(vueExtends) && vueExtends.props) {
+ behaviors.push(
+ initBehavior({
+ properties: initProperties(vueExtends.props, true)
+ })
+ );
+ }
+ if (Array.isArray(vueMixins)) {
+ vueMixins.forEach(vueMixin => {
+ if (isPlainObject(vueMixin) && vueMixin.props) {
+ behaviors.push(
+ initBehavior({
+ properties: initProperties(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 initProperties (props, isBehavior = false, file = '') {
+ const properties = {};
+ if (!isBehavior) {
+ properties.vueId = {
+ type: String,
+ value: ''
+ };
+ 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(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);
+
+ properties[key] = {
+ type: PROP_TYPES.indexOf(opts.type) !== -1 ? opts.type : null,
+ value,
+ observer: createObserver(key)
+ };
+ } else { // content:String
+ const type = parsePropType(key, opts);
+ properties[key] = {
+ type: PROP_TYPES.indexOf(type) !== -1 ? type : null,
+ observer: createObserver(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 isMatchEventType (eventType, optType) {
+ return (eventType === optType) ||
+ (
+ optType === 'regionchange' &&
+ (
+ eventType === 'begin' ||
+ eventType === 'end'
+ )
+ )
+}
+
+function handleEvent (event) {
+ event = wrapper$1(event);
+
+ // [['tap',[['handle',[1,2,a]],['handle1',[1,2,a]]]]]
+ const dataset = (event.currentTarget || event.target).dataset;
+ if (!dataset) {
+ return console.warn(`事件信息不存在`)
+ }
+ const eventOpts = dataset.eventOpts || dataset['event-opts']; // 支付宝 web-view 组件 dataset 非驼峰
+ if (!eventOpts) {
+ return console.warn(`事件信息不存在`)
+ }
+
+ // [['handle',[1,2,a]],['handle1',[1,2,a]]]
+ const eventType = event.type;
+
+ const ret = [];
+
+ 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 && isMatchEventType(eventType, type)) {
+ eventsArray.forEach(eventArray => {
+ const methodName = eventArray[0];
+ if (methodName) {
+ let handlerCtx = this.$vm;
+ if (
+ handlerCtx.$options.generic &&
+ handlerCtx.$parent &&
+ handlerCtx.$parent.$parent
+ ) { // mp-weixin,mp-toutiao 抽象节点模拟 scoped slots
+ handlerCtx = handlerCtx.$parent.$parent;
+ }
+ if (methodName === '$emit') {
+ handlerCtx.$emit.apply(handlerCtx,
+ processEventArgs(
+ this.$vm,
+ event,
+ eventArray[1],
+ eventArray[2],
+ isCustom,
+ methodName
+ ));
+ return
+ }
+ const handler = handlerCtx[methodName];
+ if (!isFn(handler)) {
+ throw new Error(` _vm.${methodName} is not a function`)
+ }
+ if (isOnce) {
+ if (handler.once) {
+ return
+ }
+ handler.once = true;
+ }
+ ret.push(handler.apply(handlerCtx, processEventArgs(
+ this.$vm,
+ event,
+ eventArray[1],
+ eventArray[2],
+ isCustom,
+ methodName
+ )));
+ }
+ });
+ }
+ });
+
+ if (
+ eventType === 'input' &&
+ ret.length === 1 &&
+ typeof ret[0] !== 'undefined'
+ ) {
+ return ret[0]
+ }
+}
+
+const hooks = [
+ 'onShow',
+ 'onHide',
+ 'onError',
+ 'onPageNotFound'
+];
+
+function parseBaseApp (vm, {
+ mocks,
+ initRefs
+}) {
+ if (vm.$options.store) {
+ Vue.prototype.$store = vm.$options.store;
+ }
+
+ Vue.prototype.mpHost = "mp-kuaishou";
+
+ Vue.mixin({
+ beforeCreate () {
+ if (!this.$options.mpType) {
+ return
+ }
+
+ this.mpType = this.$options.mpType;
+
+ this.$mp = {
+ data: {},
+ [this.mpType]: this.$options.mpInstance
+ };
+
+ this.$scope = this.$options.mpInstance;
+
+ delete this.$options.mpType;
+ delete this.$options.mpInstance;
+
+ if (this.mpType !== 'app') {
+ initRefs(this);
+ initMocks(this, mocks);
+ }
+ }
+ });
+
+ const appOptions = {
+ onLaunch (args) {
+ if (this.$vm) { // 已经初始化过了,主要是为了百度,百度 onShow 在 onLaunch 之前
+ return
+ }
+
+ this.$vm = vm;
+
+ this.$vm.$mp = {
+ app: this
+ };
+
+ this.$vm.$scope = this;
+ // vm 上也挂载 globalData
+ this.$vm.globalData = this.globalData;
+
+ this.$vm._isMounted = true;
+ this.$vm.__call_hook('mounted', args);
+
+ this.$vm.__call_hook('onLaunch', args);
+ }
+ };
+
+ // 兼容旧版本 globalData
+ appOptions.globalData = vm.$options.globalData || {};
+ // 将 methods 中的方法挂在 getApp() 中
+ const methods = vm.$options.methods;
+ if (methods) {
+ Object.keys(methods).forEach(name => {
+ appOptions[name] = methods[name];
+ });
+ }
+
+ initHooks(appOptions, hooks);
+
+ return appOptions
+}
+
+/* 快手也使用__wxExparserNodeId__和__wxWebviewId__ */
+const mocks = ['__route__', '__wxExparserNodeId__', '__wxWebviewId__'];
+
+function findVmByVueId (vm, vuePid) {
+ const $children = vm.$children;
+ // 优先查找直属
+ let parentVm = $children.find(childVm => childVm.$scope._$vueId === vuePid);
+ if (parentVm) {
+ return parentVm
+ }
+ // 反向递归查找
+ for (let i = $children.length - 1; i >= 0; i--) {
+ parentVm = findVmByVueId($children[i], vuePid);
+ if (parentVm) {
+ return parentVm
+ }
+ }
+}
+
+function initBehavior (options) {
+ return Behavior(options)
+}
+
+function isPage () {
+ return !!this.route
+}
+
+function initRelation (detail) {
+ this.triggerEvent('__l', detail);
+}
+
+function initRefs (vm) {
+ const mpInstance = vm.$scope;
+ Object.defineProperty(vm, '$refs', {
+ get () {
+ const $refs = {};
+ const components = mpInstance.selectAllComponents('.vue-ref');
+ components.forEach(component => {
+ const ref = component.dataset.ref;
+ $refs[ref] = component.$vm || component;
+ });
+ const forComponents = mpInstance.selectAllComponents('.vue-ref-in-for');
+ forComponents.forEach(component => {
+ const ref = component.dataset.ref;
+ if (!$refs[ref]) {
+ $refs[ref] = [];
+ }
+ $refs[ref].push(component.$vm || component);
+ });
+ return $refs
+ }
+ });
+}
+
+function handleLink (event) {
+ const {
+ vuePid,
+ vueOptions
+ } = event.detail || event.value; // detail 是微信,value 是百度(dipatch)
+
+ let parentVm;
+
+ if (vuePid) {
+ parentVm = findVmByVueId(this.$vm, vuePid);
+ }
+
+ if (!parentVm) {
+ parentVm = this.$vm;
+ }
+
+ vueOptions.parent = parentVm;
+}
+
+function parseApp (vm) {
+ return parseBaseApp(vm, {
+ mocks,
+ initRefs
+ })
+}
+
+function createApp (vm) {
+ App(parseApp(vm));
+ return vm
+}
+
+function parseBaseComponent (vueComponentOptions, {
+ isPage,
+ initRelation
+} = {}) {
+ let [VueComponent, vueOptions] = initVueComponent(Vue, vueComponentOptions);
+
+ const options = {
+ multipleSlots: true,
+ addGlobalClass: true
+ };
+
+ const componentOptions = {
+ options,
+ data: initData(vueOptions, Vue.prototype),
+ behaviors: initBehaviors(vueOptions, initBehavior),
+ properties: initProperties(vueOptions.props, false, vueOptions.__file),
+ lifetimes: {
+ attached () {
+ const properties = this.properties;
+
+ const options = {
+ mpType: isPage.call(this) ? 'page' : 'component',
+ mpInstance: this,
+ propsData: properties
+ };
+
+ initVueIds(properties.vueId, this);
+
+ // 处理父子关系
+ initRelation.call(this, {
+ vuePid: this._$vuePid,
+ vueOptions: options
+ });
+
+ // 初始化 vue 实例
+ this.$vm = new VueComponent(options);
+
+ // 处理$slots,$scopedSlots(暂不支持动态变化$slots)
+ initSlots(this.$vm, properties.vueSlots);
+
+ // 触发首次 setData
+ this.$vm.$mount();
+ },
+ ready () {
+ // 当组件 props 默认值为 true,初始化时传入 false 会导致 created,ready 触发, 但 attached 不触发
+ // https://developers.weixin.qq.com/community/develop/doc/00066ae2844cc0f8eb883e2a557800
+ if (this.$vm) {
+ this.$vm._isMounted = true;
+ this.$vm.__call_hook('mounted');
+ this.$vm.__call_hook('onReady');
+ }
+ },
+ detached () {
+ this.$vm.$destroy();
+ }
+ },
+ pageLifetimes: {
+ show (args) {
+ this.$vm && 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: {
+ __l: handleLink,
+ __e: handleEvent
+ }
+ };
+
+ if (Array.isArray(vueOptions.wxsCallMethods)) {
+ vueOptions.wxsCallMethods.forEach(callMethod => {
+ componentOptions.methods[callMethod] = function (args) {
+ return this.$vm[callMethod](args)
+ };
+ });
+ }
+
+ if (isPage) {
+ return componentOptions
+ }
+ return [componentOptions, VueComponent]
+}
+
+function parseComponent (vueComponentOptions) {
+ return parseBaseComponent(vueComponentOptions, {
+ isPage,
+ initRelation
+ })
+}
+
+const hooks$1 = [
+ 'onShow',
+ 'onHide',
+ 'onUnload'
+];
+
+hooks$1.push(...PAGE_EVENT_HOOKS);
+
+function parseBasePage (vuePageOptions, {
+ isPage,
+ initRelation
+}) {
+ const pageOptions = parseComponent(vuePageOptions);
+
+ initHooks(pageOptions.methods, hooks$1, vuePageOptions);
+
+ pageOptions.methods.onLoad = function (args) {
+ this.$vm.$mp.query = args; // 兼容 mpvue
+ this.$vm.__call_hook('onLoad', args);
+ };
+
+ return pageOptions
+}
+
+function parsePage (vuePageOptions) {
+ return parseBasePage(vuePageOptions, {
+ isPage,
+ initRelation
+ })
+}
+
+function createPage (vuePageOptions) {
+ {
+ return Component(parsePage(vuePageOptions))
+ }
+}
+
+function createComponent (vueOptions) {
+ {
+ return Component(parseComponent(vueOptions))
+ }
+}
+
+todos.forEach(todoApi => {
+ protocols[todoApi] = false;
+});
+
+canIUses.forEach(canIUseApi => {
+ const apiName = protocols[canIUseApi] && protocols[canIUseApi].name ? protocols[canIUseApi].name
+ : canIUseApi;
+ if (!ks.canIUse(apiName)) {
+ protocols[canIUseApi] = false;
+ }
+});
+
+let uni = {};
+
+if (typeof Proxy !== 'undefined' && "mp-kuaishou" !== 'app-plus') {
+ uni = new Proxy({}, {
+ get (target, name) {
+ if (target[name]) {
+ return target[name]
+ }
+ if (baseApi[name]) {
+ return baseApi[name]
+ }
+ 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 (eventApi[name]) {
+ return eventApi[name]
+ }
+ if (!hasOwn(ks, name) && !hasOwn(protocols, name)) {
+ return
+ }
+ return promisify(name, wrapper(name, ks[name]))
+ },
+ set (target, name, value) {
+ target[name] = value;
+ return true
+ }
+ });
+} else {
+ Object.keys(baseApi).forEach(name => {
+ uni[name] = baseApi[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(eventApi).forEach(name => {
+ uni[name] = eventApi[name];
+ });
+
+ Object.keys(api).forEach(name => {
+ uni[name] = promisify(name, api[name]);
+ });
+
+ Object.keys(ks).forEach(name => {
+ if (hasOwn(ks, name) || hasOwn(protocols, name)) {
+ uni[name] = promisify(name, wrapper(name, ks[name]));
+ }
+ });
+}
+
+ks.createApp = createApp;
+ks.createPage = createPage;
+ks.createComponent = createComponent;
+
+var uni$1 = uni;
+
+export default uni$1;
+export { createApp, createComponent, createPage };
diff --git a/packages/uni-mp-kuaishou/package.json b/packages/uni-mp-kuaishou/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..c7ef7f354d6aaec77faea7bcfb137ba719cc2902
--- /dev/null
+++ b/packages/uni-mp-kuaishou/package.json
@@ -0,0 +1,16 @@
+{
+ "name": "@dcloudio/uni-mp-kuaishou",
+ "version": "2.0.0-23320190923002",
+ "description": "uni-app mp-kuaishou",
+ "main": "dist/index.js",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/aeroxy/uni-app.git",
+ "directory": "packages/uni-mp-kuaishou"
+ },
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "author": "Aero Wang",
+ "license": "MIT"
+}
diff --git a/packages/uni-stat/src/parameter.js b/packages/uni-stat/src/parameter.js
index 2ac19bc912b8c83bc7d7291e3b58d413f060e922..002f4af0b046d52c03f7fccba858e1cdb8deaf1e 100644
--- a/packages/uni-stat/src/parameter.js
+++ b/packages/uni-stat/src/parameter.js
@@ -75,7 +75,8 @@ export const getPlatformName = () => {
'mp-alipay': 'ali',
'mp-baidu': 'bd',
'mp-toutiao': 'tt',
- 'mp-qq': 'qq'
+ 'mp-qq': 'qq',
+ 'mp-kuaishou': 'ks'
}
return platformList[process.env.VUE_APP_PLATFORM];
}
@@ -385,4 +386,4 @@ const requestData = (done) => {
})
}
});
-}
+}
diff --git a/packages/uni-template-compiler/__tests__/compiler-mp-kuaishou.spec.js b/packages/uni-template-compiler/__tests__/compiler-mp-kuaishou.spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..b2160c16c3fa8d9250d60037785de8f6ba9dc87f
--- /dev/null
+++ b/packages/uni-template-compiler/__tests__/compiler-mp-kuaishou.spec.js
@@ -0,0 +1,90 @@
+const compiler = require('../lib')
+
+function assertCodegen (template, templateCode, renderCode = `with(this){}`, options = {}) {
+ const res = compiler.compile(template, {
+ resourcePath: 'test.wxml',
+ mp: Object.assign({
+ minified: true,
+ isTest: true,
+ platform: 'mp-kuaishou'
+ }, options)
+ })
+
+ expect(res.template).toBe(templateCode)
+
+ if (typeof renderCode === 'function') {
+ renderCode(res)
+ } else {
+ expect(res.render).toBe(renderCode)
+ }
+}
+
+describe('mp:compiler-mp-kuaishou', () => {
+ it('generate scoped slot', () => {
+ assertCodegen(
+ '{{ bar.foo }}',
+ ``,
+ function (res) {
+ expect(res.generic[0]).toBe('test-foo-default')
+ }
+ )
+ assertCodegen(
+ '{{ bar.foo }}',
+ ``,
+ function (res) {
+ expect(res.generic[0]).toBe('test-foo-default')
+ }
+ )
+ })
+
+ it('generate named scoped slot', () => {
+ assertCodegen(
+ '{{ bar.foo }}',
+ ``,
+ function (res) {
+ expect(res.generic[0]).toBe('test-foo-foo')
+ }
+ )
+ assertCodegen(
+ '{{ bar.foo }}',
+ ``,
+ function (res) {
+ expect(res.generic[0]).toBe('test-foo-foo')
+ }
+ )
+ })
+
+ it('generate scoped slot with multiline v-if', () => {
+ assertCodegen(
+ '{{ bar.foo }}',
+ ``,
+ function (res) {
+ expect(res.generic[0]).toBe('test-foo-default')
+ }
+ )
+ assertCodegen(
+ '{{ bar.foo }}',
+ ``,
+ function (res) {
+ expect(res.generic[0]).toBe('test-foo-foo')
+ }
+ )
+ })
+
+ it('generate scoped slot', () => {
+ assertCodegen(// TODO vue-id
+ '{{ user.lastName }}',
+ ``,
+ function (res) {
+ expect(res.componentGenerics['scoped-slots-default']).toBe(true)
+ }
+ )
+ assertCodegen(
+ '{{ user.lastName }}',
+ ``,
+ function (res) {
+ expect(res.componentGenerics['scoped-slots-header']).toBe(true)
+ }
+ )
+ })
+})
diff --git a/packages/uni-template-compiler/lib/platforms/mp-kuaishou.js b/packages/uni-template-compiler/lib/platforms/mp-kuaishou.js
new file mode 100644
index 0000000000000000000000000000000000000000..fd7320675d2926b52624723f98b7364e95725499
--- /dev/null
+++ b/packages/uni-template-compiler/lib/platforms/mp-kuaishou.js
@@ -0,0 +1,4 @@
+const mpWeixin = require('./mp-weixin')
+module.exports = Object.assign({}, mpWeixin, {
+ prefix: 'ks:'
+})
diff --git a/packages/vue-cli-plugin-uni/generator.js b/packages/vue-cli-plugin-uni/generator.js
index e0e202b380eb3d14842fdd9004629ff84cdda5ec..683faba1fe9d702c6860003471857a0b0e84fb01 100644
--- a/packages/vue-cli-plugin-uni/generator.js
+++ b/packages/vue-cli-plugin-uni/generator.js
@@ -16,6 +16,7 @@ module.exports = (api, options, rootOptions) => {
'dev:mp-baidu': 'cross-env NODE_ENV=development UNI_PLATFORM=mp-baidu vue-cli-service uni-build --watch',
'dev:mp-alipay': 'cross-env NODE_ENV=development UNI_PLATFORM=mp-alipay vue-cli-service uni-build --watch',
'dev:mp-toutiao': 'cross-env NODE_ENV=development UNI_PLATFORM=mp-toutiao vue-cli-service uni-build --watch',
+ 'dev:mp-kuaishou': 'cross-env NODE_ENV=development UNI_PLATFORM=mp-kuaishou vue-cli-service uni-build --watch',
'dev:quickapp-native': 'cross-env NODE_ENV=development UNI_PLATFORM=quickapp-native vue-cli-service uni-build --watch',
'dev:quickapp-webview': 'cross-env NODE_ENV=development UNI_PLATFORM=quickapp-webview vue-cli-service uni-build --watch',
'dev:quickapp-webview-huawei': 'cross-env NODE_ENV=development UNI_PLATFORM=quickapp-webview-huawei vue-cli-service uni-build --watch',
@@ -26,6 +27,7 @@ module.exports = (api, options, rootOptions) => {
'build:mp-baidu': 'cross-env NODE_ENV=production UNI_PLATFORM=mp-baidu vue-cli-service uni-build',
'build:mp-alipay': 'cross-env NODE_ENV=production UNI_PLATFORM=mp-alipay vue-cli-service uni-build',
'build:mp-toutiao': 'cross-env NODE_ENV=production UNI_PLATFORM=mp-toutiao vue-cli-service uni-build',
+ 'build:mp-kuaishou': 'cross-env NODE_ENV=production UNI_PLATFORM=mp-kuaishou vue-cli-service uni-build',
'build:quickapp-native': 'cross-env NODE_ENV=production UNI_PLATFORM=quickapp-native vue-cli-service uni-build',
'build:quickapp-webview': 'cross-env NODE_ENV=production UNI_PLATFORM=quickapp-webview vue-cli-service uni-build',
'build:quickapp-webview-huawei': 'cross-env NODE_ENV=production UNI_PLATFORM=quickapp-webview-huawei vue-cli-service uni-build',
@@ -80,4 +82,4 @@ module.exports = (api, options, rootOptions) => {
]
}
})
-}
+}
diff --git a/packages/vue-cli-plugin-uni/packages/@megalo/template-compiler/build.js b/packages/vue-cli-plugin-uni/packages/@megalo/template-compiler/build.js
index f1a1456b7ea54277f63565efb947a5aa326a0fe7..2d51d9c4656e7182e7fa585282a82a91c9ec30aa 100644
--- a/packages/vue-cli-plugin-uni/packages/@megalo/template-compiler/build.js
+++ b/packages/vue-cli-plugin-uni/packages/@megalo/template-compiler/build.js
@@ -742,7 +742,7 @@ if (inBrowser) {
Object.defineProperty(opts, 'passive', ({
get: function get () {
/* istanbul ignore next */
-
+
}
})); // https://github.com/facebook/flow/issues/285
window.addEventListener('test-passive', null, opts);
@@ -781,10 +781,10 @@ var hasSymbol =
/* istanbul ignore if */ // $flow-disable-line
if (typeof Set !== 'undefined' && isNative(Set)) {
// use native Set when available.
-
+
} else {
// a non-standard Set polyfill that only works with primitive keys.
-
+
}
var ASSET_TYPES = [
@@ -1636,19 +1636,19 @@ if (typeof MessageChannel !== 'undefined' && (
)) {
var channel = new MessageChannel();
channel.port1.onmessage = flushCallbacks;
-
+
} else {
/* istanbul ignore next */
-
+
}
// Determine microtask defer implementation.
/* istanbul ignore next, $flow-disable-line */
if (typeof Promise !== 'undefined' && isNative(Promise)) {
-
+
} else {
// fallback to macro
-
+
}
/**
@@ -4748,11 +4748,47 @@ var swan$1 = mergePreset(basePrest, {
}
})
+var ks = mergePreset(basePrest, {
+ prefix: prefix,
+ ext: "ksml",
+ directives: {
+ if: (prefix + "if"),
+ elseif: (prefix + "elif"),
+ else: (prefix + "else"),
+ for: (prefix + "for"),
+ forItem: (prefix + "for-item"),
+ forIndex: (prefix + "for-index"),
+ forKey: (prefix + "key"),
+ on: "bind",
+ onStop: "catch",
+ capture: "capture"
+ },
+ eventTypeMap: eventTypeMap$1,
+ findEventType: findEventType,
+ genBind: function genBind (event, type, tag) {
+ var modifiers = event.modifiers; if ( modifiers === void 0 ) modifiers = {};
+ var isCapture = /!/.test(type);
+ var realType = type.replace(/^[~|!]/, '');
+ var stop = modifiers.stop;
+ var mpType = realType;
+ var binder = stop ? 'catch' : 'bind';
+ binder = isCapture ? ("capture-" + binder) : binder;
+
+ if (type === 'change' && (tag === 'input' || tag === 'textarea')) {
+ mpType = 'blur';
+ } else {
+ mpType = mpType === 'click' ? 'tap' : mpType;
+ }
+ return ("" + binder + mpType)
+ }
+})
+
var presets = {
wechat: wechat,
alipay: alipay,
swan: swan$1,
- tt:tt//fixed by xxxxxx
+ tt: tt, //fixed by xxxxxx
+ ks: ks
}
var vbindReg = /^(v-bind:?|:)/;
@@ -4977,7 +5013,7 @@ function addAttr$1 (node, name, value) {
attrsMap[name] = "" + value;
Object.assign(node, { attrs: attrs, attrsMap: attrsMap });
-
+
}
function isTag (node) {
@@ -5170,7 +5206,7 @@ function walk$1 (node, state) {
} else if (
node.type === TYPE$1.TEXT || node.type === TYPE$1.STATIC_TEXT
) {
-
+
}
}
@@ -5423,7 +5459,7 @@ TemplateGenerator.prototype.genImports = function genImports () {
var imports = ref.imports;
var components = ref._components||new Set();//fixed by xxxxxx
return Object.keys(imports)
- .map(function (name) {
+ .map(function (name) {
//fixed by xxxxxx 过滤 import
// if(process.env.UNI_PLATFORM === 'mp-alipay'){
if(name==='_slots_'){
@@ -5447,14 +5483,14 @@ TemplateGenerator.prototype.genElement = function genElement (el) {
return this.genVHtml(el)
} else if (this.isSlot(el)) {
//fixed by xxxxxx 记录是否定义slot
- this._hasSlot = true;
+ this._hasSlot = true;
return this.genSlot(el)
} else if (this.isComponent(el)) {
//fixed by xxxxxx 记录自定义组件
if(!this._components){
this._components = new Set()
}
- this._components.add(el.tag.toLowerCase().replace(/-/g,''))
+ this._components.add(el.tag.toLowerCase().replace(/-/g,''))
return this.genComponent(el)
} else if (el.type === 1) {
return this.genTag(el)
diff --git a/packages/webpack-uni-pages-loader/lib/platforms/mp-kuaishou/index.js b/packages/webpack-uni-pages-loader/lib/platforms/mp-kuaishou/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..a4209b27d64055c25a4edf402f548ef0964d1f1e
--- /dev/null
+++ b/packages/webpack-uni-pages-loader/lib/platforms/mp-kuaishou/index.js
@@ -0,0 +1,7 @@
+module.exports = function (pagesJson, manifestJson) {
+ const {
+ app,
+ project
+ } = require('../mp')(pagesJson, manifestJson, require('./project.config.json'))
+ return [app, project]
+}
diff --git a/packages/webpack-uni-pages-loader/lib/platforms/mp-kuaishou/project.config.json b/packages/webpack-uni-pages-loader/lib/platforms/mp-kuaishou/project.config.json
new file mode 100644
index 0000000000000000000000000000000000000000..5c674c33bb48bbf681f159061b13d11c7ccc61fc
--- /dev/null
+++ b/packages/webpack-uni-pages-loader/lib/platforms/mp-kuaishou/project.config.json
@@ -0,0 +1,6 @@
+{
+ "description": "项目配置文件。",
+ "libVersion": "0.6.0",
+ "appid": "touristappid",
+ "projectname": ""
+}
diff --git a/src/core/runtime/web-view/index.js b/src/core/runtime/web-view/index.js
index 13ca271f5a0ee37c4dbefa4769bfe6084d343ad8..c01bf2650acb76178ecbc57c71f47c1714679e4a 100644
--- a/src/core/runtime/web-view/index.js
+++ b/src/core/runtime/web-view/index.js
@@ -26,6 +26,9 @@ import {
import {
initWebviewApi as initQuickappWebviewApi
} from 'uni-platforms/quickapp-webview/runtime/web-view'
+import {
+ initWebviewApi as initKuaishouWebviewApi
+} from 'uni-platforms/mp-kuaishou/runtime/web-view'
const UniAppJSBridgeReady = function () {
window.UniAppJSBridge = true
@@ -43,6 +46,7 @@ const initWebviewApis = [
initBaiduWebviewApi,
initToutiaoWebviewApi,
initQuickappWebviewApi,
+ initKuaishouWebviewApi,
initH5WebviewApi
]
@@ -69,4 +73,4 @@ if (!api.navigateTo) {
}
api.webView = webViewApi
-export default api
+export default api
diff --git a/src/platforms/mp-kuaishou/helpers/normalize-preview-image.js b/src/platforms/mp-kuaishou/helpers/normalize-preview-image.js
new file mode 100644
index 0000000000000000000000000000000000000000..02a652485e7a955b0bdaec1d93f8c912de09071e
--- /dev/null
+++ b/src/platforms/mp-kuaishou/helpers/normalize-preview-image.js
@@ -0,0 +1,33 @@
+export default {
+ args (fromArgs) {
+ let currentIndex = parseInt(fromArgs.current)
+ if (isNaN(currentIndex)) {
+ return
+ }
+ const urls = fromArgs.urls
+ if (!Array.isArray(urls)) {
+ return
+ }
+ const len = urls.length
+ if (!len) {
+ return
+ }
+ if (currentIndex < 0) {
+ currentIndex = 0
+ } else if (currentIndex >= len) {
+ currentIndex = len - 1
+ }
+ if (currentIndex > 0) {
+ fromArgs.current = urls[currentIndex]
+ fromArgs.urls = urls.filter(
+ (item, index) => index < currentIndex ? item !== urls[currentIndex] : true
+ )
+ } else {
+ fromArgs.current = urls[0]
+ }
+ return {
+ indicator: false,
+ loop: false
+ }
+ }
+}
diff --git a/src/platforms/mp-kuaishou/runtime/api/index.js b/src/platforms/mp-kuaishou/runtime/api/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/platforms/mp-kuaishou/runtime/api/protocols.js b/src/platforms/mp-kuaishou/runtime/api/protocols.js
new file mode 100644
index 0000000000000000000000000000000000000000..9d4bc155cc54f2d12136baf3f7198723d7b9172a
--- /dev/null
+++ b/src/platforms/mp-kuaishou/runtime/api/protocols.js
@@ -0,0 +1,8 @@
+import previewImage from '../../helpers/normalize-preview-image'
+export const protocols = {
+ previewImage
+}
+export const todos = [
+ 'vibrate'
+]
+export const canIUses = []
diff --git a/src/platforms/mp-kuaishou/runtime/api/providers.js b/src/platforms/mp-kuaishou/runtime/api/providers.js
new file mode 100644
index 0000000000000000000000000000000000000000..908e7177162636539a859c60f94847b3c8032042
--- /dev/null
+++ b/src/platforms/mp-kuaishou/runtime/api/providers.js
@@ -0,0 +1,6 @@
+export default {
+ oauth: ['kuaishou'],
+ share: ['kuaishou'],
+ payment: ['kspay'],
+ push: ['kuaishou']
+}
diff --git a/src/platforms/mp-kuaishou/runtime/index.js b/src/platforms/mp-kuaishou/runtime/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..cb6abd39da011aeefe5f8686f11732cbc99ea21c
--- /dev/null
+++ b/src/platforms/mp-kuaishou/runtime/index.js
@@ -0,0 +1,44 @@
+import {
+ cached,
+ camelize
+} from 'uni-shared'
+
+const MPPage = Page
+const MPComponent = Component
+
+const customizeRE = /:/g
+
+const customize = cached((str) => {
+ return camelize(str.replace(customizeRE, '-'))
+})
+
+function initTriggerEvent (mpInstance) {
+ const oldTriggerEvent = mpInstance.triggerEvent
+ mpInstance.triggerEvent = function (event, ...args) {
+ return oldTriggerEvent.apply(mpInstance, [customize(event), ...args])
+ }
+}
+
+function initHook (name, options) {
+ const oldHook = options[name]
+ if (!oldHook) {
+ options[name] = function () {
+ initTriggerEvent(this)
+ }
+ } else {
+ options[name] = function (...args) {
+ initTriggerEvent(this)
+ return oldHook.apply(this, args)
+ }
+ }
+}
+
+Page = function (options = {}) {
+ initHook('onLoad', options)
+ return MPPage(options)
+}
+
+Component = function (options = {}) {
+ initHook('created', options)
+ return MPComponent(options)
+}
diff --git a/src/platforms/mp-kuaishou/runtime/web-view.js b/src/platforms/mp-kuaishou/runtime/web-view.js
new file mode 100644
index 0000000000000000000000000000000000000000..fb3c5943c8e58f4103357c6f50e7c22235d6245d
--- /dev/null
+++ b/src/platforms/mp-kuaishou/runtime/web-view.js
@@ -0,0 +1,17 @@
+const isKuaishou = window.ks &&
+ window.ks.miniProgram &&
+ /micromessenger/i.test(navigator.userAgent) &&
+ /miniProgram/i.test(navigator.userAgent)
+
+export function initWebviewApi (readyCallback) {
+ if (!isKuaishou) {
+ return
+ }
+ if (window.WeixinJSBridge && window.WeixinJSBridge.invoke) {
+ setTimeout(readyCallback, 0)
+ } else {
+ document.addEventListener('WeixinJSBridgeReady', readyCallback)
+ }
+
+ return window.ks.miniProgram
+}
diff --git a/src/platforms/mp-kuaishou/runtime/wrapper/app-base-parser.js b/src/platforms/mp-kuaishou/runtime/wrapper/app-base-parser.js
new file mode 100644
index 0000000000000000000000000000000000000000..70736e436c1343a0244c7f9690aedd19e37f1b29
--- /dev/null
+++ b/src/platforms/mp-kuaishou/runtime/wrapper/app-base-parser.js
@@ -0,0 +1,86 @@
+import Vue from 'vue'
+
+import {
+ initHooks,
+ initMocks
+} from 'uni-wrapper/util'
+
+const hooks = [
+ 'onShow',
+ 'onHide',
+ 'onError',
+ 'onPageNotFound'
+]
+
+export default function parseBaseApp (vm, {
+ mocks,
+ initRefs
+}) {
+ if (vm.$options.store) {
+ Vue.prototype.$store = vm.$options.store
+ }
+
+ Vue.prototype.mpHost = __PLATFORM__
+
+ Vue.mixin({
+ beforeCreate () {
+ if (!this.$options.mpType) {
+ return
+ }
+
+ this.mpType = this.$options.mpType
+
+ this.$mp = {
+ data: {},
+ [this.mpType]: this.$options.mpInstance
+ }
+
+ this.$scope = this.$options.mpInstance
+
+ delete this.$options.mpType
+ delete this.$options.mpInstance
+
+ if (this.mpType !== 'app') {
+ initRefs(this)
+ initMocks(this, mocks)
+ }
+ }
+ })
+
+ const appOptions = {
+ onLaunch (args) {
+ if (this.$vm) { // 已经初始化过了,主要是为了百度,百度 onShow 在 onLaunch 之前
+ return
+ }
+
+ this.$vm = vm
+
+ this.$vm.$mp = {
+ app: this
+ }
+
+ this.$vm.$scope = this
+ // vm 上也挂载 globalData
+ this.$vm.globalData = this.globalData
+
+ this.$vm._isMounted = true
+ this.$vm.__call_hook('mounted', args)
+
+ this.$vm.__call_hook('onLaunch', args)
+ }
+ }
+
+ // 兼容旧版本 globalData
+ appOptions.globalData = vm.$options.globalData || {}
+ // 将 methods 中的方法挂在 getApp() 中
+ const methods = vm.$options.methods
+ if (methods) {
+ Object.keys(methods).forEach(name => {
+ appOptions[name] = methods[name]
+ })
+ }
+
+ initHooks(appOptions, hooks)
+
+ return appOptions
+}
diff --git a/src/platforms/mp-kuaishou/runtime/wrapper/app-parser.js b/src/platforms/mp-kuaishou/runtime/wrapper/app-parser.js
new file mode 100644
index 0000000000000000000000000000000000000000..5f8d432791ff30c4bc2eea1caa0e4ba5c76f8cda
--- /dev/null
+++ b/src/platforms/mp-kuaishou/runtime/wrapper/app-parser.js
@@ -0,0 +1,13 @@
+import parseBaseApp from './app-base-parser'
+
+import {
+ mocks,
+ initRefs
+} from './util'
+
+export default function parseApp (vm) {
+ return parseBaseApp(vm, {
+ mocks,
+ initRefs
+ })
+}
diff --git a/src/platforms/mp-kuaishou/runtime/wrapper/component-base-parser.js b/src/platforms/mp-kuaishou/runtime/wrapper/component-base-parser.js
new file mode 100644
index 0000000000000000000000000000000000000000..928f83b023fd07b6c033fdc7b00379a8d399c038
--- /dev/null
+++ b/src/platforms/mp-kuaishou/runtime/wrapper/component-base-parser.js
@@ -0,0 +1,105 @@
+import Vue from 'vue'
+
+import {
+ initData,
+ initSlots,
+ initVueIds,
+ handleEvent,
+ initBehaviors,
+ initProperties,
+ initVueComponent
+} from 'uni-wrapper/util'
+
+import {
+ handleLink,
+ initBehavior
+} from './util'
+
+export default function parseBaseComponent (vueComponentOptions, {
+ isPage,
+ initRelation
+} = {}) {
+ let [VueComponent, vueOptions] = initVueComponent(Vue, vueComponentOptions)
+
+ const options = {
+ multipleSlots: true,
+ addGlobalClass: true
+ }
+
+ const componentOptions = {
+ options,
+ data: initData(vueOptions, Vue.prototype),
+ behaviors: initBehaviors(vueOptions, initBehavior),
+ properties: initProperties(vueOptions.props, false, vueOptions.__file),
+ lifetimes: {
+ attached () {
+ const properties = this.properties
+
+ const options = {
+ mpType: isPage.call(this) ? 'page' : 'component',
+ mpInstance: this,
+ propsData: properties
+ }
+
+ initVueIds(properties.vueId, this)
+
+ // 处理父子关系
+ initRelation.call(this, {
+ vuePid: this._$vuePid,
+ vueOptions: options
+ })
+
+ // 初始化 vue 实例
+ this.$vm = new VueComponent(options)
+
+ // 处理$slots,$scopedSlots(暂不支持动态变化$slots)
+ initSlots(this.$vm, properties.vueSlots)
+
+ // 触发首次 setData
+ this.$vm.$mount()
+ },
+ ready () {
+ // 当组件 props 默认值为 true,初始化时传入 false 会导致 created,ready 触发, 但 attached 不触发
+ // https://developers.weixin.qq.com/community/develop/doc/00066ae2844cc0f8eb883e2a557800
+ if (this.$vm) {
+ this.$vm._isMounted = true
+ this.$vm.__call_hook('mounted')
+ this.$vm.__call_hook('onReady')
+ } else {
+ // this.is && console.warn(this.is + ' is not attached')
+ }
+ },
+ detached () {
+ this.$vm.$destroy()
+ }
+ },
+ pageLifetimes: {
+ show (args) {
+ this.$vm && 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: {
+ __l: handleLink,
+ __e: handleEvent
+ }
+ }
+
+ if (Array.isArray(vueOptions.wxsCallMethods)) {
+ vueOptions.wxsCallMethods.forEach(callMethod => {
+ componentOptions.methods[callMethod] = function (args) {
+ return this.$vm[callMethod](args)
+ }
+ })
+ }
+
+ if (isPage) {
+ return componentOptions
+ }
+ return [componentOptions, VueComponent]
+}
diff --git a/src/platforms/mp-kuaishou/runtime/wrapper/component-parser.js b/src/platforms/mp-kuaishou/runtime/wrapper/component-parser.js
new file mode 100644
index 0000000000000000000000000000000000000000..e84b4456e72a258b95e6e4496d8f6c9b1a6a6298
--- /dev/null
+++ b/src/platforms/mp-kuaishou/runtime/wrapper/component-parser.js
@@ -0,0 +1,13 @@
+import parseBaseComponent from './component-base-parser'
+
+import {
+ isPage,
+ initRelation
+} from './util'
+
+export default function parseComponent (vueComponentOptions) {
+ return parseBaseComponent(vueComponentOptions, {
+ isPage,
+ initRelation
+ })
+}
diff --git a/src/platforms/mp-kuaishou/runtime/wrapper/page-base-parser.js b/src/platforms/mp-kuaishou/runtime/wrapper/page-base-parser.js
new file mode 100644
index 0000000000000000000000000000000000000000..6464fedcf011302e0bd9937130c3d8a8dc07138c
--- /dev/null
+++ b/src/platforms/mp-kuaishou/runtime/wrapper/page-base-parser.js
@@ -0,0 +1,33 @@
+import {
+ initHooks,
+ PAGE_EVENT_HOOKS
+} from 'uni-wrapper/util'
+
+import parseComponent from 'uni-platform/runtime/wrapper/component-parser'
+
+const hooks = [
+ 'onShow',
+ 'onHide',
+ 'onUnload'
+]
+
+hooks.push(...PAGE_EVENT_HOOKS)
+
+export default function parseBasePage (vuePageOptions, {
+ isPage,
+ initRelation
+}) {
+ const pageOptions = parseComponent(vuePageOptions, {
+ isPage,
+ initRelation
+ })
+
+ initHooks(pageOptions.methods, hooks, vuePageOptions)
+
+ pageOptions.methods.onLoad = function (args) {
+ this.$vm.$mp.query = args // 兼容 mpvue
+ this.$vm.__call_hook('onLoad', args)
+ }
+
+ return pageOptions
+}
diff --git a/src/platforms/mp-kuaishou/runtime/wrapper/page-parser.js b/src/platforms/mp-kuaishou/runtime/wrapper/page-parser.js
new file mode 100644
index 0000000000000000000000000000000000000000..0a64ca8610c4c4a8152bb1a8ddbda6644ee9636f
--- /dev/null
+++ b/src/platforms/mp-kuaishou/runtime/wrapper/page-parser.js
@@ -0,0 +1,13 @@
+import parseBasePage from './page-base-parser'
+
+import {
+ isPage,
+ initRelation
+} from './util'
+
+export default function parsePage (vuePageOptions) {
+ return parseBasePage(vuePageOptions, {
+ isPage,
+ initRelation
+ })
+}
diff --git a/src/platforms/mp-kuaishou/runtime/wrapper/util.js b/src/platforms/mp-kuaishou/runtime/wrapper/util.js
new file mode 100644
index 0000000000000000000000000000000000000000..6b27333161170a827f446aba197a15f7701726eb
--- /dev/null
+++ b/src/platforms/mp-kuaishou/runtime/wrapper/util.js
@@ -0,0 +1,72 @@
+/* 快手也使用__wxExparserNodeId__和__wxWebviewId__ */
+export const mocks = ['__route__', '__wxExparserNodeId__', '__wxWebviewId__']
+
+export function findVmByVueId (vm, vuePid) {
+ const $children = vm.$children
+ // 优先查找直属
+ let parentVm = $children.find(childVm => childVm.$scope._$vueId === vuePid)
+ if (parentVm) {
+ return parentVm
+ }
+ // 反向递归查找
+ for (let i = $children.length - 1; i >= 0; i--) {
+ parentVm = findVmByVueId($children[i], vuePid)
+ if (parentVm) {
+ return parentVm
+ }
+ }
+}
+
+export function initBehavior (options) {
+ return Behavior(options)
+}
+
+export function isPage () {
+ return !!this.route
+}
+
+export function initRelation (detail) {
+ this.triggerEvent('__l', detail)
+}
+
+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 handleLink (event) {
+ const {
+ vuePid,
+ vueOptions
+ } = event.detail || event.value // detail 是微信,value 是百度(dipatch)
+
+ let parentVm
+
+ if (vuePid) {
+ parentVm = findVmByVueId(this.$vm, vuePid)
+ }
+
+ if (!parentVm) {
+ parentVm = this.$vm
+ }
+
+ vueOptions.parent = parentVm
+}