component-parser.js 4.1 KB
Newer Older
fxy060608's avatar
fxy060608 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14
import Vue from 'vue'

import {
  initData,
  initVueIds,
  handleEvent,
  initBehaviors,
  initProperties,
  initVueComponent
} from 'uni-wrapper/util'

import {
  handleRef,
  handleLink,
15
  handleWrap,
fxy060608's avatar
fxy060608 已提交
16 17 18 19 20
  initBehavior,
  initRelation,
  triggerEvent,
  createObserver,
  isComponent2,
fxy060608's avatar
fxy060608 已提交
21
  initChildVues,
fxy060608's avatar
fxy060608 已提交
22
  initSpecialMethods
fxy060608's avatar
fxy060608 已提交
23 24
} from './util'

25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
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
    })
  }
}

fxy060608's avatar
fxy060608 已提交
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
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)

72 73
    initSlots(this.$vm, properties.vueSlots)

fxy060608's avatar
fxy060608 已提交
74 75
    // 触发首次 setData
    this.$vm.$mount()
fxy060608's avatar
fxy060608 已提交
76
  } else {
fxy060608's avatar
fxy060608 已提交
77 78 79 80 81 82
    // 处理父子关系
    initRelation.call(this, {
      vuePid: this._$vuePid,
      vueOptions: options,
      VueComponent,
      mpInstance: this
fxy060608's avatar
fxy060608 已提交
83
    })
fxy060608's avatar
fxy060608 已提交
84

fxy060608's avatar
fxy060608 已提交
85
    if (options.parent) { // 父组件已经初始化,直接初始化子,否则放到父组件的 didMount 中处理
fxy060608's avatar
fxy060608 已提交
86
      // 初始化 vue 实例
fxy060608's avatar
fxy060608 已提交
87
      this.$vm = new VueComponent(options)
fxy060608's avatar
fxy060608 已提交
88
      handleRef.call(options.parent.$scope, this)
89 90 91

      initSlots(this.$vm, properties.vueSlots)

fxy060608's avatar
fxy060608 已提交
92
      // 触发首次 setData
fxy060608's avatar
fxy060608 已提交
93 94 95
      this.$vm.$mount()

      initChildVues(this)
fxy060608's avatar
fxy060608 已提交
96 97 98 99 100 101 102 103 104

      this.$vm._isMounted = true
      this.$vm.__call_hook('mounted')
      this.$vm.__call_hook('onReady')
    }
  }
}

export default function parseComponent (vueComponentOptions) {
fxy060608's avatar
fxy060608 已提交
105
  const [VueComponent, vueOptions] = initVueComponent(Vue, vueComponentOptions)
fxy060608's avatar
fxy060608 已提交
106 107 108 109 110 111 112 113

  const properties = initProperties(vueOptions.props, false, vueOptions.__file)

  const props = {
    onVueInit: function () {}
  }

  Object.keys(properties).forEach(key => {
114
    props[key] = properties[key].value
fxy060608's avatar
fxy060608 已提交
115 116 117 118 119 120
  })

  const componentOptions = {
    mixins: initBehaviors(vueOptions, initBehavior),
    data: initData(vueOptions, Vue.prototype),
    props,
fxy060608's avatar
fxy060608 已提交
121 122 123 124 125 126 127 128
    didMount () {
      if (my.dd) { // 钉钉小程序底层基础库有 bug,组件嵌套使用时,在 didMount 中无法及时调用 props 中的方法
        setTimeout(() => {
          initVm.call(this, VueComponent)
        }, 4)
      } else {
        initVm.call(this, VueComponent)
      }
fxy060608's avatar
fxy060608 已提交
129 130 131

      initSpecialMethods(this)

fxy060608's avatar
fxy060608 已提交
132 133 134 135 136 137 138
      if (isComponent2) {
        this.$vm._isMounted = true
        this.$vm.__call_hook('mounted')
        this.$vm.__call_hook('onReady')
      }
    },
    didUnmount () {
fxy060608's avatar
fxy060608 已提交
139
      this.$vm && this.$vm.$destroy()
fxy060608's avatar
fxy060608 已提交
140 141 142 143 144
    },
    methods: {
      __r: handleRef,
      __e: handleEvent,
      __l: handleLink,
145
      __w: handleWrap,
fxy060608's avatar
fxy060608 已提交
146 147 148 149 150 151 152 153 154 155 156
      triggerEvent
    }
  }

  if (isComponent2) {
    componentOptions.onInit = function onInit () {
      initVm.call(this, VueComponent)
    }
    componentOptions.deriveDataFromProps = createObserver()
  } else {
    componentOptions.didUpdate = createObserver(true)
157 158 159 160 161 162 163 164
  }

  if (Array.isArray(vueOptions.wxsCallMethods)) {
    vueOptions.wxsCallMethods.forEach(callMethod => {
      componentOptions.methods[callMethod] = function (args) {
        return this.$vm[callMethod](args)
      }
    })
fxy060608's avatar
fxy060608 已提交
165 166 167
  }

  return componentOptions
168
}