diff --git a/packages/uni-app-plus/dist/service.runtime.esm.js b/packages/uni-app-plus/dist/service.runtime.esm.js index bccd677c1a3d26a4e315591450238a1bd6ff65cd..edc7d98c1596a7f8aa0f404745272edf736c7e0a 100644 --- a/packages/uni-app-plus/dist/service.runtime.esm.js +++ b/packages/uni-app-plus/dist/service.runtime.esm.js @@ -4181,6 +4181,9 @@ function updateChildComponent ( vm.$options.propsData = propsData; } + // fixed by xxxxxx update properties(mp runtime) + vm._$updateProperties && vm._$updateProperties(vm); + // update listeners listeners = listeners || emptyObject; var oldListeners = vm.$options._parentListeners; diff --git a/packages/uni-migration/__tests__/demo.js b/packages/uni-migration/__tests__/demo.js index 80e9ae7da2da07aeccf538380fcde198aec3b3ce..25a2285fcf0b80b97fbe8d465ab0ac4e74534a42 100644 --- a/packages/uni-migration/__tests__/demo.js +++ b/packages/uni-migration/__tests__/demo.js @@ -13,7 +13,7 @@ migrate('/Users/fxy/Downloads/wa-vantui_1.1') // transformTemplate // } = require('../lib/mp-weixin/transform/template-transformer') // console.log(transformTemplate( -// ``, { +// ``, { // filename: 'index' // } // )) diff --git a/packages/uni-migration/__tests__/wxml.spec.js b/packages/uni-migration/__tests__/wxml.spec.js index fb4ecade4eb9e7de07214196280ca6aa0adaf99f..a1f64f86113f82e0f48b4c9b66a255e42d2b31f4 100644 --- a/packages/uni-migration/__tests__/wxml.spec.js +++ b/packages/uni-migration/__tests__/wxml.spec.js @@ -24,7 +24,7 @@ describe('wxml:compiler', () => { `` ) assertCodegen( - '', + '', `` ) assertCodegen( diff --git a/packages/uni-migration/lib/index.js b/packages/uni-migration/lib/index.js index 0b406e7673006e4b6a50c5e44149333b0909d784..933d7223a6940e8137d58e2f9d3b2998a2d36459 100644 --- a/packages/uni-migration/lib/index.js +++ b/packages/uni-migration/lib/index.js @@ -20,6 +20,7 @@ module.exports = function migrate(input, out, options = { } const [files, assets] = migrater.transform(input, out, options) files.forEach(file => { + migrater.patch.vue(file) console.log(`write: ${file.path}`) fs.outputFileSync(file.path, file.content) }) @@ -30,7 +31,7 @@ module.exports = function migrate(input, out, options = { if (typeof asset === 'string') { const src = path.resolve(input, asset) const dest = path.resolve(out, asset.replace(styleExtname, '.css')) - if (!migrater.patch(src, dest)) { + if (!migrater.patch.asset(src, dest)) { if ( needCopy || ( asset.indexOf(styleExtname) !== -1 && diff --git a/packages/uni-migration/lib/mp-weixin/patch.js b/packages/uni-migration/lib/mp-weixin/patch.js index 8b872e0cff5c8f45e03449ac3b85bfb85ba950c7..f9f41d53a68ce5ae1e896e7f22296bed5e5eb6b1 100644 --- a/packages/uni-migration/lib/mp-weixin/patch.js +++ b/packages/uni-migration/lib/mp-weixin/patch.js @@ -4,40 +4,52 @@ const { normalizePath } = require('./util') -const VANTS = [{ // wxs array.constructor +const VANT_ASSETS = [{ // wxs array.constructor test(src) { return src.indexOf('array.wxs') !== -1 }, source(code) { return code.replace(`array.constructor === 'Array'`, 'Array.isArray(array)') } -}, { // vue $options conflicts - test(src) { - return normalizePath(src).indexOf('mixins/observer/index.js') !== -1 - }, - source(code) { - return code.replace(`options.methods.$options`, `options.methods.$getVantOptions`) - } -}, { // vue $options conflicts - test(src) { - return normalizePath(src).indexOf('mixins/observer/behavior.js') !== -1 +}] + +const PATCH_ASSETS = [ + ...VANT_ASSETS +] + +const VANT_VUES = [{ + test(file) { + return normalizePath(file.path).indexOf('/image/index.vue') !== -1 }, source(code) { - return code.replace(`!this.$options`, `!this.$getVantOptions`) - .replace(`this.$options()`, `this.$getVantOptions()`) + // onLoad 与 onError 是生命周期函数名,需要替换为其他 + return code.replace(/onLoad/g, 'onImageLoad') + .replace(/onError/g, 'onImageError') } -}] +}] -const PATCHS = [ - ...VANTS +const PATCH_VUES = [ + ...VANT_VUES ] -module.exports = function patch(src, dest) { - const options = PATCHS.find(patch => patch.test(src)) +function patchAsset(src, dest) { + const options = PATCH_ASSETS.find(patch => patch.test(src)) if (options) { console.log(`write: ${dest}`) fs.outputFileSync(dest, options.source(fs.readFileSync(src).toString())) return true } return false +} + +function patchVue(file) { + const options = PATCH_VUES.find(patch => patch.test(file)) + if (options) { + file.content = options.source(file.content) + } +} + +module.exports = { + vue: patchVue, + asset: patchAsset } diff --git a/packages/uni-migration/lib/mp-weixin/transform/template-transformer/transform/traverse.js b/packages/uni-migration/lib/mp-weixin/transform/template-transformer/transform/traverse.js index accfcd84f6714224e8cf1bd2e984d4afa77b826b..64ccaa234768db8b8b1f69d366198de5fe0e63cd 100644 --- a/packages/uni-migration/lib/mp-weixin/transform/template-transformer/transform/traverse.js +++ b/packages/uni-migration/lib/mp-weixin/transform/template-transformer/transform/traverse.js @@ -64,10 +64,14 @@ function transformFor(attribs) { //处理 wx:for-item="index" ) - attribs['v-for'] = `(${vItem},${vIndex}) in (${parseMustache(vFor)})` - if (vKey) { - vKey === '*this' ? (vKey = vItem) : (vKey = vItem + '.' + vKey) - attribs[':key'] = vKey + attribs['v-for'] = `(${vItem},${vIndex}) in (${parseMustache(vFor)})` + if (vKey) { + if (vKey === '*this') { + vKey = vItem + } else if (vKey !== vItem) { + vKey = vItem + '.' + vKey + } + attribs[':key'] = vKey } delete attribs[FOR.for] diff --git a/packages/uni-mp-weixin/dist/mp.js b/packages/uni-mp-weixin/dist/mp.js index f335b8c2e4a7626c440669260ddf511c8a2f88cb..426517fd8447b303669af156c815d0b7d6821740 100644 --- a/packages/uni-mp-weixin/dist/mp.js +++ b/packages/uni-mp-weixin/dist/mp.js @@ -1,3 +1,5 @@ +import Vue from 'vue'; + function parseData (data, vueComponentOptions) { if (!data) { return @@ -397,6 +399,34 @@ function proxy (target, sourceKey, key) { Object.defineProperty(target, key, sharedPropertyDefinition); } +function setDataByExprPath (exprPath, value, data) { + const keys = exprPath.replace(/\[(\d+?)\]/g, '.$1').split('.'); + keys.reduce((obj, key, idx) => { + if (idx === keys.length - 1) { + obj[key] = value; + } else { + if (typeof obj[key] === 'undefined') { + obj[key] = {}; + } + return obj[key] + } + }, data); + return keys.length === 1 +} + +function setData (data, callback) { + if (!isPlainObject(data)) { + return + } + Object.keys(data).forEach(key => { + if (setDataByExprPath(key, data[key], this.data)) { + !hasOwn(this, key) && proxy(this, SOURCE_KEY, key); + } + }); + this.$forceUpdate(); + isFn(callback) && this.$nextTick(callback); +} + const PROP_DEFAULT_VALUES = { String: '', Number: 0, @@ -474,24 +504,24 @@ function initProperties (vm, instanceData) { return value }, set (newVal) { + const oldVal = value; + /* eslint-disable no-self-compare */ + if (newVal === value || (newVal !== newVal && value !== value)) { + return + } if (observer) { - const oldVal = value; - /* eslint-disable no-self-compare */ - if (newVal === value || (newVal !== newVal && value !== value)) { - return - } value = newVal; observe(observer, vm, newVal, oldVal); - } else { - value = newVal; } + // 触发渲染 + vm.$forceUpdate(); } }); } } function updateProperties (vm) { - const properties = vm.$options.mpOptions.properties; + const properties = vm.$options.mpOptions && vm.$options.mpOptions.properties; const propsData = vm.$options.propsData; if (propsData && properties) { Object.keys(properties).forEach(key => { @@ -526,20 +556,7 @@ function initState (vm) { properties: propertyDefinition }); - vm.setData = (data, callback) => { - // TODO data path: array[0].text,object.text - if (!isPlainObject(data)) { - return - } - Object.keys(data).forEach(key => { - vm.data[key] = data[key]; - if (!hasOwn(vm, key)) { - proxy(vm, SOURCE_KEY, key); - } - }); - vm.$forceUpdate(); - isFn(callback) && vm.$nextTick(callback); - }; + vm.setData = setData; initProperties(vm, instanceData); @@ -568,6 +585,8 @@ function initMethods (vm) { /* eslint-disable no-mixed-operators */ return vm._$relationNodes && vm._$relationNodes[relationKey] || [] }; + + vm._$updateProperties = updateProperties; } function initRelationHandlers (type, handler, target, ctx, handlerCtx) { @@ -696,9 +715,6 @@ var polyfill = { mounted () { handleObservers(this); }, - beforeUpdate () { - updateProperties(this); - }, beforeDestroy () { handleRelations(this, 'unlinked'); } @@ -742,6 +758,9 @@ function Component (options) { function Behavior (options) { return options -} +} + +const nextTick = Vue.nextTick; -export { Behavior, Component, Page, getDate, getRegExp }; +export default uni; +export { Behavior, Component, Page, getDate, getRegExp, nextTick }; diff --git a/packages/vue-cli-plugin-uni/lib/app-plus/index.js b/packages/vue-cli-plugin-uni/lib/app-plus/index.js index 3e62e58d68b1ad5b2379b7c17bd5f2a35ec4ce5e..293e9e7b0f24892a7d3e45670c1bbb5190fcf9ee 100644 --- a/packages/vue-cli-plugin-uni/lib/app-plus/index.js +++ b/packages/vue-cli-plugin-uni/lib/app-plus/index.js @@ -21,8 +21,9 @@ const runtimePath = '@dcloudio/uni-mp-weixin/dist/mp.js' function getProvides () { return { '__f__': [path.resolve(__dirname, '../format-log.js'), 'default'], - 'wx': ['@dcloudio/uni-app-plus/dist/uni.js', 'default'], - 'Page': [runtimePath, 'Page'], + 'wx': [runtimePath, 'default'], + 'wx.nextTick': [runtimePath, 'nextTick'], + 'Page': [runtimePath, 'Page'], 'Component': [runtimePath, 'Component'], 'Behavior': [runtimePath, 'Behavior'], 'getDate': [runtimePath, 'getDate'], diff --git a/src/core/runtime/mp/index.js b/src/core/runtime/mp/index.js index d80636968ac9364a21ad9b30c3dcc3c77cec3a7a..7cf86b7086050ea9c9ad62f7091e6ed4917c0242 100644 --- a/src/core/runtime/mp/index.js +++ b/src/core/runtime/mp/index.js @@ -1,3 +1,5 @@ +import Vue from 'vue' + import { parsePage } from './parser/page-parser' @@ -30,4 +32,8 @@ export function Component (options) { export function Behavior (options) { return options -} +} + +export const nextTick = Vue.nextTick + +export default uni diff --git a/src/core/runtime/mp/polyfill/index.js b/src/core/runtime/mp/polyfill/index.js index f8fa62db0afe1dda4318c9813da5297dc2fe0a4c..5363e7125ea54fbf48b67acdc258475d57c6ab60 100644 --- a/src/core/runtime/mp/polyfill/index.js +++ b/src/core/runtime/mp/polyfill/index.js @@ -13,11 +13,7 @@ import { import { handleObservers -} from './observers' - -import { - updateProperties -} from './state/properties' +} from './observers' export default { beforeCreate () { @@ -31,9 +27,6 @@ export default { mounted () { handleObservers(this) }, - beforeUpdate () { - updateProperties(this) - }, beforeDestroy () { handleRelations(this, 'unlinked') } diff --git a/src/core/runtime/mp/polyfill/methods.js b/src/core/runtime/mp/polyfill/methods.js index 6c8deffd7ab6b92e54055af57bf50ee3e0a41453..59c176679b0cdeb55c7af03e09ff8ce829c83dcb 100644 --- a/src/core/runtime/mp/polyfill/methods.js +++ b/src/core/runtime/mp/polyfill/methods.js @@ -1,3 +1,7 @@ +import { + updateProperties +} from './state/properties' + export function initMethods (vm) { const oldEmit = vm.$emit vm.triggerEvent = (eventName, detail, options) => { @@ -18,4 +22,6 @@ export function initMethods (vm) { /* eslint-disable no-mixed-operators */ return vm._$relationNodes && vm._$relationNodes[relationKey] || [] } + + vm._$updateProperties = updateProperties } diff --git a/src/core/runtime/mp/polyfill/state/data.js b/src/core/runtime/mp/polyfill/state/data.js new file mode 100644 index 0000000000000000000000000000000000000000..10e6813424e1edf46cab943c2b1471e8b123f6c8 --- /dev/null +++ b/src/core/runtime/mp/polyfill/state/data.js @@ -0,0 +1,41 @@ +import { + isFn, + hasOwn, + isPlainObject +} from 'uni-shared' + +import { + proxy +} from './proxy' + +import { + SOURCE_KEY +} from '../../constants' + +function setDataByExprPath (exprPath, value, data) { + const keys = exprPath.replace(/\[(\d+?)\]/g, '.$1').split('.') + keys.reduce((obj, key, idx) => { + if (idx === keys.length - 1) { + obj[key] = value + } else { + if (typeof obj[key] === 'undefined') { + obj[key] = {} + } + return obj[key] + } + }, data) + return keys.length === 1 +} + +export function setData (data, callback) { + if (!isPlainObject(data)) { + return + } + Object.keys(data).forEach(key => { + if (setDataByExprPath(key, data[key], this.data)) { + !hasOwn(this, key) && proxy(this, SOURCE_KEY, key) + } + }) + this.$forceUpdate() + isFn(callback) && this.$nextTick(callback) +} diff --git a/src/core/runtime/mp/polyfill/state/index.js b/src/core/runtime/mp/polyfill/state/index.js index 2744b801fd7b850d4f171e43319230968339aba0..b99343331be5c9e4bb2290e8e3f12f0434575761 100644 --- a/src/core/runtime/mp/polyfill/state/index.js +++ b/src/core/runtime/mp/polyfill/state/index.js @@ -1,9 +1,3 @@ -import { - isFn, - hasOwn, - isPlainObject -} from 'uni-shared' - import { SOURCE_KEY } from '../../constants' @@ -12,6 +6,10 @@ import { proxy } from './proxy' +import { + setData +} from './data' + import { initProperties } from './properties' @@ -35,20 +33,7 @@ export function initState (vm) { properties: propertyDefinition }) - vm.setData = (data, callback) => { - // TODO data path: array[0].text,object.text - if (!isPlainObject(data)) { - return - } - Object.keys(data).forEach(key => { - vm.data[key] = data[key] - if (!hasOwn(vm, key)) { - proxy(vm, SOURCE_KEY, key) - } - }) - vm.$forceUpdate() - isFn(callback) && vm.$nextTick(callback) - } + vm.setData = setData initProperties(vm, instanceData) diff --git a/src/core/runtime/mp/polyfill/state/properties.js b/src/core/runtime/mp/polyfill/state/properties.js index a6e80ce2212223c0513f26beef99632bd46030af..0d55c3aae22f3f8ae7e9b1c6913d1d6fab9a96f5 100644 --- a/src/core/runtime/mp/polyfill/state/properties.js +++ b/src/core/runtime/mp/polyfill/state/properties.js @@ -80,24 +80,24 @@ export function initProperties (vm, instanceData) { return value }, set (newVal) { + const oldVal = value + /* eslint-disable no-self-compare */ + if (newVal === value || (newVal !== newVal && value !== value)) { + return + } if (observer) { - const oldVal = value - /* eslint-disable no-self-compare */ - if (newVal === value || (newVal !== newVal && value !== value)) { - return - } value = newVal observe(observer, vm, newVal, oldVal) - } else { - value = newVal } + // 触发渲染 + vm.$forceUpdate() } }) } } export function updateProperties (vm) { - const properties = vm.$options.mpOptions.properties + const properties = vm.$options.mpOptions && vm.$options.mpOptions.properties const propsData = vm.$options.propsData if (propsData && properties) { Object.keys(properties).forEach(key => {