import Vue from 'vue' import { initData, initVueIds, handleEvent, initBehaviors, initProperties, initVueComponent } from 'uni-wrapper/util' import { handleRef, handleLink, handleWrap, initBehavior, initRelation, triggerEvent, createObserver, isComponent2, initChildVues, initSpecialMethods } from './util' function initSlots (vm, vueSlots) { const $slots = Object.create(null) // 未启用小程序基础库 2.0 时,组件实例支持支持访问 $slots、$scopedSlots Object.defineProperty(vm, '$slots', { get () { const $scope = this.$scope return ($scope && $scope.props.$slots) || ($scope && $scope.props.$scopedSlots ? {} : $slots) } }) Object.defineProperty(vm, '$scopedSlots', { get () { const $scope = this.$scope return ($scope && $scope.props.$scopedSlots) || ($scope && $scope.props.$slots ? {} : $slots) } }) // 处理$slots,$scopedSlots(暂不支持动态变化$slots) if (Array.isArray(vueSlots) && vueSlots.length) { vueSlots.forEach(slotName => { $slots[slotName] = true }) } } function initVm (VueComponent) { if (this.$vm) { return } const properties = this.props const options = { mpType: 'component', mpInstance: this, propsData: properties } initVueIds(properties.vueId, this) if (isComponent2) { // 处理父子关系 initRelation.call(this, { vuePid: this._$vuePid, vueOptions: options }) // 初始化 vue 实例 this.$vm = new VueComponent(options) initSlots(this.$vm, properties.vueSlots) // 触发首次 setData this.$vm.$mount() } else { // 处理父子关系 initRelation.call(this, { vuePid: this._$vuePid, vueOptions: options, VueComponent, mpInstance: this }) if (options.parent) { // 父组件已经初始化,直接初始化子,否则放到父组件的 didMount 中处理 // 初始化 vue 实例 this.$vm = new VueComponent(options) handleRef.call(options.parent.$scope, this) initSlots(this.$vm, properties.vueSlots) // 触发首次 setData this.$vm.$mount() initChildVues(this) this.$vm._isMounted = true this.$vm.__call_hook('mounted') this.$vm.__call_hook('onReady') } } } export default function parseComponent (vueComponentOptions, needVueOptions) { const [VueComponent, vueOptions] = initVueComponent(Vue, vueComponentOptions) const properties = initProperties(vueOptions.props, false, vueOptions.__file) const props = { onVueInit: function () {} } Object.keys(properties).forEach(key => { props[key] = properties[key].value }) const componentOptions = { mixins: initBehaviors(vueOptions, initBehavior), data: initData(vueOptions, Vue.prototype), props, didMount () { if (my.dd) { // 钉钉小程序底层基础库有 bug,组件嵌套使用时,在 didMount 中无法及时调用 props 中的方法 setTimeout(() => { initVm.call(this, VueComponent) }, 4) } else { initVm.call(this, VueComponent) } initSpecialMethods(this) if (isComponent2) { this.$vm._isMounted = true this.$vm.__call_hook('mounted') this.$vm.__call_hook('onReady') } }, didUnmount () { this.$vm && this.$vm.$destroy() }, methods: { __r: handleRef, __e: handleEvent, __l: handleLink, __w: handleWrap, triggerEvent } } if (isComponent2) { componentOptions.onInit = function onInit () { initVm.call(this, VueComponent) } componentOptions.deriveDataFromProps = createObserver() } else { componentOptions.didUpdate = createObserver(true) } if (Array.isArray(vueOptions.wxsCallMethods)) { vueOptions.wxsCallMethods.forEach(callMethod => { componentOptions.methods[callMethod] = function (args) { return this.$vm[callMethod](args) } }) } return needVueOptions ? [componentOptions, vueOptions] : componentOptions }