提交 b2970df4 编写于 作者: fxy060608's avatar fxy060608

Merge branch 'dev' of https://github.com/dcloudio/uni-app into dev-quickapp

......@@ -92,7 +92,7 @@ module.exports = {
return uniPluginOptions.vue || '@dcloudio/vue-cli-plugin-uni/packages/mp-vue'
},
getPlatformCssVars () {
return uniPluginOptions.cssVars
return uniPluginOptions.cssVars || {}
},
getPlatformCssnano () {
return {
......@@ -134,4 +134,4 @@ module.exports = {
]
}
}
}
}
......@@ -236,6 +236,14 @@ const v3 = {
}
if (isAppView) {
if (process.env.UNI_USING_V3_SCOPED) {
webpackConfig.module
.rule('vue')
.use('uniapp-app-style-scoped')
.loader(path.resolve(__dirname,
'../../packages/webpack-uni-app-loader/view/style'))
}
if (process.env.NODE_ENV === 'production') {
require('../h5/cssnano-options')(webpackConfig)
}
......
......@@ -26,6 +26,8 @@ global.uniPlugin.validate.forEach(validate => {
process.UNI_MANIFEST = manifestJsonObj
process.env.UNI_USING_V3_SCOPED = true
process.UNI_CLOUD = false
process.UNI_CLOUD_TCB = false
process.UNI_CLOUD_ALIYUN = false
......@@ -408,6 +410,10 @@ global.uniPlugin.configureEnv.forEach(configureEnv => {
configureEnv()
})
if (process.env.UNI_PLATFORM.startsWith('mp-')) {
console.log('小程序各家浏览器内核及自定义组件实现机制存在差异,可能存在样式布局兼容问题,参考:https://uniapp.dcloud.io/matter?id=mp')
}
runByHBuilderX && console.log('正在编译中...')
module.exports = {
......
......@@ -7,11 +7,12 @@ const splitRE = /\r?\n/g;
const emptyRE = /^(?:\/\/)?\s*$/;
function parse(options) {
const { source, filename = '', compiler, compilerParseOptions = { pad: 'line' }, sourceRoot = '', needMap = true } = options;
const cacheKey = hash(filename + source);
// fixed by xxxxxx (添加isAppNVue标记,防止nvue与vue引用相同组件时,走了相同的cache)
const cacheKey = hash(String(options.isAppNVue) + filename + source);
let output = cache.get(cacheKey);
if (output)
return output;
// fixed by xxxxxx
// fixed by xxxxxx
output = require('./parseCustomBlocks')(compiler.parseComponent(source, compilerParseOptions), options);
if (needMap) {
if (output.script && !output.script.src) {
......
const path = require('path')
const loaderUtils = require('loader-utils')
const isWin = /^win/.test(process.platform)
const normalizePath = path => (isWin ? path.replace(/\\/g, '/') : path)
const AppPath = normalizePath(path.resolve(process.env.UNI_INPUT_DIR, 'App.vue'))
module.exports = function(content) {
this.cacheable && this.cacheable()
if (this.resourceQuery) {
const params = loaderUtils.parseQuery(this.resourceQuery)
if (params.mpType === 'page') {
return content
}
}
if (normalizePath(this.resourcePath) === AppPath) {
return content
}
if (content.indexOf('platform="mp-weixin"') !== -1) {
return content
}
return content.replace(/(<style\b[^><]*)>/ig, '$1 scoped>')
}
......@@ -3,7 +3,7 @@ function generatePageCode (pages, pageOptions) {
if (pageOptions[pagePath].nvue) {
return ''
}
return `__definePage('${pagePath}',function(){return Vue.extend(require('${pagePath}.vue').default)})`
return `__definePage('${pagePath}',function(){return Vue.extend(require('${pagePath}.vue?mpType=page').default)})`
}).join('\n')
}
......
<template>
<uni-canvas
:canvas-id="canvasId"
:disable-scroll="disableScroll"
v-on="_listeners"
<uni-canvas
:canvas-id="canvasId"
:disable-scroll="disableScroll"
v-on="_listeners"
>
<canvas
ref="canvas"
width="300"
height="150"
<canvas
ref="canvas"
width="300"
height="150"
/>
<div style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; overflow: hidden;">
<slot />
</div>
<v-uni-resize-sensor
ref="sensor"
@resize="_resize"
<v-uni-resize-sensor
ref="sensor"
@resize="_resize"
/>
</uni-canvas>
</template>
......@@ -279,37 +279,37 @@ export default {
}
},
preloadImage: function (actions) {
var sefl = this
var self = this
actions.forEach(function (action) {
var method = action.method
var data = action.data
var src = ''
if (method === 'drawImage') {
src = data[0]
src = sefl.$getRealPath(src)
src = self.$getRealPath(src)
data[0] = src
} else if (method === 'setFillStyle' && data[0] === 'pattern') {
src = data[1]
src = sefl.$getRealPath(src)
src = self.$getRealPath(src)
data[1] = src
}
if (src && !sefl._images[src]) {
if (src && !self._images[src]) {
loadImage()
}
/**
* 加载图像
*/
function loadImage () {
sefl._images[src] = new Image()
sefl._images[src].onload = function () {
sefl._images[src].ready = true
self._images[src] = new Image()
self._images[src].onload = function () {
self._images[src].ready = true
}
/**
* 从Blob加载
* @param {Blob} blob
*/
function loadBlob (blob) {
sefl._images[src].src = (window.URL || window.webkitURL).createObjectURL(blob)
self._images[src].src = (window.URL || window.webkitURL).createObjectURL(blob)
}
/**
* 从本地文件加载
......@@ -318,7 +318,7 @@ export default {
function loadFile (path) {
var bitmap = new plus.nativeObj.Bitmap('bitmap' + Date.now())
bitmap.load(path, function () {
sefl._images[src].src = bitmap.toBase64Data()
self._images[src].src = bitmap.toBase64Data()
bitmap.clear()
}, function () {
bitmap.clear()
......@@ -337,7 +337,7 @@ export default {
if (status === 200) {
loadFile(d.filename)
} else {
sefl._images[src].src = src
self._images[src].src = src
}
}).start()
}
......@@ -350,20 +350,20 @@ export default {
}
}
xhr.onerror = window.plus ? plusDownload : function () {
sefl._images[src].src = src
self._images[src].src = src
}
xhr.send()
}
if (window.plus && (!window.webkit || !window.webkit.messageHandlers)) {
sefl._images[src].src = src
self._images[src].src = src
} else {
// 解决 PLUS-APP(wkwebview)以及 H5 图像跨域问题(H5图像响应头需包含access-control-allow-origin)
if (window.plus && src.indexOf('http://') !== 0 && src.indexOf('https://') !==
0) {
loadFile(src)
} else if (/^data:.*,.*/.test(src)) {
sefl._images[src].src = src
self._images[src].src = src
} else {
loadUrl(src)
}
......@@ -449,7 +449,7 @@ export default {
}, this.$page.id)
return
}
if (!callbackId) {
if (!callbackId) {
// fix [...]展开TypedArray在低版本手机报错的问题,使用Array.prototype.slice
return {
data: Array.prototype.slice.call(imgData.data),
......
export default function (Quill) {
const Image = Quill.import('formats/image')
const ATTRIBUTES = [
'alt',
'height',
'width',
'data-custom',
'class',
'data-local'
]
Image.sanitize = url => url
Image.formats = function formats (domNode) {
return ATTRIBUTES.reduce(function (formats, attribute) {
if (domNode.hasAttribute(attribute)) {
formats[attribute] = domNode.getAttribute(attribute)
}
return formats
}, {})
}
const format = Image.prototype.format
Image.prototype.format = function (name, value) {
if (ATTRIBUTES.indexOf(name) > -1) {
if (value) {
this.domNode.setAttribute(name, value)
} else {
this.domNode.removeAttribute(name)
}
} else {
format.call(this, name, value)
}
}
}
......@@ -142,9 +142,15 @@ export default {
case 'insertImage':
{
range = quill.getSelection(true)
const { src = '', alt = '', data = {} } = options
quill.insertEmbed(range.index, 'image', this.$getRealPath(src), Quill.sources.USER)
const { src = '', alt = '', width = '', height = '', extClass = '', data = {} } = options
const path = this.$getRealPath(src)
quill.insertEmbed(range.index, 'image', path, Quill.sources.USER)
const local = /^(file|blob):/.test(path) ? path : false
quill.formatText(range.index, 1, 'data-local', local)
quill.formatText(range.index, 1, 'alt', alt)
quill.formatText(range.index, 1, 'width', width)
quill.formatText(range.index, 1, 'height', height)
quill.formatText(range.index, 1, 'class', extClass)
quill.formatText(range.index, 1, 'data-custom', Object.keys(data).map(key => `${key}=${data[key]}`).join('&'))
quill.setSelection(range.index + 1, Quill.sources.SILENT)
}
......
......@@ -2,13 +2,13 @@
<uni-image v-on="$listeners">
<div
ref="content"
:style="modeStyle"
:style="modeStyle"
/>
<img :src="realImagePath">
<v-uni-resize-sensor
v-if="mode === 'widthFix'"
ref="sensor"
@resize="_resize"
@resize="_resize"
/>
</uni-image>
</template>
......@@ -34,8 +34,7 @@ export default {
return {
originalWidth: 0,
originalHeight: 0,
availHeight: '',
sizeFixed: false
availHeight: ''
}
},
computed: {
......@@ -43,7 +42,7 @@ export default {
return this.originalWidth && this.originalHeight ? this.originalWidth / this.originalHeight : 0
},
realImagePath () {
return this.src && this.$getRealPath(this.src)
return this.$getRealPath(this.src)
},
modeStyle () {
let size = 'auto'
......@@ -106,7 +105,6 @@ export default {
mode (newValue, oldValue) {
if (oldValue === 'widthFix') {
this.$el.style.height = this.availHeight
this.sizeFixed = false
}
if (newValue === 'widthFix' && this.ratio) {
this._fixSize()
......@@ -123,7 +121,7 @@ export default {
},
methods: {
_resize () {
if (this.mode === 'widthFix' && !this.sizeFixed) {
if (this.mode === 'widthFix') {
this._fixSize()
}
},
......@@ -136,7 +134,6 @@ export default {
height = Math.round(height / 2) * 2
}
this.$el.style.height = height + 'px'
this.sizeFixed = true
}
},
_setContentImage () {
......
<template>
<uni-input
@change.stop
<uni-input
@change.stop
v-on="$listeners"
>
<div
ref="wrapper"
<div
ref="wrapper"
class="uni-input-wrapper"
>
<div
......@@ -97,7 +97,7 @@ export default {
},
data () {
return {
inputValue: this.value + '',
inputValue: this._getValueString(this.value),
composing: false,
wrapperHeight: 0,
cachedValue: ''
......@@ -133,7 +133,7 @@ export default {
value && this._focusInput()
},
value (value) {
this.inputValue = value + ''
this.inputValue = this._getValueString(value)
},
inputValue (value) {
this.$emit('update:value', value)
......@@ -255,6 +255,9 @@ export default {
value: this.inputValue,
key: this.name
} : {}
},
_getValueString (value) {
return value === null ? '' : String(value)
}
}
}
......@@ -295,7 +298,7 @@ uni-input[hidden] {
}
.uni-input-placeholder,
.uni-input-input{
.uni-input-input {
width: 100%;
}
......
<script>
import {
disableScrollBounce
disableScrollBounce,
deepClone
} from 'uni-shared'
function calc (e) {
......@@ -56,9 +57,9 @@ export default {
}
return get(target)
},
_touchstart (t) {
disableScrollBounce({
disable: true
_touchstart (t) {
disableScrollBounce({
disable: true
})
var i = t.touches
if (i) {
......@@ -94,9 +95,9 @@ export default {
}
}
},
_touchend (e) {
disableScrollBounce({
disable: false
_touchend (e) {
disableScrollBounce({
disable: false
})
var t = e.touches
if (!(t && t.length)) {
......@@ -142,8 +143,9 @@ export default {
},
render (createElement) {
var items = []
if (this.$slots.default) {
this.$slots.default.forEach(vnode => {
const $slots = this.$slots.default && deepClone(this.$slots.default, createElement)
if ($slots) {
$slots.forEach(vnode => {
if (vnode.componentOptions && vnode.componentOptions.tag === 'v-uni-movable-view') {
items.push(vnode)
}
......@@ -163,7 +165,7 @@ export default {
on: {
resize: this._resize
}
}), this.$slots.default])
}), $slots])
}
}
</script>
......@@ -178,4 +180,4 @@ export default {
uni-movable-area[hidden] {
display: none;
}
</style>
</style>
<script>
import { deepClone } from 'uni-shared'
export default {
name: 'PickerView',
props: {
......@@ -93,7 +95,7 @@ export default {
render (createElement) {
var items = []
if (this.$slots.default) {
this.$slots.default.forEach(vnode => {
deepClone(this.$slots.default, createElement).forEach(vnode => {
if (vnode.componentOptions && vnode.componentOptions.tag === 'v-uni-picker-view-column') {
items.push(vnode)
}
......
<script>
import touchtrack from 'uni-mixins/touchtrack'
function deepClone (vnodes, createElement) {
function cloneVNode (vnode) {
var clonedChildren = vnode.children && vnode.children.map(cloneVNode)
var cloned = createElement(vnode.tag, vnode.data, clonedChildren)
cloned.text = vnode.text
cloned.isComment = vnode.isComment
cloned.componentOptions = vnode.componentOptions
cloned.elm = vnode.elm
cloned.context = vnode.context
cloned.ns = vnode.ns
cloned.isStatic = vnode.isStatic
cloned.key = vnode.key
return cloned
}
return vnodes.map(cloneVNode)
}
import { deepClone } from 'uni-shared'
export default {
name: 'Swiper',
......
......@@ -119,7 +119,7 @@ export default {
},
data () {
return {
valueSync: String(this.value),
valueSync: this._getValueString(this.value),
valueComposition: '',
composition: false,
focusSync: this.focus,
......@@ -152,7 +152,7 @@ export default {
},
watch: {
value (val) {
this.valueSync = String(val)
this.valueSync = this._getValueString(val)
},
valueSync (val) {
if (val !== this._oldValue) {
......@@ -296,6 +296,9 @@ export default {
},
_resetFormData () {
this.valueSync = ''
},
_getValueString (value) {
return value === null ? '' : String(value)
}
}
}
......
......@@ -6,10 +6,10 @@ import {
export default {
methods: {
$getRealPath (src) {
return getRealPath(src)
return src ? getRealPath(src) : src
},
$trigger (name, $event, detail) {
this.$emit(name, processEvent.call(this, name, $event, detail, this.$el, this.$el))
}
}
}
}
......@@ -107,6 +107,10 @@ export default {
UniViewJSBridge.unsubscribe('hideKeyboard', this.hideKeyboardTemp)
document.removeEventListener('click', iosHideKeyboard, false)
this.resetSoftinputNavBar()
// 修复ios端显示与点击位置错位的Bug by:wyq
if (document.body.scrollIntoView) {
document.body.scrollIntoView()
}
}
}
}
......@@ -168,7 +168,7 @@ export function showActionSheet ({
}
if (plus.os.name === 'iOS') {
options.cancel = '取消'
options.cancel = ''
}
plus.nativeUI.actionSheet(Object.assign(options, { popover }), (e) => {
......
......@@ -320,11 +320,18 @@ export default {
nativeMap.__markers__[id + ''] = nativeMarker
})
},
_clearMarkers () {
const map = this.map
const data = map.__markers__
for (const key in data) {
map.removeOverlay(data[key])
}
map.__markers__ = {}
},
_addMarkers (markers, clear) {
if (this.map) {
if (clear) {
this.map.clearOverlays()
this.map.__markers__ = {}
this._clearMarkers()
}
markers.forEach(marker => {
this._addMarker(this.map, marker)
......
......@@ -127,7 +127,7 @@ function getData (id, name) {
try {
return this.$r[id][name]
} catch (e) {
console.error(this.$options.__file + `:[${this._$id}]$r[${id}][${name}] is undefined`)
// console.error(this.$options.__file + `:[${this._$id}]$r[${id}][${name}] is undefined`)
}
}
/**
......@@ -143,7 +143,7 @@ function getChangeData (id, name) {
this.$set(this.wxsProps, wxsPropName, value)
return value
} catch (e) {
console.error(this.$options.__file + `:[${this._$id}]$r[${id}][${name}] is undefined`)
// console.error(this.$options.__file + `:[${this._$id}]$r[${id}][${name}] is undefined`)
}
}
......
......@@ -55,7 +55,7 @@ export function chooseImage ({
for (let i = 0; i < fileCount; i++) {
const file = event.target.files[i]
let filePath
Object.defineProperty(file, 'filePath', {
Object.defineProperty(file, 'path', {
get () {
filePath = filePath || fileToUrl(file)
return filePath
......
......@@ -385,7 +385,9 @@ export default {
for (let index = 0; index < length; index++) {
const val0 = Number(val[index])
const val1 = Number(this.valueSync[index])
this.valueSync.splice(index, 1, isNaN(val0) ? (isNaN(val1) ? 0 : val1) : val0)
const val2 = isNaN(val0) ? (isNaN(val1) ? 0 : val1) : val0
const maxVal = this.range[index] ? this.range[index].length - 1 : 0
this.valueSync.splice(index, 1, val2 > maxVal ? 0 : val2)
}
}
break
......
......@@ -95,43 +95,61 @@ export function debounce (fn, delay) {
export function kebabCase (string) {
return string.replace(/[A-Z]/g, str => '-' + str.toLowerCase())
}
/**
* Check if two values are loosely equal - that is,
* if they are plain objects, do they have the same shape?
*/
export function looseEqual (a, b) {
if (a === b) return true
const isObjectA = isObject(a)
const isObjectB = isObject(b)
if (isObjectA && isObjectB) {
try {
const isArrayA = Array.isArray(a)
const isArrayB = Array.isArray(b)
if (isArrayA && isArrayB) {
return a.length === b.length && a.every((e, i) => {
return looseEqual(e, b[i])
})
} else if (a instanceof Date && b instanceof Date) {
return a.getTime() === b.getTime()
} else if (!isArrayA && !isArrayB) {
const keysA = Object.keys(a)
const keysB = Object.keys(b)
return keysA.length === keysB.length && keysA.every(key => {
return looseEqual(a[key], b[key])
})
} else {
/* istanbul ignore next */
return false
}
} catch (e) {
/* istanbul ignore next */
return false
}
} else if (!isObjectA && !isObjectB) {
return String(a) === String(b)
} else {
return false
}
}
}
/**
* Check if two values are loosely equal - that is,
* if they are plain objects, do they have the same shape?
*/
export function looseEqual (a, b) {
if (a === b) return true
const isObjectA = isObject(a)
const isObjectB = isObject(b)
if (isObjectA && isObjectB) {
try {
const isArrayA = Array.isArray(a)
const isArrayB = Array.isArray(b)
if (isArrayA && isArrayB) {
return a.length === b.length && a.every((e, i) => {
return looseEqual(e, b[i])
})
} else if (a instanceof Date && b instanceof Date) {
return a.getTime() === b.getTime()
} else if (!isArrayA && !isArrayB) {
const keysA = Object.keys(a)
const keysB = Object.keys(b)
return keysA.length === keysB.length && keysA.every(key => {
return looseEqual(a[key], b[key])
})
} else {
/* istanbul ignore next */
return false
}
} catch (e) {
/* istanbul ignore next */
return false
}
} else if (!isObjectA && !isObjectB) {
return String(a) === String(b)
} else {
return false
}
}
export function deepClone (vnodes, createElement) {
function cloneVNode (vnode) {
var clonedChildren = vnode.children && vnode.children.map(cloneVNode)
var cloned = createElement(vnode.tag, vnode.data, clonedChildren)
cloned.text = vnode.text
cloned.isComment = vnode.isComment
cloned.componentOptions = vnode.componentOptions
cloned.elm = vnode.elm
cloned.context = vnode.context
cloned.ns = vnode.ns
cloned.isStatic = vnode.isStatic
cloned.key = vnode.key
return cloned
}
return vnodes.map(cloneVNode)
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册