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

merge

......@@ -29,7 +29,7 @@ App端如需要更丰富的相机拍照API(如直接调用前置摄像头)
|参数|类型|说明|
|:-|:-|:-|
|tempFilePaths|Array<String>|图片的本地文件路径列表|
|tempFiles|Array<Object>|图片的本地文件列表,每一项是一个 File 对象|
|tempFiles|Array<Object>、Array<File>|图片的本地文件列表,每一项是一个 File 对象|
**File 对象结构如下**
......@@ -38,6 +38,7 @@ App端如需要更丰富的相机拍照API(如直接调用前置摄像头)
|path|String|本地文件路径|
|size|Number|本地文件大小,单位:B|
|name|String|包含扩展名的文件名称,仅H5支持|
|type|String|文件类型,仅H5支持|
**示例**
......
......@@ -21,14 +21,15 @@
**success 返回参数说明**
|参数|说明|平台差异说明说明|
|:-|:-|:-|
|tempFilePath|选定视频的临时文件路径||
|duration|选定视频的时间长度,单位为 s|APP平台 2.1.0+、微信小程序|
|size|选定视频的数据量大小|APP平台 2.1.0+、微信小程序|
|height|返回选定视频的高|APP平台 2.1.0+、微信小程序|
|width|返回选定视频的宽|APP平台 2.1.0+、微信小程序|
|name|包含扩展名的文件名称|仅H5支持|
|参数|类型|说明|平台差异说明说明|
|:-|:-|:-|:-|
|tempFilePath|String|选定视频的临时文件路径||
|tempFile|File|选定的视频文件|仅H5(2.7.0+)支持|
|duration|Number|选定视频的时间长度,单位为 s|APP 2.1.0+、H5、微信小程序|
|size|Number|选定视频的数据量大小|APP 2.1.0+、H5、微信小程序|
|height|Number|返回选定视频的高|APP 2.1.0+、H5、微信小程序|
|width|Number|返回选定视频的宽|APP 2.1.0+、H5、微信小程序|
|name|String|包含扩展名的文件名称|仅H5支持|
**注意:**
* 文件的临时路径,在应用本次启动期间可以正常使用,如需持久保存,需在主动调用 [uni.saveFile](api/file/file?id=savefile),在应用下次启动时才能访问得到。
......
......@@ -9,8 +9,9 @@
|参数名|类型|必填|说明|平台差异说明|
|:-|:-|:-|:-|:-|
|url|String|是|开发者服务器 url||
|files|Array|否|需要上传的文件列表。**使用 files 时,filePath 和 name 不生效。**|App|
|files|Array|否|需要上传的文件列表。**使用 files 时,filePath 和 name 不生效。**|App、H5( 2.7.0+)|
|fileType|String|见平台差异说明|文件类型,image/video/audio|仅支付宝小程序,且必填。|
|file|File|否|要上传的文件对象。|仅H5(2.7.0+)支持|
|filePath|String|是|要上传文件资源的路径。||
|name|String|是|文件对应的 key , 开发者在服务器端通过这个 key 可以获取到文件二进制内容||
|header|Object|否|HTTP 请求 Header, header 中不能设置 Referer。||
......@@ -33,6 +34,7 @@ files 参数是一个 file 对象的数组,file 对象的结构如下:
|参数名|类型|必填|说明|
|:-|:-|:-|:-|
|name|String|否|multipart 提交时,表单的项目名,默认为 file|
|file|File|否|要上传的文件对象,仅H5(2.7.0+)支持|
|uri|String|是|文件的本地地址|
Tip:
......
......@@ -15,6 +15,7 @@
|dataType|String|否|json |如果设为 json,会尝试对返回的数据做一次 JSON.parse||
|responseType|String|否|text |设置响应的数据类型。合法值:text、arraybuffer|App和支付宝小程序不支持|
|sslVerify|Boolean|否|true|验证 ssl 证书|仅App安卓端支持(HBuilderX 2.3.3+)|
|withCredentials|Boolean|否|false|跨域请求时是否携带凭证(cookies)|仅H5支持(HBuilderX 2.7.0+)|
|success|Function|否||收到开发者服务成功返回的回调函数||
|fail|Function|否||接口调用失败的回调函数||
|complete|Function|否||接口调用结束的回调函数(调用成功、失败都会执行)| |
......
......@@ -231,13 +231,13 @@ const promiseInterceptor = {
};
const SYNC_API_RE =
/^\$|restoreGlobal|getCurrentSubNVue|getMenuButtonBoundingClientRect|^report|interceptors|Interceptor$|getSubNVueById|requireNativePlugin|upx2px|hideKeyboard|canIUse|^create|Sync$|Manager$|base64ToArrayBuffer|arrayBufferToBase64/;
/^\$|sendNativeEvent|restoreGlobal|getCurrentSubNVue|getMenuButtonBoundingClientRect|^report|interceptors|Interceptor$|getSubNVueById|requireNativePlugin|upx2px|hideKeyboard|canIUse|^create|Sync$|Manager$|base64ToArrayBuffer|arrayBufferToBase64/;
const CONTEXT_API_RE = /^create|Manager$/;
const ASYNC_API = ['createBLEConnection'];
const CALLBACK_API_RE = /^on/;
const CALLBACK_API_RE = /^on|^off/;
function isContextApi (name) {
return CONTEXT_API_RE.test(name)
......@@ -1699,6 +1699,17 @@ function parsePage (vuePageOptions) {
} else {
this.is && console.warn(this.is + ' is not ready');
}
};
pageOptions.lifetimes.detached = function detached () {
this.$vm && this.$vm.$destroy();
// 清理
const webviewId = this.__webviewId__;
webviewId && Object.keys(instances).forEach(key => {
if (key.indexOf(webviewId + '_') === 0) {
delete instances[key];
}
});
};
return pageOptions
......
function typof (v) {
var s = Object.prototype.toString.call(v)
return s.substring(8, s.length - 1)
}
function isDebugMode () {
/* eslint-disable no-undef */
return typeof __channelId__ === 'string' && __channelId__
}
export function log (type) {
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key]
}
console[type].apply(console, args)
}
export default function formatLog () {
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key]
}
var type = args.shift()
if (isDebugMode()) {
args.push(args.pop().replace('at ', 'uni-app:///'))
return console[type]['apply'](console, args)
}
var msgs = args.map(function (v) {
var type = Object.prototype.toString.call(v).toLowerCase()
if (type === '[object object]' || type === '[object array]') {
try {
v = '---BEGIN:JSON---' + JSON.stringify(v) + '---END:JSON---'
} catch (e) {
v = '[object object]'
}
} else {
if (v === null) {
v = '---NULL---'
} else if (v === undefined) {
v = '---UNDEFINED---'
} else {
var vType = typof(v).toUpperCase()
if (vType === 'NUMBER' || vType === 'BOOLEAN') {
v = '---BEGIN:' + vType + '---' + v + '---END:' + vType + '---'
} else {
v = String(v)
}
}
}
return v
})
var msg = ''
if (msgs.length > 1) {
var lastMsg = msgs.pop()
msg = msgs.join('---COMMA---')
if (lastMsg.indexOf(' at ') === 0) {
msg += lastMsg
} else {
msg += '---COMMA---' + lastMsg
}
} else {
msg = msgs[0]
}
console[type](msg)
function typof (v) {
var s = Object.prototype.toString.call(v)
return s.substring(8, s.length - 1)
}
function isDebugMode () {
/* eslint-disable no-undef */
return typeof __channelId__ === 'string' && __channelId__
}
export function log (type) {
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key]
}
console[type].apply(console, args)
}
export default function formatLog () {
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key]
}
var type = args.shift()
if (isDebugMode()) {
args.push(args.pop().replace('at ', 'uni-app:///'))
return console[type]['apply'](console, args)
}
var msgs = args.map(function (v) {
var type = Object.prototype.toString.call(v).toLowerCase()
if (type === '[object object]' || type === '[object array]') {
try {
v = '---BEGIN:JSON---' + JSON.stringify(v) + '---END:JSON---'
} catch (e) {
v = '[object object]'
}
} else {
if (v === null) {
v = '---NULL---'
} else if (v === undefined) {
v = '---UNDEFINED---'
} else {
var vType = typof(v).toUpperCase()
if (vType === 'NUMBER' || vType === 'BOOLEAN') {
v = '---BEGIN:' + vType + '---' + v + '---END:' + vType + '---'
} else {
v = String(v)
}
}
}
return v
})
var msg = ''
if (msgs.length > 1) {
var lastMsg = msgs.pop()
msg = msgs.join('---COMMA---')
if (lastMsg.indexOf(' at ') === 0) {
msg += lastMsg
} else {
msg += '---COMMA---' + lastMsg
}
} else {
msg = msgs[0]
}
console[type](msg)
}
......@@ -75,7 +75,10 @@ module.exports = function initOptions (options) {
options.css.loaderOptions.sass.sassOptions = {}
}
// 指定 outputStyle, 否则 production 模式下会被默认成 compressed
options.css.loaderOptions.sass.sassOptions.outputStyle = 'nested'
const outputStyle = options.css.loaderOptions.sass.sassOptions.outputStyle
if (!outputStyle || outputStyle === 'compressed') {
options.css.loaderOptions.sass.sassOptions.outputStyle = 'expanded'
}
if (sassLoaderVersion < 8) {
options.css.loaderOptions.sass.data = sassData
......
......@@ -26,6 +26,31 @@ function parseRoutes (config) {
return __uniRoutes
}
const GLOBALS = [
'global',
'window',
'document',
'frames',
'self',
'location',
'navigator',
'localStorage',
'history',
'Caches',
'screen',
'alert',
'confirm',
'prompt',
'fetch',
'XMLHttpRequest',
'WebSocket',
'webkit',
'print'
]
const globalStatement = GLOBALS.map(g => `${g}:void 0`).join(',')
module.exports = function definePages (appJson) {
const __uniRoutes = parseRoutes(appJson)
......@@ -42,7 +67,7 @@ var isReady=false;var onReadyCallbacks=[];
var __uniConfig = ${JSON.stringify(appJson, null)};
var __uniRoutes = ${JSON.stringify(__uniRoutes)};
__uniConfig.onReady=function(callback){if(__uniConfig.ready){callback()}else{onReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"ready",{get:function(){return isReady},set:function(val){isReady=val;if(!isReady){return}const callbacks=onReadyCallbacks.slice(0);onReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}});
service.register("uni-app-config",{create(a,b,c){if(!__uniConfig.viewport){var d=b.weex.config.env.scale,e=b.weex.config.env.deviceWidth,f=Math.ceil(e/d);Object.assign(__uniConfig,{viewport:f,defaultFontSize:Math.round(f/20)})}return{instance:{__uniConfig:__uniConfig,__uniRoutes:__uniRoutes,window:void 0,global:void 0}}}});
service.register("uni-app-config",{create(a,b,c){if(!__uniConfig.viewport){var d=b.weex.config.env.scale,e=b.weex.config.env.deviceWidth,f=Math.ceil(e/d);Object.assign(__uniConfig,{viewport:f,defaultFontSize:Math.round(f/20)})}return{instance:{__uniConfig:__uniConfig,__uniRoutes:__uniRoutes,${globalStatement}}}}});
`
}
}
......@@ -355,7 +355,8 @@ import Vue from 'vue'
global['____${h5.appid}____'] = true;
delete global['____${h5.appid}____'];
global.__uniConfig = ${JSON.stringify(pagesJson)};
global.__uniConfig.router = ${JSON.stringify(h5.router)};
global.__uniConfig.router = ${JSON.stringify(h5.router)};
global.__uniConfig.publicPath = ${JSON.stringify(h5.publicPath)};
global.__uniConfig['async'] = ${JSON.stringify(h5['async'])};
global.__uniConfig.debug = ${manifestJson.debug === true};
global.__uniConfig.networkTimeout = ${JSON.stringify(networkTimeoutConfig)};
......
......@@ -100,5 +100,8 @@ export const request = {
value = (value || '').toLowerCase()
params.responseType = Object.values(responseType).indexOf(value) < 0 ? responseType.TEXT : value
}
},
withCredentials: {
type: Boolean
}
}
}
......@@ -9,6 +9,9 @@ export const uploadFile = {
files: {
type: Array
},
file: {
type: File
},
filePath: {
type: String,
validator (value, params) {
......
......@@ -60,7 +60,7 @@ class SocketTask {
success,
fail,
complete
}, errMsg) {
} = {}, errMsg) {
var data = {
errMsg
}
......
......@@ -9,13 +9,13 @@ export default function initSubscribe (subscribe, {
getCurrentPages
}) {
function createPageEvent (eventType) {
return function (args, pageId) {
return function (args, pageId) {
pageId = parseInt(pageId)
const pages = getCurrentPages()
const page = pages.find(page => page.$page.id === pageId)
if (page) {
callPageHook(page, eventType, args)
} else {
} else if (process.env.NODE_ENV !== 'production') {
console.error(`Not Found:Page[${pageId}]`)
}
}
......@@ -48,7 +48,7 @@ export default function initSubscribe (subscribe, {
}
callback(res)
}
}
}
if (__PLATFORM__ === 'h5') {
subscribe('onPageReady', createPageEvent('onReady'))
......@@ -59,4 +59,4 @@ export default function initSubscribe (subscribe, {
subscribe('onRequestComponentInfo', onRequestComponentInfo)
subscribe('onRequestComponentObserver', onRequestComponentObserver)
}
}
......@@ -48,7 +48,7 @@ const initStateChage = audioId => {
export function createAudioInstance () {
const audioId = `${Date.now()}${Math.random()}`
const audio = audios[audioId] = plus.audio.createPlayer('')
const audio = audios[audioId] = plus.audio.createPlayer('')
audio.src = ''
audio.volume = 1
audio.startTime = 0
......@@ -122,7 +122,7 @@ export function getAudioState ({
errMsg: 'getAudioState:ok',
duration: 1e3 * (audio.getDuration() || 0),
currentTime: audio.isStopped ? 0 : 1e3 * audio.getPosition(),
paused: audio.isPaused,
paused: audio.isPaused(),
src,
volume,
startTime: 1e3 * startTime,
......@@ -138,7 +138,7 @@ export function operateAudio ({
const audio = audios[audioId]
const operationTypes = ['play', 'pause', 'stop']
if (operationTypes.indexOf(operationType) >= 0) {
audio[operationType === operationTypes[0] && audio.isPaused ? 'resume' : operationType]()
audio[operationType === operationTypes[0] && audio.isPaused() ? 'resume' : operationType]()
} else if (operationType === 'seek') {
audio.seekTo(currentTime / 1e3)
}
......
......@@ -6,9 +6,9 @@ import {
publish
} from '../../bridge'
let audio
let timeUpdateTimer = null
let audio
let timeUpdateTimer = null
const TIME_UPDATE = 250
const publishBackgroundAudioStateChange = (state, res = {}) => publish('onBackgroundAudioStateChange', Object.assign({
......@@ -31,15 +31,15 @@ function initMusic () {
audio.addEventListener(event, () => {
// 添加 isStopped 属性是为了解决 安卓设备停止播放后获取播放进度不正确的问题
if (event === 'play') {
audio.isStopped = false
audio.isStopped = false
startTimeUpdateTimer()
} else if (event === 'stop') {
audio.isStopped = true
}
if (event === 'pause' || event === 'ended' || event === 'stop') {
stopTimeUpdateTimer()
}
}
if (event === 'pause' || event === 'ended' || event === 'stop') {
stopTimeUpdateTimer()
}
const eventName = `onMusic${event[0].toUpperCase() + event.substr(1)}`
publish(eventName, {
......@@ -51,13 +51,13 @@ function initMusic () {
})
})
})
audio.addEventListener('waiting', () => {
audio.addEventListener('waiting', () => {
stopTimeUpdateTimer()
publishBackgroundAudioStateChange('waiting', {
dataUrl: audio.src
})
})
audio.addEventListener('error', err => {
audio.addEventListener('error', err => {
stopTimeUpdateTimer()
publish('onMusicError', {
dataUrl: audio.src,
......@@ -71,20 +71,20 @@ function initMusic () {
})
audio.addEventListener('prev', () => publish('onBackgroundAudioPrev'))
audio.addEventListener('next', () => publish('onBackgroundAudioNext'))
}
function startTimeUpdateTimer () {
stopTimeUpdateTimer()
timeUpdateTimer = setInterval(() => {
publishBackgroundAudioStateChange('timeUpdate', {})
}, TIME_UPDATE)
}
}
function stopTimeUpdateTimer () {
if (timeUpdateTimer !== null) {
clearInterval(timeUpdateTimer)
}
}
function startTimeUpdateTimer () {
stopTimeUpdateTimer()
timeUpdateTimer = setInterval(() => {
publishBackgroundAudioStateChange('timeUpdate', {})
}, TIME_UPDATE)
}
function stopTimeUpdateTimer () {
if (timeUpdateTimer !== null) {
clearInterval(timeUpdateTimer)
}
}
function setMusicState (args) {
initMusic()
......@@ -113,7 +113,7 @@ export function getMusicPlayerState () {
dataUrl: audio.src,
duration: audio.getDuration() || 0,
currentPosition: audio.getPosition(),
status: audio.isPaused ? 0 : 1,
status: audio.isPaused() ? 0 : 1,
downloadPercent: Math.round(100 * audio.getBuffered() / audio.getDuration()),
errMsg: `getMusicPlayerState:ok`
}
......@@ -189,7 +189,7 @@ export function getBackgroundAudioState () {
let newData = {
duration: audio.getDuration() || 0,
currentTime: audio.isStopped ? 0 : audio.getPosition(),
paused: audio.isPaused,
paused: audio.isPaused(),
src: audio.src,
buffered: audio.getBuffered(),
title: audio.title,
......
......@@ -52,8 +52,7 @@ function diffElmData (newObj, oldObj) {
cur = newObj[key]
old = oldObj[key]
if (old !== cur) {
// 全量同步 style (因为 style 可能会动态删除部分样式)
if (key === B_STYLE && isPlainObject(cur) && isPlainObject(old)) {
if (key === B_STYLE && isPlainObject(cur) && isPlainObject(old)) { // 全量同步 style (因为 style 可能会动态删除部分样式)
if (Object.keys(cur).length !== Object.keys(old).length) { // 长度不等
setResult(result || (result = Object.create(null)), B_STYLE, cur)
} else {
......@@ -64,6 +63,14 @@ function diffElmData (newObj, oldObj) {
const vFor = diffArray(cur, old)
vFor && setResult(result || (result = Object.create(null)), V_FOR, vFor)
} else {
if (key.indexOf('change:') === 0) { // wxs change:prop
try {
// 先简单的用 stringify 判断
if (JSON.stringify(cur) === JSON.stringify(old)) {
continue
}
} catch (e) {}
}
setResult(result || (result = Object.create(null)), key, cur)
}
}
......
......@@ -61,3 +61,8 @@ export function fileToUrl (file) {
files[url] = file
return url
}
export function revokeObjectURL (url) {
(window.URL || window.webkitURL).revokeObjectURL(url)
delete files[url]
}
......@@ -50,26 +50,27 @@ export function chooseImage ({
document.body.appendChild(imageInput)
imageInput.addEventListener('change', function (event) {
const tempFilePaths = []
const tempFiles = []
const fileCount = event.target.files.length
for (let i = 0; i < fileCount; i++) {
const file = event.target.files[i]
const filePath = fileToUrl(file)
tempFilePaths.push(filePath)
tempFiles.push({
path: filePath,
size: file.size,
name: file.name
let filePath
Object.defineProperty(file, 'filePath', {
get () {
filePath = filePath || fileToUrl(file)
return filePath
}
})
tempFiles.push(file)
}
invoke(callbackId, {
const res = {
errMsg: 'chooseImage:ok',
tempFilePaths: tempFilePaths,
get tempFilePaths () {
return tempFiles.map(({ filePath }) => filePath)
},
tempFiles: tempFiles
})
}
invoke(callbackId, res)
// TODO 用户取消选择时,触发 fail,目前尚未找到合适的方法。
})
......
import { fileToUrl } from 'uni-platform/helpers/file'
import { fileToUrl, revokeObjectURL } from 'uni-platform/helpers/file'
import { updateElementStyle } from 'uni-shared'
const {
......@@ -42,23 +42,30 @@ export function chooseVideo ({
videoInput.addEventListener('change', function (event) {
const file = event.target.files[0]
const filePath = fileToUrl(file)
let callbackResult = {
const callbackResult = {
errMsg: 'chooseVideo:ok',
tempFilePath: filePath,
tempFile: file,
size: file.size,
duration: 0,
width: 0,
height: 0,
name: file.name
}
let filePath
Object.defineProperty(callbackResult, 'tempFilePath', {
get () {
filePath = filePath || fileToUrl(this.tempFile)
return filePath
}
})
const video = document.createElement('video')
if (video.onloadedmetadata !== undefined) {
const filePath = fileToUrl(file)
// 尝试获取视频的宽高信息
video.onloadedmetadata = function () {
invoke(callbackId, Object.assign({}, callbackResult, {
revokeObjectURL(filePath)
invoke(callbackId, Object.assign(callbackResult, {
duration: video.duration || 0,
width: video.videoWidth || 0,
height: video.videoHeight || 0
......@@ -66,11 +73,9 @@ export function chooseVideo ({
}
// 部分浏览器(如微信内置浏览器)未播放无法触发loadedmetadata事件
setTimeout(() => {
invoke(callbackId, Object.assign({}, callbackResult, {
duration: 0,
width: 0,
height: 0
}))
video.onloadedmetadata = null
revokeObjectURL(filePath)
invoke(callbackId, callbackResult)
}, 300)
video.src = filePath
} else {
......
......@@ -45,7 +45,8 @@ export function request ({
header,
method,
dataType,
responseType
responseType,
withCredentials
}, callbackId) {
const {
invokeCallbackHandler: invoke
......@@ -143,6 +144,7 @@ export function request ({
errMsg: 'request:fail'
})
}
xhr.withCredentials = withCredentials
xhr.send(body)
return requestTask
}
......@@ -45,8 +45,10 @@ class UploadTask {
*/
export function uploadFile ({
url,
file,
filePath,
name,
files,
header,
formData
}, callbackId) {
......@@ -55,15 +57,24 @@ export function uploadFile ({
invokeCallbackHandler: invoke
} = UniServiceJSBridge
var uploadTask = new UploadTask(null, callbackId)
function upload (file) {
if (!Array.isArray(files) || !files.length) {
files = [{
name,
file,
uri: filePath
}]
}
function upload (realFiles) {
var xhr = new XMLHttpRequest()
var form = new FormData()
var timer
Object.keys(formData).forEach(key => {
form.append(key, formData[key])
})
form.append(name, file, file.name || `file-${Date.now()}`)
Object.values(files).forEach(({ name }, index) => {
const file = realFiles[index]
form.append(name || 'file', file, file.name || `file-${Date.now()}`)
})
xhr.open('POST', url)
Object.keys(header).forEach(key => {
xhr.setRequestHeader(key, header[key])
......@@ -118,13 +129,16 @@ export function uploadFile ({
}
}
urlToFile(filePath).then(upload).catch(() => {
setTimeout(() => {
invoke(callbackId, {
errMsg: 'uploadFile:fail file error'
})
}, 0)
})
Promise
.all(files.map(({ file, uri }) => file instanceof File ? Promise.resolve(file) : urlToFile(uri)))
.then(upload)
.catch(() => {
setTimeout(() => {
invoke(callbackId, {
errMsg: 'uploadFile:fail file error'
})
}, 0)
})
return uploadTask
}
import {
isPage,
isPage,
instances,
initRelation
} from './util'
......@@ -21,6 +22,17 @@ export default function parsePage (vuePageOptions) {
} else {
this.is && console.warn(this.is + ' is not ready')
}
}
pageOptions.lifetimes.detached = function detached () {
this.$vm && this.$vm.$destroy()
// 清理
const webviewId = this.__webviewId__
webviewId && Object.keys(instances).forEach(key => {
if (key.indexOf(webviewId + '_') === 0) {
delete instances[key]
}
})
}
return pageOptions
......
......@@ -51,7 +51,7 @@ export function initRefs (vm) {
}
}
const instances = Object.create(null)
export const instances = Object.create(null)
export function initRelation ({
vuePid,
......@@ -101,4 +101,4 @@ export function handleLink ({
vm._isMounted = true
vm.__call_hook('mounted')
vm.__call_hook('onReady')
}
}
......@@ -78,7 +78,8 @@ src
#### 开发示例
- button 组件 [https://github.com/dcloudio/uni-app/tree/master/src/platforms/quickapp/view/components/button](https://github.com/dcloudio/uni-app/tree/master/src/platforms/quickapp/view/components/button)
- button 组件 `src/platforms/quickapp/view/components/button`
- clipboard API `src/platforms/quickapp/service/api/device/clipboard`
......
import clipboard from '@system.clipboard'
import {
invoke
} from '../../bridge'
export function getClipboardData (options, callbackId) {
clipboard.get({
success: (ret) => {
invoke(callbackId, {
data: ret.text,
errMsg: 'getClipboardData:ok'
})
},
fail: (data, code) => {
invoke(callbackId, {
data: code,
errMsg: 'getClipboardData:fail'
})
}
})
}
export function setClipboardData ({
data
}) {
clipboard.set({
text: data
})
return {
errMsg: 'setClipboardData:ok'
}
}
export * from './api/route/navigate-back'
export * from './api/route/navigate-to'
export * from './api/route/redirect-to'
// device
export * from './api/device/clipboard'
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册