import { isFn, cached, camelize, hasOwn } from 'uni-shared' import { handleLink as handleBaseLink } from '../../../mp-weixin/runtime/wrapper/util' import deepEqual from './deep-equal' const customizeRE = /:/g const customize = cached((str) => { return camelize(str.replace(customizeRE, '-')) }) export const isComponent2 = my.canIUse('component2') export const mocks = ['$id'] export function initRefs () { } export function initBehavior ({ properties }) { const props = {} Object.keys(properties).forEach(key => { props[key] = properties[key].value }) return { props } } export function initRelation (detail) { this.props.onVueInit(detail) } export function initSpecialMethods (mpInstance) { if (!mpInstance.$vm) { return } let path = mpInstance.is || mpInstance.route if (!path) { return } if (path.indexOf('/') === 0) { path = path.substr(1) } const specialMethods = my.specialMethods && my.specialMethods[path] if (specialMethods) { specialMethods.forEach(method => { if (isFn(mpInstance.$vm[method])) { mpInstance[method] = function (event) { if (hasOwn(event, 'markerId')) { event.detail = typeof event.detail === 'object' ? event.detail : {} event.detail.markerId = event.markerId } // TODO normalizeEvent mpInstance.$vm[method](event) } } }) } } export function initChildVues (mpInstance) { // 此时需保证当前 mpInstance 已经存在 $vm if (!mpInstance.$vm) { return } mpInstance._$childVues && mpInstance._$childVues.forEach(({ vuePid, vueOptions, VueComponent, mpInstance: childMPInstance }) => { // 父子关系 handleBaseLink.call(mpInstance, { detail: { vuePid, vueOptions } }) childMPInstance.$vm = new VueComponent(vueOptions) initSpecialMethods(childMPInstance) handleRef.call(vueOptions.parent.$scope, childMPInstance) childMPInstance.$vm.$mount() initChildVues(childMPInstance) childMPInstance.$vm._isMounted = true childMPInstance.$vm.__call_hook('mounted') childMPInstance.$vm.__call_hook('onReady') }) delete mpInstance._$childVues } export function handleRef (ref) { if (!ref) { return } const refName = ref.props['data-ref'] const refInForName = ref.props['data-ref-in-for'] if (refName) { this.$vm.$refs[refName] = ref.$vm || ref } else if (refInForName) { (this.$vm.$refs[refInForName] || (this.$vm.$refs[refInForName] = [])).push(ref.$vm || ref) } } export function triggerEvent (type, detail, options) { const handler = this.props && this.props[customize('on-' + type)] if (!handler) { return } const eventOpts = this.props['data-event-opts'] const eventParams = this.props['data-event-params'] const target = { dataset: { eventOpts, eventParams } } handler({ type: customize(type), target, currentTarget: target, detail }) } const IGNORES = ['$slots', '$scopedSlots'] export function createObserver (isDidUpdate) { return function observe (props) { const prevProps = isDidUpdate ? props : this.props const nextProps = isDidUpdate ? this.props : props if (deepEqual(prevProps, nextProps)) { return } Object.keys(prevProps).forEach(name => { if (IGNORES.indexOf(name) === -1) { const prevValue = prevProps[name] const nextValue = nextProps[name] if (!isFn(prevValue) && !isFn(nextValue) && !deepEqual(prevValue, nextValue)) { this.$vm[name] = nextProps[name] } } }) } } export const handleLink = (function () { if (isComponent2) { return function handleLink (detail) { return handleBaseLink.call(this, { detail }) } } return function handleLink (detail) { if (this.$vm && this.$vm._isMounted) { // 父已初始化 return handleBaseLink.call(this, { detail: { vuePid: detail.vuePid, vueOptions: detail.vueOptions } }) } // 支付宝通过 didMount 来实现,先子后父,故等父 ready 之后,统一初始化 (this._$childVues || (this._$childVues = [])).unshift(detail) } })()