From 6d6bdf84a96810b5bd9136c553122cff6c9ed284 Mon Sep 17 00:00:00 2001 From: fxy060608 Date: Fri, 15 Mar 2019 20:01:06 +0800 Subject: [PATCH] =?UTF-8?q?feat(h5):=20createSelectorQuery=E6=94=AF?= =?UTF-8?q?=E6=8C=81=20in=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- packages/uni-app-plus/dist/index.js | 204 ++++++++++++------ packages/uni-app-plus/package.json | 2 +- packages/uni-mp-baidu/dist/index.js | 9 +- packages/uni-mp-baidu/package.json | 2 +- packages/uni-mp-toutiao/dist/index.js | 9 +- packages/uni-mp-toutiao/package.json | 2 +- packages/uni-mp-weixin/dist/index.js | 9 +- packages/uni-mp-weixin/package.json | 2 +- src/core/runtime/wrapper/create-page.js | 3 +- src/core/runtime/wrapper/util.js | 6 +- src/core/service/api/create-selector-query.js | 2 +- .../subscribe/request-component-info.js | 5 +- yarn.lock | 14 +- 14 files changed, 178 insertions(+), 93 deletions(-) diff --git a/package.json b/package.json index ece581cc3..951742e64 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "scripts": { "lint": "eslint --fix --config package.json --ext .js --ext .vue --ignore-path .eslintignore build src", "dev:h5": "npm run lint && cross-env NODE_ENV=production UNI_WATCH=true UNI_PLATFORM=h5 node build/build.js", - "build:h5": "npm run lint && cross-env NODE_ENV=production UNI_WATCH=false UNI_PLATFORM=h5 node build/build.js", + "build:h5": "npm run lint && cross-env NODE_ENV=production UNI_WATCH=false UNI_PLATFORM=h5 node build/build.js", "build:app-plus": "npm run lint && cross-env UNI_PLATFORM=app-plus rollup -c build/rollup.config.js", "build:mp-weixin": "npm run lint && cross-env UNI_PLATFORM=mp-weixin rollup -c build/rollup.config.js", "build:mp-baidu": "npm run lint && cross-env UNI_PLATFORM=mp-baidu rollup -c build/rollup.config.js", diff --git a/packages/uni-app-plus/dist/index.js b/packages/uni-app-plus/dist/index.js index a2f49dea1..07427479e 100644 --- a/packages/uni-app-plus/dist/index.js +++ b/packages/uni-app-plus/dist/index.js @@ -277,33 +277,53 @@ function initMocks (vm) { }); } -function initHooks (mpOptions, hooks) { +function initHooks (mpOptions, hooks, delay = false) { hooks.forEach(hook => { mpOptions[hook] = function (args) { - this.$vm.__call_hook(hook, args); + if (delay) { + setTimeout(() => this.$vm.__call_hook(hook, args)); + } else { + this.$vm.__call_hook(hook, args); + } }; }); } -function getData (data) { +function getData (vueOptions) { + let data = vueOptions.data || {}; + const methods = vueOptions.methods || {}; + if (typeof data === 'function') { try { - return data() + data = data(); } catch (e) { - console.warn('根据 Vue 的 data 函数初始化小程序 data 失败,请尽量确保 data 函数中不访问 vm 对象,否则可能影响首次数据渲染速度。'); + if (process.env.VUE_APP_DEBUG) { + console.warn('根据 Vue 的 data 函数初始化小程序 data 失败,请尽量确保 data 函数中不访问 vm 对象,否则可能影响首次数据渲染速度。', data); + } } - return {} } - return data || {} + + return Object.assign(data, methods) } 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 getProperties (props) { const properties = {}; if (Array.isArray(props)) { // ['title'] props.forEach(key => { - properties[key] = null; + properties[key] = { + type: null, + observer: createObserver(key) + }; }); } else if (isPlainObject(props)) { // {title:{type:String,default:''},content:String} Object.keys(props).forEach(key => { @@ -315,10 +335,14 @@ function getProperties (props) { } properties[key] = { type: PROP_TYPES.includes(opts.type) ? opts.type : null, - value + value, + observer: createObserver(key) }; } else { // content:String - properties[key] = PROP_TYPES.includes(opts) ? opts : null; + properties[key] = { + type: PROP_TYPES.includes(opts) ? opts : null, + observer: createObserver(key) + }; } }); } @@ -331,6 +355,7 @@ function wrapper$1 (event) { event.target = event.target || {}; event.detail = event.detail || {}; + // TODO 又得兼容 mpvue 的 mp 对象 event.mp = event; event.target = Object.assign({}, event.target, event.detail); @@ -379,6 +404,9 @@ function handleEvent (event) { if (eventsArray && eventType === type) { eventsArray.forEach(eventArray => { const handler = this.$vm[eventArray[0]]; + if (!isFn(handler)) { + throw new Error(` _vm.${eventArray[0]} is not a function`) + } if (isOnce) { if (handler.once) { return @@ -400,12 +428,12 @@ function initRefs (vm) { Object.defineProperty(vm, '$refs', { get () { const $refs = Object.create(null); - const components = mpInstance.selectAllComponents('.__ref__'); + const components = mpInstance.selectAllComponents('.vue-ref'); components.forEach(component => { const ref = component.dataset.ref; $refs[ref] = component.$vm; }); - const forComponents = mpInstance.selectAllComponents('.__ref-in-for__'); + const forComponents = mpInstance.selectAllComponents('.vue-ref-in-for'); forComponents.forEach(component => { const ref = component.dataset.ref; if (!$refs[ref]) { @@ -416,6 +444,20 @@ function initRefs (vm) { return $refs } }); +} + +function initChildren (vm) { + const mpInstance = vm.$mp[vm.mpType]; + Object.defineProperty(vm, '$children', { + get () { + const $children = []; + const components = mpInstance.selectAllComponents('.vue-com'); + components.forEach(component => { + $children.push(component.$vm); + }); + return $children + } + }); } const hooks = [ @@ -427,20 +469,41 @@ const hooks = [ function createApp (vueOptions) { vueOptions = vueOptions.default || vueOptions; + // 外部初始化时 Vue 还未初始化,放到 createApp 内部初始化 mixin + Vue.mixin({ + beforeCreate () { + if (!this.$options.mpType) { + return + } + this.mpType = this.$options.mpType; + this.$mp = { + data: {}, + [this.mpType]: this.$options.mpInstance + }; + delete this.$options.mpType; + delete this.$options.mpInstance; + + if (this.mpType !== 'app') { + initRefs(this); + initMocks(this); + initChildren(this); + } + } + }); const appOptions = { onLaunch (args) { - this.$vm = new Vue(vueOptions); - this.$vm.mpType = 'app'; - this.$vm.$mp = { - app: this - }; + this.$vm = new Vue(Object.assign(vueOptions, { + mpType: 'app', + mpInstance: this + })); + this.$vm.$mount(); - this.$vm.__call_hook('onLaunch', args); + setTimeout(() => this.$vm.__call_hook('onLaunch', args)); } }; - initHooks(appOptions, hooks); + initHooks(appOptions, hooks, true); // 延迟执行,因为 App 的注册在 main.js 之前,可能导致生命周期内 Vue 原型上开发者注册的属性无法访问 App(appOptions); @@ -466,28 +529,27 @@ const hooks$1 = [ function createPage (vueOptions) { vueOptions = vueOptions.default || vueOptions; const pageOptions = { - data: getData(vueOptions.data), + data: getData(vueOptions), onLoad (args) { - this.$vm = new Vue(vueOptions); - this.$vm.mpType = 'page'; - this.$vm.$mp = { - data: {}, - page: this - }; - initRefs(this.$vm); - initMocks(this.$vm); + this.$vm = new Vue(Object.assign(vueOptions, { + mpType: 'page', + mpInstance: this + })); this.$vm.$mount(); this.$vm.__call_hook('onLoad', args); }, onReady () { - this.$vm._isMounted = true; + this.$vm._isMounted = true; + this.$vm.__call_hook('mounted'); this.$vm.__call_hook('onReady'); }, onUnload () { this.$vm.__call_hook('onUnload'); - this.$vm.$destroy(); + { + this.$vm.$destroy(); + } }, __e: handleEvent, __l: handleLink @@ -498,6 +560,23 @@ function createPage (vueOptions) { return Page(pageOptions) } +function initVueComponent (mpInstace, VueComponent) { + if (mpInstace.$vm) { + return + } + + const options = { + mpType: 'component', + mpInstance: mpInstace, + propsData: mpInstace.properties + }; + // 初始化 vue 实例 + mpInstace.$vm = new VueComponent(options); + + // 初始化渲染数据 + mpInstace.$vm.$mount(); +} + function createComponent (vueOptions) { vueOptions = vueOptions.default || vueOptions; @@ -510,50 +589,39 @@ function createComponent (vueOptions) { multipleSlots: true, addGlobalClass: true }, - data: getData(vueOptions.data), + data: getData(vueOptions), properties, - attached () { - // props的处理,一个是直接 与 mp 的 properties 对接,另一个是要做成 reactive,且排除掉 render watch - const options = { - propsData: this.properties, - $component: this - }; - // 初始化 vue 实例 - this.$vm = new VueComponent(options); - this.$vm.mpType = 'component'; - this.$vm.$mp = { - data: {}, - component: this - }; + lifetimes: { + attached () { + initVueComponent(this, VueComponent); + }, + ready () { + initVueComponent(this, VueComponent); // 目前发现部分情况小程序 attached 不触发 - initRefs(this.$vm); - initMocks(this.$vm); + { + this.triggerEvent('__l', this.$vm); // TODO 百度仅能传递 json 对象 + } - // 初始化渲染数据 - this.$vm.$mount(); - }, - ready () { - this.triggerEvent('__l', this.$vm); - - const eventId = this.dataset.eventId; - if (eventId) { - const listeners = this.$vm.$parent.$mp.listeners; - if (listeners) { - const listenerOpts = listeners[eventId]; - Object.keys(listenerOpts).forEach(eventType => { - listenerOpts[eventType].forEach(handler => { - this.$vm[handler.once ? '$once' : '$on'](eventType, handler); + const eventId = this.dataset.eventId; + if (eventId) { + const listeners = this.$vm.$parent.$mp.listeners; + if (listeners) { + const listenerOpts = listeners[eventId]; + Object.keys(listenerOpts).forEach(eventType => { + listenerOpts[eventType].forEach(handler => { + this.$vm[handler.once ? '$once' : '$on'](eventType, handler); + }); }); - }); + } } - } - this.$vm._isMounted = true; - this.$vm.__call_hook('mounted'); - this.$vm.__call_hook('onReady'); - }, - detached () { - this.$vm.$destroy(); + this.$vm._isMounted = true; + this.$vm.__call_hook('mounted'); + this.$vm.__call_hook('onReady'); + }, + detached () { + this.$vm.$destroy(); + } }, pageLifetimes: { show (args) { diff --git a/packages/uni-app-plus/package.json b/packages/uni-app-plus/package.json index 56f062da3..b2b38415a 100644 --- a/packages/uni-app-plus/package.json +++ b/packages/uni-app-plus/package.json @@ -1,6 +1,6 @@ { "name": "@dcloudio/uni-app-plus", - "version": "0.0.2", + "version": "0.0.201", "description": "uni-app app-plus", "main": "dist/index.js", "scripts": { diff --git a/packages/uni-mp-baidu/dist/index.js b/packages/uni-mp-baidu/dist/index.js index 24a493958..c7f796aad 100644 --- a/packages/uni-mp-baidu/dist/index.js +++ b/packages/uni-mp-baidu/dist/index.js @@ -404,7 +404,7 @@ function initHooks (mpOptions, hooks, delay = false) { }); } -function getData (vueOptions) { +function getData (vueOptions) { let data = vueOptions.data || {}; const methods = vueOptions.methods || {}; @@ -412,7 +412,9 @@ function getData (vueOptions) { try { data = data(); } catch (e) { - console.warn('根据 Vue 的 data 函数初始化小程序 data 失败,请尽量确保 data 函数中不访问 vm 对象,否则可能影响首次数据渲染速度。', data); + if (process.env.VUE_APP_DEBUG) { + console.warn('根据 Vue 的 data 函数初始化小程序 data 失败,请尽量确保 data 函数中不访问 vm 对象,否则可能影响首次数据渲染速度。', data); + } } } @@ -677,7 +679,8 @@ function createPage (vueOptions) { this.$vm.__call_hook('onLoad', args); }, onReady () { - this.$vm._isMounted = true; + this.$vm._isMounted = true; + this.$vm.__call_hook('mounted'); this.$vm.__call_hook('onReady'); }, onUnload () { diff --git a/packages/uni-mp-baidu/package.json b/packages/uni-mp-baidu/package.json index a90dded9e..d89102acf 100644 --- a/packages/uni-mp-baidu/package.json +++ b/packages/uni-mp-baidu/package.json @@ -1,6 +1,6 @@ { "name": "@dcloudio/uni-mp-baidu", - "version": "0.0.804", + "version": "0.0.806", "description": "uni-app mp-baidu", "main": "dist/index.js", "scripts": { diff --git a/packages/uni-mp-toutiao/dist/index.js b/packages/uni-mp-toutiao/dist/index.js index 8d4bfca6d..b5fce943e 100644 --- a/packages/uni-mp-toutiao/dist/index.js +++ b/packages/uni-mp-toutiao/dist/index.js @@ -449,7 +449,7 @@ function initHooks (mpOptions, hooks, delay = false) { }); } -function getData (vueOptions) { +function getData (vueOptions) { let data = vueOptions.data || {}; const methods = vueOptions.methods || {}; @@ -457,7 +457,9 @@ function getData (vueOptions) { try { data = data(); } catch (e) { - console.warn('根据 Vue 的 data 函数初始化小程序 data 失败,请尽量确保 data 函数中不访问 vm 对象,否则可能影响首次数据渲染速度。', data); + if (process.env.VUE_APP_DEBUG) { + console.warn('根据 Vue 的 data 函数初始化小程序 data 失败,请尽量确保 data 函数中不访问 vm 对象,否则可能影响首次数据渲染速度。', data); + } } } @@ -699,7 +701,8 @@ function createPage (vueOptions) { this.$vm.__call_hook('onLoad', args); }, onReady () { - this.$vm._isMounted = true; + this.$vm._isMounted = true; + this.$vm.__call_hook('mounted'); this.$vm.__call_hook('onReady'); }, onUnload () { diff --git a/packages/uni-mp-toutiao/package.json b/packages/uni-mp-toutiao/package.json index 4432239d1..fdf018617 100644 --- a/packages/uni-mp-toutiao/package.json +++ b/packages/uni-mp-toutiao/package.json @@ -1,6 +1,6 @@ { "name": "@dcloudio/uni-mp-toutiao", - "version": "0.0.301", + "version": "0.0.303", "description": "uni-app mp-toutiao", "main": "dist/index.js", "scripts": { diff --git a/packages/uni-mp-weixin/dist/index.js b/packages/uni-mp-weixin/dist/index.js index 16b09394e..88d768256 100644 --- a/packages/uni-mp-weixin/dist/index.js +++ b/packages/uni-mp-weixin/dist/index.js @@ -291,7 +291,7 @@ function initHooks (mpOptions, hooks, delay = false) { }); } -function getData (vueOptions) { +function getData (vueOptions) { let data = vueOptions.data || {}; const methods = vueOptions.methods || {}; @@ -299,7 +299,9 @@ function getData (vueOptions) { try { data = data(); } catch (e) { - console.warn('根据 Vue 的 data 函数初始化小程序 data 失败,请尽量确保 data 函数中不访问 vm 对象,否则可能影响首次数据渲染速度。', data); + if (process.env.VUE_APP_DEBUG) { + console.warn('根据 Vue 的 data 函数初始化小程序 data 失败,请尽量确保 data 函数中不访问 vm 对象,否则可能影响首次数据渲染速度。', data); + } } } @@ -541,7 +543,8 @@ function createPage (vueOptions) { this.$vm.__call_hook('onLoad', args); }, onReady () { - this.$vm._isMounted = true; + this.$vm._isMounted = true; + this.$vm.__call_hook('mounted'); this.$vm.__call_hook('onReady'); }, onUnload () { diff --git a/packages/uni-mp-weixin/package.json b/packages/uni-mp-weixin/package.json index 9dbe6715d..3aea14961 100644 --- a/packages/uni-mp-weixin/package.json +++ b/packages/uni-mp-weixin/package.json @@ -1,6 +1,6 @@ { "name": "@dcloudio/uni-mp-weixin", - "version": "0.0.905", + "version": "0.0.907", "description": "uni-app mp-weixin", "main": "dist/index.js", "scripts": { diff --git a/src/core/runtime/wrapper/create-page.js b/src/core/runtime/wrapper/create-page.js index b3d40667f..25591cf60 100644 --- a/src/core/runtime/wrapper/create-page.js +++ b/src/core/runtime/wrapper/create-page.js @@ -42,7 +42,8 @@ export function createPage (vueOptions) { this.$vm.__call_hook('onLoad', args) }, onReady () { - this.$vm._isMounted = true + this.$vm._isMounted = true + this.$vm.__call_hook('mounted') this.$vm.__call_hook('onReady') }, onUnload () { diff --git a/src/core/runtime/wrapper/util.js b/src/core/runtime/wrapper/util.js index 00fc9cbc7..c70b0f4af 100644 --- a/src/core/runtime/wrapper/util.js +++ b/src/core/runtime/wrapper/util.js @@ -28,7 +28,7 @@ export function initHooks (mpOptions, hooks, delay = false) { }) } -export function getData (vueOptions) { +export function getData (vueOptions) { let data = vueOptions.data || {} const methods = vueOptions.methods || {} @@ -36,7 +36,9 @@ export function getData (vueOptions) { try { data = data() } catch (e) { - console.warn('根据 Vue 的 data 函数初始化小程序 data 失败,请尽量确保 data 函数中不访问 vm 对象,否则可能影响首次数据渲染速度。', data) + if (process.env.VUE_APP_DEBUG) { + console.warn('根据 Vue 的 data 函数初始化小程序 data 失败,请尽量确保 data 函数中不访问 vm 对象,否则可能影响首次数据渲染速度。', data) + } } } diff --git a/src/core/service/api/create-selector-query.js b/src/core/service/api/create-selector-query.js index 525afc784..ca60692ed 100644 --- a/src/core/service/api/create-selector-query.js +++ b/src/core/service/api/create-selector-query.js @@ -84,7 +84,7 @@ class SelectorQuery { } ['in'] (component) { - console.error('Unsupported method:SelectorQuery.in') + this._component = component return this } diff --git a/src/core/view/bridge/subscribe/request-component-info.js b/src/core/view/bridge/subscribe/request-component-info.js index b0e93485e..83fec6bb6 100644 --- a/src/core/view/bridge/subscribe/request-component-info.js +++ b/src/core/view/bridge/subscribe/request-component-info.js @@ -74,7 +74,8 @@ function getNodeInfo (el, fields) { } function getNodesInfo (pageVm, component, selector, single, fields) { - const $el = pageVm.$el + /* eslint-disable no-mixed-operators */ + const $el = component && component.$el || pageVm.$el if (single) { const node = $el && ($el.matches(selector) ? $el : $el.querySelector(selector)) if (node) { @@ -129,4 +130,4 @@ export default function requestComponentInfo ({ reqId, res: result }, pageVm.$page.id) -} +} diff --git a/yarn.lock b/yarn.lock index ffed33ce4..0de15d910 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1784,10 +1784,14 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000939, caniuse-lite@^1.0.30000940: +caniuse-lite@^1.0.0: version "1.0.30000940" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000940.tgz#19f2b1497fbfa5b96b615963097c3757f27989ce" +caniuse-lite@^1.0.30000939, caniuse-lite@^1.0.30000940: + version "1.0.30000948" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000948.tgz#793ed7c28fe664856beb92b43fc013fc22b81633" + case-sensitive-paths-webpack-plugin@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.2.0.tgz#3371ef6365ef9c25fa4b81c16ace0e9c7dc58c3e" @@ -2698,8 +2702,8 @@ ejs@^2.6.1: resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.1.tgz#498ec0d495655abc6f23cd61868d926464071aa0" electron-to-chromium@^1.3.113: - version "1.3.113" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.113.tgz#b1ccf619df7295aea17bc6951dc689632629e4a9" + version "1.3.116" + resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.116.tgz#1dbfee6a592a0c14ade77dbdfe54fef86387d702" elliptic@^6.0.0: version "6.4.1" @@ -4953,8 +4957,8 @@ node-pre-gyp@^0.10.0: tar "^4" node-releases@^1.1.8: - version "1.1.9" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.9.tgz#70d0985ec4bf7de9f08fc481f5dae111889ca482" + version "1.1.10" + resolved "https://registry.npmjs.org/node-releases/-/node-releases-1.1.10.tgz#5dbeb6bc7f4e9c85b899e2e7adcc0635c9b2adf7" dependencies: semver "^5.3.0" -- GitLab