提交 cedbfeec 编写于 作者: Q qiang

Merge branch 'dev' into alpha

......@@ -240,7 +240,8 @@ const third = [
const ad = [
'createRewardedVideoAd',
'createFullScreenVideoAd'
'createFullScreenVideoAd',
'createInterstitialAd'
]
const apis = [
......
......@@ -223,6 +223,7 @@
"title": "广告",
"apiList": {
"uni.createRewardedVideoAd": true,
"uni.createFullScreenVideoAd": true
"uni.createFullScreenVideoAd": true,
"uni.'createInterstitialAd'": true
}
}]
......@@ -237,16 +237,28 @@ describe('mp:compiler-extra', () => {
assertCodegen(
'<component1 v-slot>text</component1>',
'<component1 vue-id="551070e6-1" bind:__l="__l" vue-slots="{{[\'default\']}}"><view>text</view></component1>'
'<component1 vue-id="551070e6-1" bind:__l="__l" vue-slots="{{[\'default\']}}"><block>text</block></component1>'
)
assertCodegen(
'<component1 v-slot:default>text<text>123213</text></component1>',
'<component1 vue-id="551070e6-1" bind:__l="__l" vue-slots="{{[\'default\']}}"><view>text<text>123213</text></view></component1>'
'<component1 vue-id="551070e6-1" bind:__l="__l" vue-slots="{{[\'default\']}}"><block>text<text>123213</text></block></component1>'
)
assertCodegen(
'<component1><template v-slot:left><text></text></template><template v-slot:right><text></text></template></component1>',
'<component1 vue-id="551070e6-1" bind:__l="__l" vue-slots="{{[\'left\',\'right\']}}"><view slot="left"><text></text></view><view slot="right"><text></text></view></component1>'
'<component1 vue-id="551070e6-1" bind:__l="__l" vue-slots="{{[\'left\',\'right\']}}"><text slot="left"></text><text slot="right"></text></component1>'
)
assertCodegen(
'<component1><view>view1</view><view>view2</view></component1>',
'<component1 vue-id="551070e6-1" bind:__l="__l" vue-slots="{{[\'default\']}}"><view>view1</view><view>view2</view></component1>'
)
assertCodegen(
'<component1><template v-slot><view>view1</view><view>view2</view><template></component1>',
'<component1 vue-id="551070e6-1" bind:__l="__l" vue-slots="{{[\'default\']}}"><block><view>view1</view><view>view2</view></block></component1>'
)
assertCodegen(
'<component1><template v-slot:test><view>view1</view><view>view2</view><template></component1>',
'<component1 vue-id="551070e6-1" bind:__l="__l" vue-slots="{{[\'test\']}}"><view slot="test"><view>view1</view><view>view2</view></view></component1>'
)
assertCodegen(
`<my-component>
......@@ -258,7 +270,7 @@ describe('mp:compiler-extra', () => {
<p>Here's some contact info</p>
</template>
</my-component>`,
'<my-component vue-id="551070e6-1" bind:__l="__l" vue-slots="{{[\'default\',\'header\',\'footer\']}}"><view slot="header"><view class="_h1">Here might be a page title</view></view><view slot="footer"><view class="_p">Here\'s some contact info</view></view><view class="_p">A paragraph for the main content.</view></my-component>'
'<my-component vue-id="551070e6-1" bind:__l="__l" vue-slots="{{[\'default\',\'header\',\'footer\']}}"><view class="_h1" slot="header">Here might be a page title</view><view class="_p" slot="footer">Here\'s some contact info</view><view class="_p">A paragraph for the main content.</view></my-component>'
)
})
......
......@@ -55,6 +55,12 @@ describe('mp:compiler-mp-alipay', () => {
}
)
})
it('generate slot fallback content', () => {
assertCodegen(
'<view><slot>slot</slot></view>',
'<view><block a:if="{{$slots.$default}}"><slot></slot></block><block a:else>slot</block></view>'
)
})
it('generate default slot', () => {
assertCodegen(
'<component1>text</component1>',
......
......@@ -82,6 +82,41 @@ describe('mp:compiler-mp-weixin', () => {
)
})
it('generate scoped slot with filter', () => {
assertCodegen(
'<my-component><template v-slot="{item}">{{getValue(item)}}<template></my-component>',
'<my-component vue-id="551070e6-1" bind:__l="__l" vue-slots="{{[\'default\']}}"><block><block wx:if="{{$root.m0}}">{{$root.m1}}</block></block></my-component>',
'with(this){var m0=$hasScopedSlotsParams("551070e6-1");var m1=m0?getValue($getScopedSlotsParams("551070e6-1","default","item")):null;$mp.data=Object.assign({},{$root:{m0:m0,m1:m1}})}',
{
betterScopedSlots: true
}
)
assertCodegen(
'<my-component><template v-slot="item">{{getValue(item.text)}}<template></my-component>',
'<my-component vue-id="551070e6-1" bind:__l="__l" vue-slots="{{[\'default\']}}"><block><block wx:if="{{$root.m0}}">{{$root.m1}}</block></block></my-component>',
'with(this){var m0=$hasScopedSlotsParams("551070e6-1");var m1=m0?getValue($getScopedSlotsParams("551070e6-1","default").text):null;$mp.data=Object.assign({},{$root:{m0:m0,m1:m1}})}',
{
betterScopedSlots: true
}
)
assertCodegen(
'<view><slot :item="item"><slot></view>',
'<view><block wx:if="{{$slots.default}}"><slot></slot></block><block wx:else><slot></slot></block></view>',
'with(this){$setScopedSlotsParams("default",{"item":item})}',
{
betterScopedSlots: true
}
)
assertCodegen(
'<view><slot v-bind="object"><slot></view>',
'<view><block wx:if="{{$slots.default}}"><slot></slot></block><block wx:else><slot></slot></block></view>',
'with(this){$setScopedSlotsParams("default",object)}',
{
betterScopedSlots: true
}
)
})
it('generate scoped slot', () => {
assertCodegen(
'<slot v-bind:user="user"></slot>',
......@@ -158,4 +193,4 @@ describe('mp:compiler-mp-weixin', () => {
'<test data-custom-hidden="{{!(shown)}}" vue-id="551070e6-1" bind:__l="__l" vue-slots="{{[\'default\']}}">hello world</test>'
)
})
})
})
......@@ -106,6 +106,9 @@ module.exports = {
METHOD_TO_STRING,
METHOD_RENDER_LIST,
METHOD_RESOLVE_FILTER,
METHOD_RENDER_SLOT,
METHOD_CREATE_EMPTY_VNODE,
METHOD_RESOLVE_SCOPED_SLOTS,
PREFIX_GLOBAL: 'g',
PREFIX_ATTR: 'a',
PREFIX_METHOD: 'm',
......
......@@ -90,6 +90,7 @@ module.exports = function traverse (ast, state) {
const blockStatementBody = []
const objectPropertyArray = []
const initExpressionStatementArray = []
const renderSlotStatementArray = []
// TODO 待重构,至少 filter,method 等实现方式要调整
babelTraverse(ast, visitor, undefined, {
scoped: [],
......@@ -100,7 +101,8 @@ module.exports = function traverse (ast, state) {
identifierArray: identifierArray,
propertyArray: objectPropertyArray,
declarationArray: blockStatementBody,
initExpressionStatementArray: initExpressionStatementArray
initExpressionStatementArray: initExpressionStatementArray,
renderSlotStatementArray
})
if (initExpressionStatementArray.length) {
......@@ -111,10 +113,14 @@ module.exports = function traverse (ast, state) {
blockStatementBody.push(getDataExpressionStatement(objectPropertyArray))
}
if (renderSlotStatementArray.length) {
blockStatementBody.push(...renderSlotStatementArray)
}
reIdentifier(identifierArray)
return t.withStatement(
t.thisExpression(),
t.blockStatement(blockStatementBody)
)
}
}
const t = require('@babel/types')
module.exports = function getRenderSlot (path, state) {
const name = path.get('arguments.0')
const arg2 = path.get('arguments.2')
const arg3 = path.get('arguments.3')
let valueNode
if (arg3) {
// v-bind:object
valueNode = arg3.node
} else if (arg2 && !arg2.isNullLiteral()) {
if (arg2.isObjectExpression()) {
const propertiesPath = arg2.get('properties')
const oldProperties = []
const newProperties = []
propertiesPath.forEach(path => {
const properties = path.get('key').isStringLiteral({ value: 'SLOT_DEFAULT' }) ? oldProperties : newProperties
properties.push(path.node)
})
if (!newProperties.length) {
return
}
valueNode = t.objectExpression(newProperties)
arg2.replaceWith(t.objectExpression(oldProperties))
} else {
valueNode = arg2.node
}
}
if (valueNode) {
state.renderSlotStatementArray.push(t.expressionStatement(t.callExpression(t.identifier('$setScopedSlotsParams'), [t.stringLiteral(name.node.value), valueNode])))
}
// TODO 组件嵌套
path.skip()
}
const t = require('@babel/types')
const {
METHOD_CREATE_EMPTY_VNODE
} = require('../../constants')
function replaceId (path, ids) {
let replaced
path.traverse({
noScope: true,
Identifier (path) {
const name = path.node.name
if (name in ids && path.key !== 'key' && (path.key !== 'property' || path.parent.computed)) {
path.replaceWith(ids[name])
replaced = true
}
}
})
return replaced
}
module.exports = function getResolveScopedSlots (parent, state) {
const properties = parent.get('arguments.0.elements.0.properties')
const fn = properties.find(path => path.get('key').isIdentifier({ name: 'fn' }))
const params = fn.get('value.params.0')
if (!params) {
return
}
const vueId = parent.parentPath.parentPath.get('properties').find(path => path.get('key').isIdentifier({ name: 'attrs' })).get('value').get('properties').find(path => path.get('key').isStringLiteral({ value: 'vue-id' })).get('value').node.value
const slot = properties.find(path => path.get('key').isIdentifier({ name: 'key' })).get('value').node.value
const ids = {}
function updateIds (vueId, slot, value, key) {
const array = [t.stringLiteral(vueId), t.stringLiteral(slot)]
if (key) {
array.push(t.stringLiteral(key))
}
ids[value] = t.callExpression(t.identifier('$getScopedSlotsParams'), array)
}
if (params.isObjectPattern()) {
params.get('properties').forEach(prop => {
updateIds(vueId, slot, prop.get('value').node.name, prop.get('key').node.name)
})
} else if (params.isIdentifier()) {
updateIds(vueId, slot, params.node.name)
}
const fnBody = fn.get('value.body')
if (replaceId(fnBody, ids)) {
const orgin = fnBody.get('body.0.argument')
const elements = orgin.get('elements')
const node = (elements.length === 1 ? elements[0] : orgin).node
const test = t.callExpression(t.identifier('$hasScopedSlotsParams'), [t.stringLiteral(vueId)])
orgin.replaceWith(t.arrayExpression([t.conditionalExpression(test, node, t.callExpression(t.identifier(METHOD_CREATE_EMPTY_VNODE), []))]))
}
}
......@@ -6,6 +6,8 @@ const {
METHOD_RENDER_LIST,
METHOD_BUILT_IN,
METHOD_RESOLVE_FILTER,
METHOD_RENDER_SLOT,
METHOD_RESOLVE_SCOPED_SLOTS,
IDENTIFIER_FILTER,
IDENTIFIER_METHOD,
IDENTIFIER_GLOBAL
......@@ -26,6 +28,8 @@ const traverseData = require('./data')
const traverseRenderList = require('./render-list')
const getMemberExpr = require('./member-expr')
const getRenderSlot = require('./render-slot')
const getResolveScopedSlots = require('./resolve-scoped-slots')
function addStaticClass (path, staticClass) {
const dataPath = path.get('arguments.1')
......@@ -217,6 +221,12 @@ module.exports = {
this
)
)
} else if (this.options.betterScopedSlots) {
if (methodName === METHOD_RESOLVE_SCOPED_SLOTS) {
getResolveScopedSlots(path, this)
} else if (methodName === METHOD_RENDER_SLOT) {
getRenderSlot(path, this)
}
}
break
}
......
......@@ -48,12 +48,17 @@ function processElement (ast, state, isRoot) {
const slots = []
for (let i = children.length - 1; i >= 0; i--) {
const childElement = children[i]
// <block name="left"></block> => <view name="left"></view>
/**
* 仅百度、字节支持使用 block 作为命名插槽根节点
* 此处为了统一仅忽略默认插槽
* <block slot="left"></block> => <view slot="left"></view>
*/
if (typeof childElement !== 'string' && childElement.attr.slot) {
if (childElement.type === 'block') {
const slot = childElement.attr.slot
if (slot && slot !== 'default' && childElement.type === 'block') {
childElement.type = 'view'
}
slots.push(childElement.attr.slot)
slots.push(slot)
} else {
defaultSlot = true
}
......@@ -78,7 +83,7 @@ function processElement (ast, state, isRoot) {
if (ast.attr.id && ast.attr.id.indexOf('{{') === 0) {
state.tips.add(`id 作为属性保留名,不允许在自定义组件 ${ast.type} 中定义为 props`)
}
if (hasOwn(ast.attr, 'data') && platformName !== 'mp-toutiao') { // 百度中会出现异常情况
if (hasOwn(ast.attr, 'data') && platformName !== 'mp-toutiao') { // 百度中会出现异常情况
// TODO 暂不输出
// state.tips.add(`data 作为属性保留名,不允许在自定义组件 ${ast.type} 中定义为 props`)
}
......
......@@ -273,6 +273,10 @@ function genSlotNode (slotName, slotNode, fallbackNodes, state) {
if (!fallbackNodes || t.isNullLiteral(fallbackNodes)) {
return slotNode
}
// 支付宝小程序默认插槽为 $default
if (state.options.platform.name === 'mp-alipay') {
slotName = slotName === 'default' ? '$default' : slotName
}
const prefix = state.options.platform.directive
return [{
type: 'block',
......@@ -300,7 +304,7 @@ function traverseRenderSlot (callExprNode, state) {
const slotName = callExprNode.arguments[0].value
let deleteSlotName = false // 标记是否组件 slot 手动指定了 name="default"
if (callExprNode.arguments.length > 2) { // 作用域插槽
if (!state.options.betterScopedSlots && callExprNode.arguments.length > 2) { // 作用域插槽
const props = {}
callExprNode.arguments[2].properties.forEach(property => {
props[property.key.value] = genCode(property.value)
......@@ -333,6 +337,20 @@ function traverseRenderSlot (callExprNode, state) {
}
function traverseResolveScopedSlots (callExprNode, state) {
function single (children, slotName, ignore) {
if (Array.isArray(children) && children.length === 1) {
const child = children[0]
if (!child.type) {
return
}
if (ignore.includes(child.type)) {
return single(child.children, slotName, ignore)
}
child.attr = child.attr || {}
child.attr.slot = slotName
return true
}
}
return callExprNode.arguments[0].elements.map(slotNode => {
let keyProperty = false
let fnProperty = false
......@@ -351,7 +369,7 @@ function traverseResolveScopedSlots (callExprNode, state) {
})
const slotName = keyProperty.value.value
const returnExprNodes = fnProperty.value.body.body[0].argument
if (!proxyProperty) {
if (!state.options.betterScopedSlots && !proxyProperty) {
const resourcePath = state.options.resourcePath
const ownerName = path.basename(resourcePath, path.extname(resourcePath))
......@@ -379,14 +397,18 @@ function traverseResolveScopedSlots (callExprNode, state) {
state
)
}
const node = {
type: 'view',
const children = normalizeChildren(traverseExpr(returnExprNodes, state))
// 除百度、字节外其他小程序仅默认插槽可以支持多个节点
if (single(children, slotName, ['template', 'block'])) {
return children[0]
}
return {
type: 'block',
attr: {
slot: slotName
},
children: normalizeChildren(traverseExpr(returnExprNodes, state))
children
}
return node
})
}
......@@ -488,4 +510,4 @@ function traverseCreateTextVNode (callExprNode, state) {
function traverseCreateEmptyVNode (callExprNode, state) {
return ''
}
}
......@@ -30,9 +30,11 @@ module.exports = function custom (argv) {
service.run(command, {
watch: process.env.NODE_ENV === 'development',
minimize: process.env.UNI_MINIMIZE === 'true',
clean: false
clean: false,
subpackage: argv.subpackage,
plugin: argv.plugin
}).catch(err => {
console.error(err)
process.exit(1)
})
})
}
......@@ -258,6 +258,10 @@ if (platformOptions.usingComponents === true) {
}
}
if (platformOptions.betterScopedSlots) {
process.env.BETTER_SCOPED_SLOTS = true
}
if (
process.env.UNI_USING_COMPONENTS ||
process.env.UNI_PLATFORM === 'h5'
......
......@@ -36,12 +36,12 @@ class ErrorReport {
return this._https
}
report (type, err) {
report (type, err = '') {
if (!this._shouldReport(err)) {
return
}
err = normalizePath(err)
err = normalizePath(err) || ''
err = err.replace(this._UNI_INPUT_DIR_REG, 'UNI_INPUT_DIR')
err = err.replace(this._UNI_CLI_CONTEXT_REG, 'UNI_CLI_CONTEXT')
......
......@@ -65,7 +65,8 @@ module.exports = function (content, map) {
const filterModules = parseFilterModules(params && params['filter-modules'])
Object.assign(vueLoaderOptions.options.compilerOptions, {
mp: {
platform: process.env.UNI_PLATFORM
platform: process.env.UNI_PLATFORM,
betterScopedSlots: process.env.BETTER_SCOPED_SLOTS
},
filterModules,
filterTagName,
......@@ -84,4 +85,4 @@ module.exports = function (content, map) {
throw new Error('vue-loader-options parse error')
}
this.callback(null, content, map)
}
}
......@@ -4,6 +4,7 @@ import {
} from 'uni-shared'
import emitter from './emitter'
import keyboard from './keyboard'
import interact from './interact'
UniViewJSBridge.subscribe('getSelectedTextRange', function ({ pageId, callbackId }) {
const activeElement = document.activeElement
......@@ -29,7 +30,7 @@ let startTime
export default {
name: 'Field',
mixins: [emitter, keyboard],
mixins: [emitter, keyboard, interact],
model: {
prop: 'value',
event: 'update:value'
......@@ -167,7 +168,10 @@ export default {
return
}
field.focus()
plus.key.showSoftKeybord()
// 无用户交互的 webview 需主动显示键盘(安卓)
if (!this.userInteract) {
plus.key.showSoftKeybord()
}
}
},
_blur () {
......
const eventNames = [
'load',
'close',
'error',
'adClicked'
]
class InterstitialAd {
constructor (options = {}) {
const _callbacks = this._callbacks = {}
eventNames.forEach(item => {
_callbacks[item] = []
const name = item[0].toUpperCase() + item.substr(1)
this[`on${name}`] = function (callback) {
_callbacks[item].push(callback)
}
})
this._isLoad = false
this._isLoading = false
this._adError = ''
this._loadPromiseResolve = null
this._loadPromiseReject = null
const ad = this._ad = plus.ad.createInterstitialAd(options)
ad.onLoad((e) => {
this._isLoad = true
this._isLoading = false
this._dispatchEvent('load', {})
if (this._loadPromiseResolve != null) {
this._loadPromiseResolve()
this._loadPromiseResolve = null
}
})
ad.onClose((e) => {
this._isLoad = false
this._isLoading = false
this._dispatchEvent('close', {})
})
ad.onError((e) => {
this._isLoading = false
const { code, message } = e
const data = { code: code, errMsg: message }
this._adError = message
this._dispatchEvent('error', data)
if (this._loadPromiseReject != null) {
this._loadPromiseReject(data)
this._loadPromiseReject = null
}
})
ad.onAdClicked((e) => {
this._dispatchEvent('adClicked', {})
})
}
load () {
return new Promise((resolve, reject) => {
this._loadPromiseResolve = resolve
this._loadPromiseReject = reject
if (this._isLoading) {
return
}
if (this._isLoad) {
resolve()
return
}
this._loadAd()
})
}
show () {
return new Promise((resolve, reject) => {
if (this._isLoading) {
return
}
if (this._isLoad) {
this._ad.show()
resolve()
} else {
reject(new Error(this._adError))
}
})
}
getProvider () {
return this._ad.getProvider()
}
destroy () {
this._ad.destroy()
}
_loadAd () {
this._isLoad = false
this._isLoading = true
this._ad.load()
}
_dispatchEvent (name, data) {
this._callbacks[name].forEach(callback => {
if (typeof callback === 'function') {
callback(data || {})
}
})
}
}
export function createInterstitialAd (options) {
return new InterstitialAd(options)
}
......@@ -24,6 +24,7 @@ class RewardedVideoAd {
this._preload = options.preload !== undefined ? options.preload : true
this._isLoad = false
this._isLoading = false
this._adError = ''
this._loadPromiseResolve = null
this._loadPromiseReject = null
......@@ -32,6 +33,7 @@ class RewardedVideoAd {
const rewardAd = this._rewardAd = plus.ad.createRewardedVideoAd(options)
rewardAd.onLoad((e) => {
this._isLoad = true
this._isLoading = false
this._lastLoadTime = Date.now()
this._dispatchEvent('load', {})
......@@ -41,6 +43,8 @@ class RewardedVideoAd {
}
})
rewardAd.onClose((e) => {
this._isLoad = false
this._isLoading = false
if (this._preload) {
this._loadAd()
}
......@@ -50,6 +54,7 @@ class RewardedVideoAd {
this._dispatchEvent('verify', { isValid: e.isValid })
})
rewardAd.onError((e) => {
this._isLoading = false
const { code, message } = e
const data = { code: code, errMsg: message }
this._adError = message
......@@ -78,18 +83,25 @@ class RewardedVideoAd {
load () {
return new Promise((resolve, reject) => {
this._loadPromiseResolve = resolve
this._loadPromiseReject = reject
if (this._isLoading) {
return
}
if (this._isLoad) {
resolve()
return
}
this._loadPromiseResolve = resolve
this._loadPromiseReject = reject
this._loadAd()
})
}
show () {
return new Promise((resolve, reject) => {
if (this._isLoading) {
return
}
const provider = this.getProvider()
if (provider === ProviderType.CSJ && this.isExpired) {
this._isLoad = false
......@@ -118,6 +130,7 @@ class RewardedVideoAd {
_loadAd () {
this._isLoad = false
this._isLoading = true
this._rewardAd.load()
}
......
......@@ -81,3 +81,4 @@ export * from './ui/request-component-info'
export * from './ad/ad'
export * from './ad/rewarded-video-ad'
export * from './ad/full-screen-video-ad'
export * from './ad/interstitial-ad'
......@@ -185,7 +185,7 @@ export function getStorageInfo () {
let currentSize = 0
for (let index = 0; index < length; index++) {
const key = plus.storage.key(index)
if (key !== STORAGE_KEYS && key.indexOf(STORAGE_DATA_TYPE) + STORAGE_DATA_TYPE.length !== key.length) {
if (key !== STORAGE_KEYS && (key.indexOf(STORAGE_DATA_TYPE) < 0 || key.indexOf(STORAGE_DATA_TYPE) + STORAGE_DATA_TYPE.length !== key.length)) {
const value = plus.storage.getItem(key)
currentSize += key.length + value.length
keys.push(key)
......
......@@ -93,10 +93,15 @@ function initGlobalListeners () {
})
})
let keyboardHeightChange = 0
plus.globalEvent.addEventListener('KeyboardHeightChange', function (event) {
publish('onKeyboardHeightChange', {
height: event.height
})
// 安卓设备首次获取高度为 0
if (keyboardHeightChange !== event.height) {
keyboardHeightChange = event.height
publish('onKeyboardHeightChange', {
height: keyboardHeightChange
})
}
})
globalEvent.addEventListener('uistylechange', function (event) {
......
export default {
/**
* 关于图片常见的MIME类型
*/
image: {
jpg: 'jpeg',
jpe: 'jpeg',
pbm: 'x-portable-bitmap',
pgm: 'x-portable-graymap',
pnm: 'x-portable-anymap',
ppm: 'x-portable-pixmap',
psd: 'vnd.adobe.photoshop',
pic: 'x-pict',
rgb: 'x-rgb',
svg: 'svg+xml',
svgz: 'svg+xml',
tif: 'tiff',
xif: 'vnd.xiff',
wbmp: 'vnd.wap.wbmp',
wdp: 'vnd.ms-photo',
xbm: 'x-xbitmap',
ico: 'x-icon'
},
/**
* 关于视频常见的MIME类型
*/
video: {
'3g2': '3gpp2',
'3gp': '3gpp',
avi: 'x-msvideo',
f4v: 'x-f4v',
flv: 'x-flv',
jpgm: 'jpm',
jpgv: 'jpeg',
m1v: 'mpeg',
m2v: 'mpeg',
mpe: 'mpeg',
mpg: 'mpeg',
mpg4: 'mpeg',
m4v: 'x-m4v',
mkv: 'x-matroska',
mov: 'quicktime',
qt: 'quicktime',
movie: 'x-sgi-movie',
mp4v: 'mp4',
ogv: 'ogg',
smv: 'x-smv',
wm: 'x-ms-wm',
wmv: 'x-ms-wmv',
wmx: 'x-ms-wmx',
wvx: 'x-ms-wvx'
}
}
import { updateElementStyle } from 'uni-shared'
import MIMEType from './MIMEType'
const ALL = '*'
function isWXEnv () {
......@@ -24,16 +25,20 @@ export default function ({ count, sourceType, type, extension }) {
left: 0
})
/**
* 选择文件
* chooseFile 使用后缀名
* chooseImage、chooseVideo 使用MIME类型
*/
inputEl.accept = extension.map(item => {
if (type !== ALL) {
// 剔除.拼接在type后
return `${type}/${item.replace('.', '')}`
const MIMEKey = item.replace('.', '')
return `${type}/${MIMEType[type][MIMEKey] || MIMEKey}`
} else {
// 在微信环境里,'.jpeg,.png' 会提示没有应用可执行此操作
if (isWXEnv()) {
return '.'
}
// 在后缀前方加上.
return item.indexOf('.') === 0 ? item : `.${item}`
}
}).join(',')
......
......@@ -8,9 +8,14 @@ import {
import {
isPage,
initRelation
initRelation,
mocks
} from './util'
import {
initMocks
} from 'uni-wrapper/util'
import parseBaseComponent from '../../../mp-weixin/runtime/wrapper/component-base-parser'
const newLifecycle = swan.canIUse('lifecycle-2-0')
......@@ -52,6 +57,7 @@ export default function parseComponent (vueOptions) {
if (!this.$vm) {
oldAttached.call(this)
} else {
initMocks(this.$vm, mocks)
this.__fixInitData && this.__fixInitData()
}
if (isPage.call(this)) { // 百度 onLoad 在 attached 之前触发(基础库小于 3.70)
......
......@@ -41,11 +41,63 @@ function initEventChannel () {
}
}
function initScopedSlotsParams () {
const center = {}
const parents = {}
Vue.prototype.$hasScopedSlotsParams = function (vueId) {
const has = center[vueId]
if (!has) {
parents[vueId] = this
this.$on('hook:destory', () => {
delete parents[vueId]
})
}
return has
}
Vue.prototype.$getScopedSlotsParams = function (vueId, name, key) {
const data = center[vueId]
if (data) {
const object = data[name] || {}
return key ? object[key] : object
} else {
parents[vueId] = this
this.$on('hook:destory', () => {
delete parents[vueId]
})
}
}
Vue.prototype.$setScopedSlotsParams = function (name, value) {
const vueId = this.$options.propsData.vueId
const object = center[vueId] = center[vueId] || {}
object[name] = value
if (parents[vueId]) {
parents[vueId].$forceUpdate()
}
}
Vue.mixin({
destroyed () {
const propsData = this.$options.propsData
const vueId = propsData && propsData.vueId
if (vueId) {
delete center[vueId]
delete parents[vueId]
}
}
})
}
export default function parseBaseApp (vm, {
mocks,
initRefs
}) {
initEventChannel()
if (__PLATFORM__ === 'mp-weixin' || __PLATFORM__ === 'mp-qq' || __PLATFORM__ === 'mp-toutiao' || __PLATFORM__ === 'mp-kuaishou' || __PLATFORM__ === 'mp-alipay' || __PLATFORM__ === 'mp-baidu') {
initScopedSlotsParams()
}
if (vm.$options.store) {
Vue.prototype.$store = vm.$options.store
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册