提交 68323555 编写于 作者: Q qiang

Merge branch 'dev' into alpha

......@@ -165,3 +165,7 @@ uniCloud服务商为阿里云时支持配置全球加速,步骤如下:
4. 选择不使用的账号登录之后注销即可,参考文档:[注销腾讯云账号](https://cloud.tencent.com/document/product/378/30253)
同时,如果付费购买腾讯云服务空间,每个账号可以最多拥有50个腾讯云服务空间(注意其中仅有一个享受免费额度)。
### 部署网站到前端网页托管报“The requested file was not found on this server.”
- 部署history模式的uni-app项目时,如果未修改前端网页托管的配置,直接访问子页面时就会遇到上面的错误。如何配置请参考[部署uni-app项目](uniCloud/hosting.md?id=host-uni-app)
\ No newline at end of file
......@@ -151,6 +151,21 @@ uni.request({
+ 请求Body大小限制,不能超过1M。
+ 响应Body大小限制,不能超过1M。
云函数接收到的post请求的请求体可能是被转成base64的,如果是这样需要进行一次转化。
以接收application/json格式的post请求为例
```js
exports.main = function(event) {
let body = event.body
if(event.isBase64Encoded){
body = Buffer.from(body)
}
const param = JSON.parse(body) // param为客户端上传的数据
// ...
}
```
### 云函数的返回值
......@@ -160,7 +175,7 @@ uni.request({
云函数返回字符串,那么:
```js
module.exports.main = function() {
exports.main = function() {
return 'hello gateway'
}
```
......@@ -180,7 +195,7 @@ hello gateway
返回的`Object`会被转换为 JSON,同时 HTTP 响应的`content-type`会被设置为 `application/json`
```js
module.exports.main = function() {
exports.main = function() {
return {
foo: 'bar'
}
......@@ -216,7 +231,7 @@ content-length: 13
`content-type`设置为`text/html`,即可在`body`中返回 HTML,会被浏览器自动解析:
```js
module.exports.main = function() {
exports.main = function() {
return {
mpserverlessComposedResponse: true, // 使用阿里云返回集成响应是需要此字段为true
statusCode: 200,
......@@ -243,7 +258,7 @@ content-length: 14
`content-type`设置为`application/javascript`,即可在`body`中返回 JavaScript 文件:
```js
module.exports.main = function() {
exports.main = function() {
return {
mpserverlessComposedResponse: true, // 使用阿里云返回集成响应是需要此字段为true
statusCode: 200,
......@@ -270,7 +285,7 @@ console.log("Hello!")
如果返回体是诸如图片、音视频这样的二进制文件,那么可以将`isBase64Encoded`设置为`true`,并且将二进制文件内容转为 Base64 编码的字符串,例如:
```js
module.exports.main = function() {
exports.main = function() {
return {
mpserverlessComposedResponse: true, // 使用阿里云返回集成响应是需要此字段为true
isBase64Encoded: true,
......
......@@ -171,7 +171,10 @@ const ui = [
'showRightWindow',
'hideTopWindow',
'hideLeftWindow',
'hideRightWindow'
'hideRightWindow',
'setTopWindowStyle',
'setLeftWindowStyle',
'setRightWindowStyle'
]
const event = [
......
......@@ -182,7 +182,10 @@ var serviceContext = (function () {
'showRightWindow',
'hideTopWindow',
'hideLeftWindow',
'hideRightWindow'
'hideRightWindow',
'setTopWindowStyle',
'setLeftWindowStyle',
'setRightWindowStyle'
];
const event = [
......@@ -1349,7 +1352,7 @@ var serviceContext = (function () {
},
extension: {
type: Array,
default: ['*']
default: ['']
}
};
......@@ -8632,6 +8635,9 @@ var serviceContext = (function () {
}
if (!entryPagePath || entryPagePath === __uniConfig.entryPagePath) {
if (entryPageQuery) {
__uniConfig.entryPageQuery = entryPageQuery;
}
return
}
......
<template>
<view>
<slot
:options="options"
:data="dataList"
:pagination="paginationInternal"
:loading="loading"
:error="errorMessage"
/>
</view>
</template>
<script>
const events = {
load: 'load',
error: 'error'
}
const pageMode = {
add: 'add',
replace: 'replace'
}
const attrs = [
'pageCurrent',
'pageSize',
'collection',
'action',
'field',
'getcount',
'orderby',
'where'
]
export default {
name: 'UniClouddb',
props: {
options: {
type: [Object, Array],
default () {
return {}
}
},
collection: {
type: String,
default: ''
},
action: {
type: String,
default: ''
},
field: {
type: String,
default: ''
},
pageData: {
type: String,
default: 'add'
},
pageCurrent: {
type: Number,
default: 1
},
pageSize: {
type: Number,
default: 20
},
getcount: {
type: [Boolean, String],
default: false
},
orderby: {
type: String,
default: ''
},
where: {
type: [String, Object],
default: ''
},
getone: {
type: [Boolean, String],
default: false
},
manual: {
type: Boolean,
default: false
}
},
data () {
return {
loading: false,
dataList: this.getone ? {} : [],
paginationInternal: {
current: this.pageCurrent,
size: this.pageSize,
count: 0
},
errorMessage: ''
}
},
created () {
this._isEnded = false
this.$watch(() => {
var al = []
attrs.forEach(key => {
al.push(this[key])
})
return al
}, (newValue, oldValue) => {
this.paginationInternal.pageSize = this.pageSize
let needReset = false
for (let i = 2; i < newValue.length; i++) {
if (newValue[i] !== oldValue[i]) {
needReset = true
break
}
}
if (needReset) {
this.clear()
this.reset()
}
if (newValue[0] !== oldValue[0]) {
this.paginationInternal.current = this.pageCurrent
}
this._execLoadData()
})
// #ifdef H5
if (process.env.NODE_ENV === 'development') {
this._debugDataList = []
if (!window.unidev) {
window.unidev = {
clientDB: {
data: []
}
}
}
window.unidev.clientDB.data.push(this._debugDataList)
}
// #endif
// #ifdef MP-TOUTIAO
let changeName
const events = this.$scope.dataset.eventOpts
for (var i = 0; i < events.length; i++) {
const event = events[i]
if (event[0].includes('^load')) {
changeName = event[1][0][0]
}
}
if (changeName) {
let parent = this.$parent
let maxDepth = 16
this._changeDataFunction = null
while (parent && maxDepth > 0) {
const fun = parent[changeName]
if (fun && typeof fun === 'function') {
this._changeDataFunction = fun
maxDepth = 0
break
}
parent = parent.$parent
maxDepth--
}
}
// #endif
if (!this.manual) {
this.loadData()
}
},
// #ifdef H5
beforeDestroy () {
if (process.env.NODE_ENV === 'development' && window.unidev) {
var cd = this._debugDataList
var dl = window.unidev.clientDB.data
for (var i = dl.length - 1; i >= 0; i--) {
if (dl[i] === cd) {
dl.splice(i, 1)
break
}
}
}
},
// #endif
methods: {
loadData (args1, args2) {
let callback = null
if (typeof args1 === 'object') {
if (args1.clear) {
this.clear()
this.reset()
}
if (args1.current !== undefined) {
this.paginationInternal.current = args1.current
}
if (typeof args2 === 'function') {
callback = args2
}
} else if (typeof args1 === 'function') {
callback = args1
}
this._execLoadData(callback)
},
loadMore () {
if (this._isEnded) {
return
}
this._execLoadData()
},
refresh () {
this.clear()
this._execLoadData()
},
clear () {
this._isEnded = false
this.dataList = []
},
reset () {
this.paginationInternal.current = 1
},
remove (id, {
action,
callback,
confirmTitle,
confirmContent
} = {}) {
if (!id || !id.length) {
return
}
uni.showModal({
title: confirmTitle || '提示',
content: confirmContent || '是否删除该数据',
showCancel: true,
success: (res) => {
if (!res.confirm) {
return
}
this._execRemove(id, action, callback)
}
})
},
_execLoadData (callback) {
if (this.loading) {
return
}
this.loading = true
this.errorMessage = ''
this._getExec().then((res) => {
this.loading = false
const {
data,
count
} = res.result
this._isEnded = data.length < this.pageSize
callback && callback(data, this._isEnded)
this._dispatchEvent(events.load, data)
if (this.getone) {
this.dataList = data.length ? data[0] : undefined
} else if (this.pageData === pageMode.add) {
this.dataList.push(...data)
if (this.dataList.length) {
this.paginationInternal.current++
}
} else if (this.pageData === pageMode.replace) {
this.dataList = data
}
if (this.getcount) {
this.paginationInternal.count = count
}
// #ifdef H5
if (process.env.NODE_ENV === 'development') {
this._debugDataList.length = 0
this._debugDataList.push(...JSON.parse(JSON.stringify(this.dataList)))
}
// #endif
}).catch((err) => {
this.loading = false
this.errorMessage = err
callback && callback()
this.$emit(events.error, err)
})
},
_getExec () {
/* eslint-disable no-undef */
let db = uniCloud.database()
if (this.action) {
db = db.action(this.action)
}
db = db.collection(this.collection)
if (!(!this.where || !Object.keys(this.where).length)) {
db = db.where(this.where)
}
if (this.field) {
db = db.field(this.field)
}
if (this.orderby) {
db = db.orderBy(this.orderby)
}
const {
current,
size
} = this.paginationInternal
db = db.skip(size * (current - 1)).limit(size).get({
getCount: this.getcount
})
return db
},
_execRemove (id, action, callback) {
if (!this.collection || !id) {
return
}
const ids = Array.isArray(id) ? id : [id]
if (!ids.length) {
return
}
uni.showLoading({
mask: true
})
/* eslint-disable no-undef */
const db = uniCloud.database()
const dbCmd = db.command
let exec = db
if (action) {
exec = exec.action(action)
}
exec.collection(this.collection).where({
_id: dbCmd.in(ids)
}).remove().then((res) => {
callback && callback(res.result)
if (this.pageData === pageMode.replace) {
this.refresh()
} else {
this.removeData(ids)
}
}).catch((err) => {
uni.showModal({
content: err.message,
showCancel: false
})
}).finally(() => {
uni.hideLoading()
})
},
removeData (ids) {
const il = ids.slice(0)
const dl = this.dataList
for (let i = dl.length - 1; i >= 0; i--) {
const index = il.indexOf(dl[i]._id)
if (index >= 0) {
dl.splice(i, 1)
il.splice(index, 1)
}
}
},
_dispatchEvent (type, data) {
if (this._changeDataFunction) {
this._changeDataFunction(data, this._isEnded)
} else {
this.$emit(type, data, this._isEnded)
}
}
}
}
</script>
......@@ -504,7 +504,7 @@ function parseUsingAutoImportComponents (usingAutoImportComponents) {
return autoImportComponents
}
const BUILT_IN_COMPONENTS = ['page-meta', 'navigation-bar', 'uni-match-media']
const BUILT_IN_COMPONENTS = ['page-meta', 'navigation-bar', 'uni-match-media', 'unicloud-db']
function isBuiltInComponent (name) {
return BUILT_IN_COMPONENTS.includes(name)
......
import { isSymbol, extend, isMap, isObject, toRawType, def, isArray, isString, isFunction, isPromise, toHandlerKey, remove, EMPTY_OBJ, NOOP, isGloballyWhitelisted, isIntegerKey, hasOwn, hasChanged, capitalize, NO, invokeArrayFns, isSet, makeMap, toNumber, hyphenate, camelize, isReservedProp, EMPTY_ARR, toTypeString, isOn } from '@vue/shared';
import { isSymbol, extend, isMap, isObject, toRawType, def, isArray, isString, isFunction, isPromise, capitalize, toHandlerKey, remove, EMPTY_OBJ, NOOP, isGloballyWhitelisted, isIntegerKey, hasOwn, hasChanged, camelize, NO, invokeArrayFns, isSet, makeMap, toNumber, hyphenate, isReservedProp, EMPTY_ARR, toTypeString, isOn } from '@vue/shared';
export { camelize } from '@vue/shared';
const targetMap = new WeakMap();
......@@ -238,7 +238,7 @@ function createGetter(isReadonly = false, shallow = false) {
return target;
}
const targetIsArray = isArray(target);
if (targetIsArray && hasOwn(arrayInstrumentations, key)) {
if (!isReadonly && targetIsArray && hasOwn(arrayInstrumentations, key)) {
return Reflect.get(arrayInstrumentations, key, receiver);
}
const res = Reflect.get(target, key, receiver);
......@@ -393,11 +393,11 @@ function add(value) {
const target = toRaw(this);
const proto = getProto(target);
const hadKey = proto.has.call(target, value);
const result = target.add(value);
target.add(value);
if (!hadKey) {
trigger(target, "add" /* ADD */, value, value);
}
return result;
return this;
}
function set$1(key, value) {
value = toRaw(value);
......@@ -412,14 +412,14 @@ function set$1(key, value) {
checkIdentityKeys(target, has, key);
}
const oldValue = get.call(target, key);
const result = target.set(key, value);
target.set(key, value);
if (!hadKey) {
trigger(target, "add" /* ADD */, key, value);
}
else if (hasChanged(value, oldValue)) {
trigger(target, "set" /* SET */, key, value, oldValue);
}
return result;
return this;
}
function deleteEntry(key) {
const target = toRaw(this);
......@@ -630,19 +630,27 @@ function reactive(target) {
}
return createReactiveObject(target, false, mutableHandlers, mutableCollectionHandlers);
}
// Return a reactive-copy of the original object, where only the root level
// properties are reactive, and does NOT unwrap refs nor recursively convert
// returned properties.
/**
* Return a shallowly-reactive copy of the original object, where only the root
* level properties are reactive. It also does not auto-unwrap refs (even at the
* root level).
*/
function shallowReactive(target) {
return createReactiveObject(target, false, shallowReactiveHandlers, shallowCollectionHandlers);
}
/**
* Creates a readonly copy of the original object. Note the returned copy is not
* made reactive, but `readonly` can be called on an already reactive object.
*/
function readonly(target) {
return createReactiveObject(target, true, readonlyHandlers, readonlyCollectionHandlers);
}
// Return a reactive-copy of the original object, where only the root level
// properties are readonly, and does NOT unwrap refs nor recursively convert
// returned properties.
// This is used for creating the props proxy object for stateful components.
/**
* Returns a reactive-copy of the original object, where only the root level
* properties are readonly, and does NOT unwrap refs nor recursively convert
* returned properties.
* This is used for creating the props proxy object for stateful components.
*/
function shallowReadonly(target) {
return createReactiveObject(target, true, shallowReadonlyHandlers, readonlyCollectionHandlers);
}
......@@ -1189,8 +1197,6 @@ function flushJobs(seen) {
// priority number)
// 2. If a component is unmounted during a parent component's update,
// its update can be skipped.
// Jobs can never be null before flush starts, since they are only invalidated
// during execution of another flushed job.
queue.sort((a, b) => getId(a) - getId(b));
try {
for (flushIndex = 0; flushIndex < queue.length; flushIndex++) {
......@@ -1346,17 +1352,71 @@ function isEmitListener(options, key) {
if (!options || !isOn(key)) {
return false;
}
key = key.replace(/Once$/, '');
return (hasOwn(options, key[2].toLowerCase() + key.slice(3)) ||
hasOwn(options, key.slice(2)));
key = key.slice(2).replace(/Once$/, '');
return (hasOwn(options, key[0].toLowerCase() + key.slice(1)) ||
hasOwn(options, hyphenate(key)) ||
hasOwn(options, key));
}
// mark the current rendering instance for asset resolution (e.g.
// resolveComponent, resolveDirective) during render
/**
* mark the current rendering instance for asset resolution (e.g.
* resolveComponent, resolveDirective) during render
*/
let currentRenderingInstance = null;
function markAttrsAccessed() {
}
const COMPONENTS = 'components';
const DIRECTIVES = 'directives';
/**
* @private
*/
function resolveDirective(name) {
return resolveAsset(DIRECTIVES, name);
}
// implementation
function resolveAsset(type, name, warnMissing = true) {
const instance = currentInstance;
if (instance) {
const Component = instance.type;
// self name has highest priority
if (type === COMPONENTS) {
// special self referencing call generated by compiler
// inferred from SFC filename
if (name === `_self`) {
return Component;
}
const selfName = Component.displayName || Component.name;
if (selfName &&
(selfName === name ||
selfName === camelize(name) ||
selfName === capitalize(camelize(name)))) {
return Component;
}
}
const res =
// local registration
// check instance[type] first for components with mixin or extends.
resolve(instance[type] || Component[type], name) ||
// global registration
resolve(instance.appContext[type], name);
if ((process.env.NODE_ENV !== 'production') && warnMissing && !res) {
warn(`Failed to resolve ${type.slice(0, -1)}: ${name}`);
}
return res;
}
else if ((process.env.NODE_ENV !== 'production')) {
warn(`resolve${capitalize(type.slice(0, -1))} ` +
`can only be used in render() or setup().`);
}
}
function resolve(registry, name) {
return (registry &&
(registry[name] ||
registry[camelize(name)] ||
registry[capitalize(camelize(name))]));
}
function initProps(instance, rawProps, isStateful, // result of bitwise flag comparison
isSSR = false) {
const props = {};
......@@ -1789,6 +1849,15 @@ function validateDirectiveName(name) {
if (isBuiltInDirective(name)) {
warn('Do not use built-in directive ids as custom directive id: ' + name);
}
}
/**
* Adds directives to a VNode.
*/
function withDirectives(vnode, directives) {
{
(process.env.NODE_ENV !== 'production') && warn(`withDirectives can only be used inside render functions.`);
return vnode;
}
}
function createAppContext() {
......@@ -1919,6 +1988,11 @@ function createAppAPI() {
};
}
// implementation, close to no-op
function defineComponent(options) {
return isFunction(options) ? { setup: options, name: options.name } : options;
}
const queuePostRenderEffect = queuePostFlushCb;
// Simple effect.
......@@ -2065,7 +2139,7 @@ function doWatch(source, cb, { immediate, deep, flush, onTrack, onTrigger } = EM
onTrigger,
scheduler
});
recordInstanceBoundEffect(runner);
recordInstanceBoundEffect(runner, instance);
// initial run
if (cb) {
if (immediate) {
......@@ -2193,7 +2267,9 @@ function applyOptions(instance, options, deferredData = [], deferredWatch = [],
// assets
components, directives,
// lifecycle
beforeMount, mounted, beforeUpdate, updated, activated, deactivated, beforeDestroy, beforeUnmount, destroyed, unmounted, render, renderTracked, renderTriggered, errorCaptured } = options;
beforeMount, mounted, beforeUpdate, updated, activated, deactivated, beforeDestroy, beforeUnmount, destroyed, unmounted, render, renderTracked, renderTriggered, errorCaptured,
// public API
expose } = options;
const publicThis = instance.proxy;
const ctx = instance.ctx;
const globalMixins = instance.appContext.mixins;
......@@ -2352,9 +2428,9 @@ function applyOptions(instance, options, deferredData = [], deferredWatch = [],
const provides = isFunction(provideOptions)
? provideOptions.call(publicThis)
: provideOptions;
for (const key in provides) {
Reflect.ownKeys(provides).forEach(key => {
provide(key, provides[key]);
}
});
});
}
}
......@@ -2420,6 +2496,22 @@ function applyOptions(instance, options, deferredData = [], deferredWatch = [],
if (unmounted) {
onUnmounted(unmounted.bind(publicThis));
}
if (isArray(expose)) {
if (!asMixin) {
if (expose.length) {
const exposed = instance.exposed || (instance.exposed = proxyRefs({}));
expose.forEach(key => {
exposed[key] = toRef(publicThis, key);
});
}
else if (!instance.exposed) {
instance.exposed = EMPTY_OBJ;
}
}
else if ((process.env.NODE_ENV !== 'production')) {
warn(`The \`expose\` option is ignored when used in mixins.`);
}
}
// fixed by xxxxxx
if (instance.ctx.$onApplyOptions) {
instance.ctx.$onApplyOptions(options, instance, publicThis);
......@@ -2562,6 +2654,12 @@ function mergeOptions(to, from, instance) {
}
}
/**
* #2437 In Vue 3, functional components do not have a public instance proxy but
* they exist in the internal parent chain. For code that relies on traversing
* public $parent chains, skip functional ones and go to the parent instead.
*/
const getPublicInstance = (i) => i && (i.proxy ? i.proxy : getPublicInstance(i.parent));
const publicPropertiesMap = extend(Object.create(null), {
$: i => i,
$el: i => i.vnode.el,
......@@ -2570,7 +2668,7 @@ const publicPropertiesMap = extend(Object.create(null), {
$attrs: i => ((process.env.NODE_ENV !== 'production') ? shallowReadonly(i.attrs) : i.attrs),
$slots: i => ((process.env.NODE_ENV !== 'production') ? shallowReadonly(i.slots) : i.slots),
$refs: i => ((process.env.NODE_ENV !== 'production') ? shallowReadonly(i.refs) : i.refs),
$parent: i => i.parent && i.parent.proxy,
$parent: i => getPublicInstance(i.parent),
$root: i => i.root && i.root.proxy,
$emit: i => i.emit,
$options: i => (__VUE_OPTIONS_API__ ? resolveMergedOptions(i) : i.type),
......@@ -2831,6 +2929,7 @@ function createComponentInstance(vnode, parent, suspense) {
update: null,
render: null,
proxy: null,
exposed: null,
withProxy: null,
effects: null,
provides: parent ? parent.provides : Object.create(appContext.provides),
......@@ -2973,7 +3072,9 @@ function setupStatefulComponent(instance, isSSR) {
function handleSetupResult(instance, setupResult, isSSR) {
if (isFunction(setupResult)) {
// setup returned an inline render function
instance.render = setupResult;
{
instance.render = setupResult;
}
}
else if (isObject(setupResult)) {
// if ((process.env.NODE_ENV !== 'production') && isVNode(setupResult)) {
......@@ -3012,7 +3113,9 @@ function finishComponentSetup(instance, isSSR) {
// support for 2.x options
if (__VUE_OPTIONS_API__) {
currentInstance = instance;
pauseTracking();
applyOptions(instance, Component);
resetTracking();
currentInstance = null;
}
// warn missing template/render
......@@ -3044,10 +3147,19 @@ const attrHandlers = {
}
};
function createSetupContext(instance) {
const expose = exposed => {
if ((process.env.NODE_ENV !== 'production') && instance.exposed) {
warn(`expose() should be called only once per setup().`);
}
instance.exposed = proxyRefs(exposed);
};
if ((process.env.NODE_ENV !== 'production')) {
// We use getters in dev in case libs like test-utils overwrite instance
// properties (overwrites should not be done in prod)
return Object.freeze({
get props() {
return instance.props;
},
get attrs() {
return new Proxy(instance.attrs, attrHandlers);
},
......@@ -3056,22 +3168,24 @@ function createSetupContext(instance) {
},
get emit() {
return (event, ...args) => instance.emit(event, ...args);
}
},
expose
});
}
else {
return {
attrs: instance.attrs,
slots: instance.slots,
emit: instance.emit
emit: instance.emit,
expose
};
}
}
// record effects created during a component's setup() so that they can be
// stopped when the component unmounts
function recordInstanceBoundEffect(effect) {
if (currentInstance) {
(currentInstance.effects || (currentInstance.effects = [])).push(effect);
function recordInstanceBoundEffect(effect, instance = currentInstance) {
if (instance) {
(instance.effects || (instance.effects = [])).push(effect);
}
}
const classifyRE = /(?:^|[-_])(\w)/g;
......@@ -3082,7 +3196,7 @@ function formatComponentName(instance, Component, isRoot = false) {
? Component.displayName || Component.name
: Component.name;
if (!name && Component.__file) {
const match = Component.__file.match(/([^/\\]+)\.vue$/);
const match = Component.__file.match(/([^/\\]+)\.\w+$/);
if (match) {
name = match[1];
}
......@@ -3109,8 +3223,27 @@ function computed$1(getterOrOptions) {
return c;
}
// implementation
function defineProps() {
if ((process.env.NODE_ENV !== 'production')) {
warn(`defineProps() is a compiler-hint helper that is only usable inside ` +
`<script setup> of a single file component. Its arguments should be ` +
`compiled away and passing it at runtime has no effect.`);
}
return null;
}
// implementation
function defineEmit() {
if ((process.env.NODE_ENV !== 'production')) {
warn(`defineEmit() is a compiler-hint helper that is only usable inside ` +
`<script setup> of a single file component. Its arguments should be ` +
`compiled away and passing it at runtime has no effect.`);
}
return null;
}
// Core API ------------------------------------------------------------------
const version = "3.0.2";
const version = "3.0.3";
// import deepCopy from './deepCopy'
/**
......@@ -3361,6 +3494,8 @@ function patch(instance) {
ctx.__next_tick_pending = false;
flushCallbacks(instance);
});
// props update may have triggered pre-flush watchers.
flushPreFlushCbs(undefined, instance.update);
}
else {
flushCallbacks(instance);
......@@ -3634,4 +3769,4 @@ function createApp(rootComponent, rootProps = null) {
return createVueApp(rootComponent, rootProps).use(plugin);
}
export { callWithAsyncErrorHandling, callWithErrorHandling, computed$1 as computed, createApp, createHook$1 as createHook, createVueApp, customRef, inject, injectHook, isInSSRComponentSetup, isProxy, isReactive, isReadonly, isRef, logError, markRaw, nextTick, onActivated, onAddToFavorites, onBackPress, onBeforeMount, onBeforeUnmount, onBeforeUpdate, onDeactivated, onError, onErrorCaptured, onHide, onLaunch, onLoad, onMounted, onNavigationBarButtonTap, onNavigationBarSearchInputChanged, onNavigationBarSearchInputClicked, onNavigationBarSearchInputConfirmed, onNavigationBarSearchInputFocusChanged, onPageNotFound, onPageScroll, onPullDownRefresh, onReachBottom, onReady, onRenderTracked, onRenderTriggered, onResize, onShareAppMessage, onShareTimeline, onShow, onTabItemTap, onThemeChange, onUnhandledRejection, onUnload, onUnmounted, onUpdated, provide, reactive, readonly, ref, shallowReactive, shallowReadonly, shallowRef, toRaw, toRef, toRefs, triggerRef, unref, version, warn, watch, watchEffect };
export { callWithAsyncErrorHandling, callWithErrorHandling, computed$1 as computed, createApp, createHook$1 as createHook, createVueApp, customRef, defineComponent, defineEmit, defineProps, inject, injectHook, isInSSRComponentSetup, isProxy, isReactive, isReadonly, isRef, logError, markRaw, nextTick, onActivated, onAddToFavorites, onBackPress, onBeforeMount, onBeforeUnmount, onBeforeUpdate, onDeactivated, onError, onErrorCaptured, onHide, onLaunch, onLoad, onMounted, onNavigationBarButtonTap, onNavigationBarSearchInputChanged, onNavigationBarSearchInputClicked, onNavigationBarSearchInputConfirmed, onNavigationBarSearchInputFocusChanged, onPageNotFound, onPageScroll, onPullDownRefresh, onReachBottom, onReady, onRenderTracked, onRenderTriggered, onResize, onShareAppMessage, onShareTimeline, onShow, onTabItemTap, onThemeChange, onUnhandledRejection, onUnload, onUnmounted, onUpdated, provide, reactive, readonly, ref, resolveDirective, shallowReactive, shallowReadonly, shallowRef, toRaw, toRef, toRefs, triggerRef, unref, version, warn, watch, watchEffect, withDirectives };
......@@ -35,6 +35,17 @@ describe('mp:compiler-mp-weixin', () => {
expect(res.generic[0]).toBe('test-foo-default')
}
)
assertCodegen(
'<uni-clientdb v-slot:default="{data}"><uni-table><uni-tr><uni-th align="center">日期</uni-th></uni-tr></uni-table></uni-clientdb>',
'<uni-clientdb generic:scoped-slots-default="test-uni-clientdb-default" data-vue-generic="scoped" vue-id="551070e6-1" bind:__l="__l" vue-slots="{{[\'default\']}}"></uni-clientdb>',
function (res) {
expect(res.generic[0]).toBe('test-uni-clientdb-default')
const wxmlKey = Object.keys(res.files)[0]
expect(res.files[wxmlKey]).toBe(
'<uni-table vue-id="551070e6-2" bind:__l="__l" vue-slots="{{[\'default\']}}"><uni-tr vue-id="{{(\'551070e6-3\')+\',\'+(\'551070e6-2\')}}" bind:__l="__l" vue-slots="{{[\'default\']}}"><uni-th vue-id="{{(\'551070e6-4\')+\',\'+(\'551070e6-3\')}}" align="center" bind:__l="__l" vue-slots="{{[\'default\']}}">日期</uni-th></uni-tr></uni-table>'
)
}
)
})
it('generate named scoped slot', () => {
......@@ -130,8 +141,11 @@ describe('mp:compiler-mp-weixin', () => {
'<template v-for="(item, key) in { list1, list2 }"></template>',
'<block wx:for="{{({list1,list2})}}" wx:for-item="item" wx:for-index="key"></block>'
)
assertCodegen('<test :obj="{x:0}"></test>', '<test vue-id="551070e6-1" obj="{{({x:0})}}" bind:__l="__l"></test>')
assertCodegen('<test :obj="{\'x\':0}"></test>', '<test vue-id="551070e6-1" obj="{{$root.a0}}" bind:__l="__l"></test>', 'with(this){var a0={"x":0};$mp.data=Object.assign({},{$root:{a0:a0}})}')
assertCodegen('<test :obj="{x:0}"></test>',
'<test vue-id="551070e6-1" obj="{{({x:0})}}" bind:__l="__l"></test>')
assertCodegen('<test :obj="{\'x\':0}"></test>',
'<test vue-id="551070e6-1" obj="{{$root.a0}}" bind:__l="__l"></test>',
'with(this){var a0={"x":0};$mp.data=Object.assign({},{$root:{a0:a0}})}')
assertCodegen(
'<test :obj="{x:{x:0}}"></test>', '<test vue-id="551070e6-1" obj="{{$root.a0}}" bind:__l="__l"></test>',
'with(this){var a0={x:{x:0}};$mp.data=Object.assign({},{$root:{a0:a0}})}'
......@@ -144,4 +158,4 @@ describe('mp:compiler-mp-weixin', () => {
'<test data-custom-hidden="{{!(shown)}}" vue-id="551070e6-1" bind:__l="__l" vue-slots="{{[\'default\']}}">hello world</test>'
)
})
})
})
......@@ -22,7 +22,7 @@ const res = compiler.compile(
<custom data-a="1" :data-b="b"></custom>
`, {
miniprogram: true,
resourcePath: '/User/fxy/Documents/test.wxml',
resourcePath: 'test.wxml',
isReservedTag: function (tag) {
return true
},
......
......@@ -369,7 +369,11 @@ function traverseResolveScopedSlots (callExprNode, state) {
resourcePath,
paramExprNode,
returnExprNodes,
traverseExpr,
traverseExpr: function (exprNode, state) {
const ast = traverseExpr(exprNode, state)
initParent(ast)
return ast
},
normalizeChildren
},
state
......@@ -416,7 +420,8 @@ function traverseRenderList (callExprNode, state) {
const children = traverseExpr(forReturnStatementArgument, state)
// 支付宝小程序在 block 标签上使用 key 时顺序不能保障
if (state.options.platform.name === 'mp-alipay' && t.isCallExpression(forReturnStatementArgument) && children && children.type) {
if (state.options.platform.name === 'mp-alipay' && t.isCallExpression(forReturnStatementArgument) && children &&
children.type) {
children.attr = children.attr || {}
Object.assign(children.attr, attr)
return children
......@@ -483,4 +488,4 @@ function traverseCreateTextVNode (callExprNode, state) {
function traverseCreateEmptyVNode (callExprNode, state) {
return ''
}
}
const path = require('path')
let partialIdentifier = false
module.exports = {
getPartialIdentifier () {
......@@ -21,10 +22,11 @@ module.exports = {
return {
ignored: [
/node_modules/,
/unpackage/,
/uniCloud/i,
/cloudfunctions-aliyun/,
/cloudfunctions-tcb/
path.resolve(process.env.UNI_INPUT_DIR, 'unpackage'),
path.resolve(process.env.UNI_INPUT_DIR, 'uniCloud-aliyun'),
path.resolve(process.env.UNI_INPUT_DIR, 'uniCloud-tcb'),
path.resolve(process.env.UNI_INPUT_DIR, 'cloudfunctions-aliyun'),
path.resolve(process.env.UNI_INPUT_DIR, 'cloudfunctions-tcb')
]
}
}
......
......@@ -27,6 +27,9 @@ module.exports = function modifyVueLoader (webpackConfig, loaderOptions, compile
.tap(options => Object.assign(options, vueLoader.options(loaderOptions, compilerOptions), cacheConfig))
.end()
// 强制使用vue2,vue3时会使用vue-loader-v16
webpackConfig.plugin('vue-loader').use(require(vueLoader.loader).VueLoaderPlugin)
// h5 框架需要使用 scoped 样式,其他平台编译时识别是否 nvue 文件且注入 flex 相关样式
if (process.env.UNI_PLATFORM === 'h5') {
webpackConfig.module
......
......@@ -46,6 +46,24 @@ function assertCodegenOptions (content, expectedOptions, isScoped = true) {
describe('mp:loader', () => {
it('parse scoped component', () => {
assertCodegen(
`import { uniBadge,uniCard} from '@dcloudio/uni-ui';
export default defineComponent({
components: {
'uni-badge':uniBadge,
'uni-card':uniCard
}
})`,
[{
name: 'uni-badge',
value: 'uniBadge',
source: '@dcloudio/uni-ui/lib/uni-badge/uni-badge'
}, {
name: 'uni-card',
value: 'uniCard',
source: '@dcloudio/uni-ui/lib/uni-card/uni-card'
}])
assertCodegen(
`
import mediaList from '@/components/tab-nvue/mediaList.vue';
......@@ -158,29 +176,27 @@ global['__wxVueOptions'] = {
'van-button': VanButton,
'van-search': VanSearch,
},exports.default.components || {})`,
[
{
name: 'van-button',
value: 'VanButton',
source: '../button/index.vue'
},
{
name: 'van-search',
value: 'VanSearch',
source: '../search/index.vue'
},
{
name: 'myButton',
value: 'myButton',
source: '@/components/my-button/my-button.vue'
}
[{
name: 'van-button',
value: 'VanButton',
source: '../button/index.vue'
},
{
name: 'van-search',
value: 'VanSearch',
source: '../search/index.vue'
},
{
name: 'myButton',
value: 'myButton',
source: '@/components/my-button/my-button.vue'
}
])
assertCodegenOptions(
`export default {
name: 'test'
}`,
{
}`, {
name: '"test"',
inheritAttrs: null,
props: null
......@@ -191,8 +207,7 @@ global['__wxVueOptions'] = {
`const options = {
name: 'test'
}
export default options`,
{
export default options`, {
name: '"test"',
inheritAttrs: null,
props: null
......@@ -204,8 +219,7 @@ global['__wxVueOptions'] = {
options = {
name: 'test'
}
export default options`,
{
export default options`, {
name: '"test"',
inheritAttrs: null,
props: null
......@@ -216,8 +230,7 @@ global['__wxVueOptions'] = {
`const options = Vue.extend({
name: 'test'
})
export default options`,
{
export default options`, {
name: '"test"',
inheritAttrs: null,
props: null
......@@ -229,8 +242,7 @@ global['__wxVueOptions'] = {
options = Vue.extend({
name: 'test'
})
export default options`,
{
export default options`, {
name: '"test"',
inheritAttrs: null,
props: null
......@@ -241,8 +253,7 @@ global['__wxVueOptions'] = {
`const options = {
name: 'test'
}
export default Vue.extend(options)`,
{
export default Vue.extend(options)`, {
name: '"test"',
inheritAttrs: null,
props: null
......@@ -252,8 +263,7 @@ global['__wxVueOptions'] = {
assertCodegenOptions(
`export default {
props: ['id', 'test']
}`,
{
}`, {
name: null,
inheritAttrs: null,
props: '["id","test"]'
......@@ -270,8 +280,7 @@ global['__wxVueOptions'] = {
type: String
}
}
}`,
{
}`, {
name: null,
inheritAttrs: null,
props: '["id","test"]'
......@@ -302,4 +311,4 @@ global['__wxVueOptions'] = {
source: '@/components/tab-nvue/mediaList.vue'
}], false)
})
})
})
......@@ -16,10 +16,15 @@ function handleObjectExpression (declaration, path, state) {
if (optionProperty) {
if (name === 'props') {
if (t.isArrayExpression(optionProperty.value)) {
state.options[name] = JSON.stringify(optionProperty.value.elements.filter(element => t.isStringLiteral(element)).map(({ value }) => value))
state.options[name] = JSON.stringify(optionProperty.value.elements.filter(element => t.isStringLiteral(
element)).map(({
value
}) => value))
} else if (t.isObjectExpression(optionProperty.value)) {
const props = []
optionProperty.value.properties.forEach(({ key }) => {
optionProperty.value.properties.forEach(({
key
}) => {
if (t.isIdentifier(key)) {
props.push(key.name)
} else if (t.isStringLiteral(key)) {
......@@ -60,7 +65,9 @@ function handleComponentsObjectExpression (componentsObjExpr, path, state, prepe
state.components = prepend ? components.concat(state.components) : components
}
function handleIdentifier ({ name }, path, state) {
function handleIdentifier ({
name
}, path, state) {
// 仅做有限查找
for (let i = path.container.length; i > 0; i--) {
const node = path.container[i - 1]
......@@ -101,6 +108,19 @@ module.exports = function (ast, state = {
options: {}
}) {
babelTraverse(ast, {
CallExpression (path) {
const callee = path.node.callee
const args = path.node.arguments
const objExpr = args[0]
if (
t.isIdentifier(callee) &&
callee.name === 'defineComponent' &&
args.length === 1 &&
t.isObjectExpression(objExpr)
) {
handleObjectExpression(objExpr, path, state)
}
},
AssignmentExpression (path) {
const leftExpression = path.node.left
const rightExpression = path.node.right
......@@ -162,4 +182,4 @@ module.exports = function (ast, state = {
ast,
state
}
}
}
......@@ -36,6 +36,7 @@ module.exports = function (content, map) {
this.callback(null,
`<style>
view,
label,
swiper-item,
scroll-view {
display:flex;
......@@ -62,6 +63,9 @@ module.exports = function (content, map) {
swiper-item {
position: absolute;
}
button {
margin: 0;
}
</style>
${content}`,
map)
......
......@@ -32,6 +32,6 @@ export const chooseFile = {
},
extension: {
type: Array,
default: ['*']
default: ['']
}
}
......@@ -122,6 +122,7 @@ uni-page {
}
[nvue] uni-view,
[nvue] uni-label,
[nvue] uni-swiper-item,
[nvue] uni-scroll-view {
display: flex;
......@@ -132,22 +133,30 @@ uni-page {
align-content: flex-start;
}
[nvue] uni-button{
margin: 0;
}
[nvue-dir-row] uni-view,
[nvue-dir-row] uni-label,
[nvue-dir-row] uni-swiper-item {
flex-direction: row;
}
[nvue-dir-column] uni-view,
[nvue-dir-column] uni-label,
[nvue-dir-column] uni-swiper-item {
flex-direction: column;
}
[nvue-dir-row-reverse] uni-view,
[nvue-dir-row-reverse] uni-label,
[nvue-dir-row-reverse] uni-swiper-item {
flex-direction: row-reverse;
}
[nvue-dir-column-reverse] uni-view,
[nvue-dir-column-reverse] uni-label,
[nvue-dir-column-reverse] uni-swiper-item {
flex-direction: column-reverse;
}
......
......@@ -67,6 +67,9 @@ export function initEntryPage () {
}
if (!entryPagePath || entryPagePath === __uniConfig.entryPagePath) {
if (entryPageQuery) {
__uniConfig.entryPageQuery = entryPageQuery
}
return
}
......
......@@ -108,22 +108,30 @@ uni-button[loading]:before {
align-content: flex-start;
}
[nvue] uni-button{
margin: 0;
}
[nvue-dir-row] uni-view,
[nvue-dir-row] uni-label,
[nvue-dir-row] uni-swiper-item {
flex-direction: row;
}
[nvue-dir-column] uni-view,
[nvue-dir-column] uni-label,
[nvue-dir-column] uni-swiper-item {
flex-direction: column;
}
[nvue-dir-row-reverse] uni-view,
[nvue-dir-row-reverse] uni-label,
[nvue-dir-row-reverse] uni-swiper-item {
flex-direction: row-reverse;
}
[nvue-dir-column-reverse] uni-view,
[nvue-dir-column-reverse] uni-label,
[nvue-dir-column-reverse] uni-swiper-item {
flex-direction: column-reverse;
}
......
<template>
<uni-layout
v-if="responsive"
:class="{'uni-app--showlayout':showLayout,'uni-app--showtopwindow':showTopWindow,'uni-app--showleftwindow':showLeftWindow,'uni-app--showrightwindow':showRightWindow}"
<uni-layout
v-if="responsive"
:class="{'uni-app--showlayout':showLayout,'uni-app--showtopwindow':showTopWindow,'uni-app--showleftwindow':showLeftWindow,'uni-app--showrightwindow':showRightWindow}"
>
<uni-top-window
v-if="topWindow"
v-show="showTopWindow || apiShowTopWindow"
<uni-top-window
v-if="topWindow"
v-show="showTopWindow || apiShowTopWindow"
>
<div
ref="topWindow"
class="uni-top-window"
:style="topWindowStyle"
<div
ref="topWindow"
class="uni-top-window"
:style="topWindowStyle"
>
<v-uni-top-window
ref="top"
:navigation-bar-title-text="navigationBarTitleText"
<v-uni-top-window
ref="top"
:navigation-bar-title-text="navigationBarTitleText"
v-bind="bindWindow"
@hook:mounted="onTopWindowInit"
@hook:mounted="onTopWindowInit"
/>
</div>
<div
class="uni-top-window--placeholder"
:style="{height:topWindowHeight}"
<div
class="uni-top-window--placeholder"
:style="{height:topWindowHeight}"
/>
</uni-top-window>
<uni-content>
......@@ -30,52 +30,52 @@
<router-view :key="routerKey" />
</keep-alive>
</uni-main>
<uni-left-window
v-if="leftWindow"
v-show="showLeftWindow || apiShowLeftWindow"
ref="leftWindow"
<uni-left-window
v-if="leftWindow"
v-show="showLeftWindow || apiShowLeftWindow"
ref="leftWindow"
:data-show="apiShowLeftWindow"
:style="leftWindowStyle"
:style="leftWindowStyle"
>
<div
v-if="apiShowLeftWindow"
class="uni-mask"
@click="apiShowLeftWindow = false"
<div
v-if="apiShowLeftWindow"
class="uni-mask"
@click="apiShowLeftWindow = false"
/>
<div class="uni-left-window">
<v-uni-left-window
ref="left"
v-bind="bindWindow"
@hook:mounted="onLeftWindowInit"
<v-uni-left-window
ref="left"
v-bind="bindWindow"
@hook:mounted="onLeftWindowInit"
/>
</div>
</uni-left-window>
<uni-right-window
v-if="rightWindow"
v-show="showRightWindow || apiShowRightWindow"
ref="rightWindow"
<uni-right-window
v-if="rightWindow"
v-show="showRightWindow || apiShowRightWindow"
ref="rightWindow"
:data-show="apiShowRightWindow"
:style="rightWindowStyle"
:style="rightWindowStyle"
>
<div
v-if="apiShowRightWindow"
class="uni-mask"
@click="apiShowRightWindow = false"
<div
v-if="apiShowRightWindow"
class="uni-mask"
@click="apiShowRightWindow = false"
/>
<div class="uni-right-window">
<v-uni-right-window
ref="right"
v-bind="bindWindow"
@hook:mounted="onRightWindowInit"
<v-uni-right-window
ref="right"
v-bind="bindWindow"
@hook:mounted="onRightWindowInit"
/>
</div>
</uni-right-window>
</uni-content>
<!--TODO footer-->
</uni-layout>
<keep-alive
v-else
:include="keepAliveInclude"
<keep-alive
v-else
:include="keepAliveInclude"
>
<router-view :key="routerKey" />
</keep-alive>
......@@ -274,6 +274,15 @@ export default {
}
}
},
setWindowStyle (type, style) {
if (!this[type + 'Window']) {
return type + 'Window not found'
}
if (style) {
this[type + 'WindowStyle'] = style
this.$nextTick(this['on' + capitalize(type) + 'WindowInit'])
}
},
initMaxWidth () {
window.addEventListener('resize', () => {
this.checkMaxWidth()
......@@ -438,4 +447,4 @@ export default {
z-index: 998;
overflow: hidden;
}
</style>
</style>
......@@ -25,7 +25,7 @@ export function showTopWindow () {
export function hideTopWindow () {
return showWindow('top', false)
}
}
export function showLeftWindow () {
return showWindow('left', true)
......@@ -40,4 +40,31 @@ export function showRightWindow () {
export function hideRightWindow () {
return showWindow('right', false)
}
}
function setWindowStyle (type, style) {
const api = 'set' + capitalize(type) + 'WindowStyle'
const app = getApp()
if (!app) {
return {
errMsg: `${api}:fail app not ready`
}
}
const msg = app.$children[0].$refs.layout.setWindowStyle(type, style)
if (msg) {
return {
errMsg: `${api}:fail ${msg}`
}
}
return {}
}
export function setTopWindowStyle (style) {
return setWindowStyle('top', style)
}
export function setLeftWindowStyle (style) {
return setWindowStyle('left', style)
}
export function setRightWindowStyle (style) {
return setWindowStyle('right', style)
}
......@@ -132,22 +132,29 @@ uni-page {
align-content: flex-start;
}
[nvue] uni-button{
margin: 0;
}
[nvue-dir-row] uni-view,
[nvue-dir-row] uni-swiper-item {
flex-direction: row;
}
[nvue-dir-column] uni-view,
[nvue-dir-column] uni-label,
[nvue-dir-column] uni-swiper-item {
flex-direction: column;
}
[nvue-dir-row-reverse] uni-view,
[nvue-dir-row-reverse] uni-label,
[nvue-dir-row-reverse] uni-swiper-item {
flex-direction: row-reverse;
}
[nvue-dir-column-reverse] uni-view,
[nvue-dir-column-reverse] uni-label,
[nvue-dir-column-reverse] uni-swiper-item {
flex-direction: column-reverse;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册