import Vue from 'vue' import { VD_SYNC, PAGE_CREATE, MOUNTED_DATA, UPDATED_DATA, PAGE_CREATED, VD_SYNC_CALLBACK } from '../../../constants' import { ON_PAGE_CREATE } from '../../constants' import { VDomSync } from './vdom-sync' import { setCurrentPage } from '../page' import { getPageVueComponent } from '../../../page-factory' export let vd let PageVueComponent const handleData = { [PAGE_CREATE]: function onPageCreate (data) { const [pageId, pagePath, pageOptions] = data document.title = `${pagePath}[${pageId}]` // 设置当前页面伪对象,方便其他地方使用 getCurrentPages 获取当前页面 id,route setCurrentPage(pageId, pagePath) // 通知页面创建,根据当前页面配置信息,初始化部分事件 UniViewJSBridge.subscribeHandler(ON_PAGE_CREATE, pageOptions, pageId) // 初始化当前页面 VueComponent(生成页面样式代码) PageVueComponent = getPageVueComponent(pagePath) // 生成当前页面 vd vd = new VDomSync(pageId, { version: pageOptions.version }) }, [MOUNTED_DATA]: function onMounted (data) { vd.addVData.apply(vd, data) }, [UPDATED_DATA]: function onUpdated (data) { vd.updateVData.apply(vd, data) }, [PAGE_CREATED]: function onPageCreated (data) { const [pageId, pagePath, pageQuery] = data const page = getCurrentPages()[0] page.options = pageQuery || {} page.$vm = new PageVueComponent({ mpType: 'page', pageId, pagePath, pageQuery }).$mount('#app') } } function broadcast (vm, componentName, eventName, ...params) { vm.$children.forEach(child => { const name = child.$options.name && child.$options.name.replace(/^VUni/, '') if (~componentName.indexOf(name)) { child.$emit(eventName, ...params) } broadcast(child, componentName, eventName, ...params) }) } const NATIVE_COMPONENTS = ['Camera', 'LivePlayer', 'LivePusher', 'Map', 'Video', 'CoverView', 'CoverImage', 'Ad'] function updateView () { const pages = getCurrentPages() const pageVm = pages[0] && pages[0].$vm pageVm && broadcast( pageVm, NATIVE_COMPONENTS, 'uni-view-update' ) } window.addEventListener('resize', () => { updateView() }) window.addEventListener('updateview', updateView) function vdSync ({ data, options }) { let isVdCallback = true data.forEach(data => { if (data[0] === PAGE_CREATE) { // 页面创建无需触发 callback isVdCallback = false } handleData[data[0]](data[1]) }) vd.flush() Vue.nextTick(() => { // 清空本次 addBatchData vd.clearAddBatchVData() updateView() isVdCallback && UniViewJSBridge.publishHandler(VD_SYNC_CALLBACK) }) } function getData (id, name) { try { const data = this.$r[id][name] if (name === 'is' && typeof data === 'object') { const components = this.$options.components || {} for (const key in components) { const value = components[key] const options = typeof value === 'function' ? value.options : value if (options.__file === data.__file) { return options } } } return data } catch (e) { // console.error(this.$options.__file + `:[${this._$id}]$r[${id}][${name}] is undefined`) } } /** * wxs change:prop * @param {Object} id * @param {Object} name */ function getChangeData (id, name) { try { const value = this.$r[id][name] const wxsPropName = name.replace('change:', '') this[wxsPropName] = value this.$set(this.wxsProps, wxsPropName, value) return value } catch (e) { // console.error(this.$options.__file + `:[${this._$id}]$r[${id}][${name}] is undefined`) } } export function initData (Vue) { Vue.prototype._$g = getData Vue.prototype._$gc = getChangeData UniViewJSBridge.subscribe(VD_SYNC, vdSync) Object.defineProperty(Vue.prototype, '_$vd', { get () { return !this.$options.isReserved && vd } }) Vue.mixin({ beforeCreate () { if (this.$options.mpType) { this.mpType = this.$options.mpType } if (this._$vd) { this._$vd.initVm(this) } } }) }