提交 7b474871 编写于 作者: Q qiang

chore: Merge branch 'feat-support-xhs' into dev

# Conflicts:
#	packages/uni-cli-shared/lib/platform.js
......@@ -2,7 +2,7 @@
`uni-app` 是一个使用 `Vue.js` 开发小程序、H5、App的统一前端框架。官网地址:[https://uniapp.dcloud.io](https://uniapp.dcloud.io)
开发者使用 `Vue` 语法编写代码,`uni-app` 框架将其编译到 小程序(微信/支付宝/百度/字节跳动/QQ/快手/钉钉)、App(iOS/Android)、H5等多个平台,保证其正确运行并达到优秀体验。
开发者使用 `Vue` 语法编写代码,`uni-app` 框架将其编译到 小程序(微信/支付宝/百度/字节跳动/QQ/快手/钉钉/小红书)、App(iOS/Android)、H5等多个平台,保证其正确运行并达到优秀体验。
# uni-app的特点
......
......@@ -36,6 +36,10 @@ const PLATFORMS = {
prefix: 'jd',
title: '京东小程序'
},
'mp-xhs': {
prefix: 'xhs',
title: '小红书小程序'
},
'quickapp-webview': {
prefix: 'qa',
title: '快应用(Webview)版'
......
......@@ -21,11 +21,12 @@
"build:mp-kuaishou": "cross-env UNI_PLATFORM=mp-kuaishou rollup -c build/rollup.config.mp.js",
"build:mp-lark": "cross-env UNI_PLATFORM=mp-lark rollup -c build/rollup.config.mp.js",
"build:mp-jd": "cross-env UNI_PLATFORM=mp-jd rollup -c build/rollup.config.mp.js",
"build:mp-xhs": "cross-env UNI_PLATFORM=mp-xhs rollup -c build/rollup.config.mp.js",
"build:quickapp-webview": "cross-env UNI_PLATFORM=quickapp-webview rollup -c build/rollup.config.mp.js",
"build:mp-weixin:mp": "cross-env UNI_PLATFORM=mp-weixin UNI_MP=true rollup -c build/rollup.config.mp.js",
"build:mp-weixin:wxs": "rollup -c build/rollup.config.wxs.js",
"build:quickapp-native": "cross-env NODE_ENV=development node build/build.qa.js && cross-env NODE_ENV=production node build/build.qa.js",
"build:runtime": "npm run lint && npm run build:mp-weixin && npm run build:mp-qq && npm run build:mp-alipay && npm run build:mp-baidu && npm run build:mp-toutiao && npm run build:mp-jd && npm run build:app-plus && npm run build:quickapp-webview && npm run build:quickapp-native && npm run build:mp-kuaishou && npm run build:mp-lark && npm run build:mp-jd",
"build:runtime": "npm run lint && npm run build:mp-weixin && npm run build:mp-qq && npm run build:mp-alipay && npm run build:mp-baidu && npm run build:mp-toutiao && npm run build:mp-jd && npm run build:mp-xhs && npm run build:app-plus && npm run build:quickapp-webview && npm run build:quickapp-native && npm run build:mp-kuaishou && npm run build:mp-lark && npm run build:mp-jd",
"build:stat": "npm run lint && rollup -c build/rollup.config.stat.js",
"build:web-view": "rollup -c build/rollup.config.web-view.js",
"test:cli": "cross-env NODE_ENV=test jest",
......@@ -115,6 +116,7 @@
"tt": true,
"qh": true,
"qa": true,
"xhs": true,
"HWH5": true,
"weex": true,
"__id__": true,
......
......@@ -148,7 +148,7 @@ module.exports = {
getShadowCss,
getShadowTemplate (colorType = 'grey') {
let tagName = 'cover-image'
if (process.env.UNI_PLATFORM === 'mp-toutiao' || process.env.UNI_PLATFORM === 'mp-lark') {
if (process.env.UNI_PLATFORM === 'mp-toutiao' || process.env.UNI_PLATFORM === 'mp-lark' || process.env.UNI_PLATFORM === 'mp-xhs') {
tagName = 'image'
}
return `<${tagName} src="${getShadowCdn()}/img/shadow-${colorType}.png" style="z-index:998;position:fixed;left:0;top:0;width:100%;height:3px;"/>`
......
......@@ -12,6 +12,7 @@ const inlineLimit =
process.env.UNI_PLATFORM === 'mp-kuaishou' ||
process.env.UNI_PLATFORM === 'mp-lark' ||
process.env.UNI_PLATFORM === 'mp-jd' ||
process.env.UNI_PLATFORM === 'mp-xhs' ||
process.env.UNI_PLATFORM === 'app-plus' // v2需要base64,v3需要rewriteUrl
// mp-weixin,mp-qq,app-plus 非v3(即:需要base64的平台)
......
# `uni-mp-xhs`
> 处理模板上的差异,比如文件格式模板上的各种指令。
## Usage
```
const uniMpXhs = require('uni-mp-xhs');
// TODO: DEMONSTRATE API
```
此差异已折叠。
const compiler = require('@dcloudio/uni-mp-weixin/lib/uni.compiler.js')
module.exports = Object.assign({}, compiler, {
directive: 'xhs:'
})
module.exports = {
options: {
cssVars: {
'--status-bar-height': '25px',
'--window-top': '0px',
'--window-bottom': '0px',
'--window-left': '0px',
'--window-right': '0px'
},
extnames: {
style: '.css',
template: '.xhsml'
},
project: 'project.config.json',
subPackages: true
},
copyWebpackOptions (platformOptions, vueOptions) {
const copyOptions = ['xhscomponents']
global.uniModules.forEach(module => {
copyOptions.push('uni_modules/' + module + '/xhscomponents')
})
return copyOptions
}
}
{
"name": "@dcloudio/uni-mp-xhs",
"version": "2.0.0-32920211029001",
"description": "uni-app mp-xhs",
"main": "dist/index.js",
"repository": {
"type": "git",
"url": "git+https://github.com/dcloudio/uni-app.git",
"directory": "packages/uni-mp-xhs"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "txu",
"license": "Apache-2.0",
"uni-app": {
"name": "mp-xhs",
"title": "小红书小程序"
},
"gitHead": "9e2d0f8e244724fcd64880316c57d837d1778cf8"
}
......@@ -6,6 +6,7 @@ const PLATFORMS = [
'mp-baidu',
'mp-alipay',
'mp-jd',
'mp-xhs',
'mp-toutiao',
'quickapp-native'
]
......
......@@ -110,6 +110,7 @@ const get_platform_name = () => {
'mp-qq': 'qq',
'quickapp-native': 'qn',
'mp-kuaishou': 'ks',
'mp-xhs': 'xhs',
'mp-lark': 'lark',
'quickapp-webview': 'qw'
};
......
......@@ -105,6 +105,7 @@ export const get_platform_name = () => {
'mp-qq': 'qq',
'quickapp-native': 'qn',
'mp-kuaishou': 'ks',
'mp-xhs': 'xhs',
'mp-lark': 'lark',
'quickapp-webview': 'qw'
}
......
......@@ -231,7 +231,7 @@ function traverseDataNode (dataNode, state, node) {
let key
// 自定义组件不支持 hidden 属性
const platform = state.options.platform.name
const platforms = ['mp-weixin', 'mp-qq', 'mp-jd', 'mp-toutiao', 'mp-lark']
const platforms = ['mp-weixin', 'mp-qq', 'mp-jd', 'mp-xhs', 'mp-toutiao', 'mp-lark']
if (isComponent(node.type) && platforms.includes(platform)) {
// 字节跳动|飞书小程序自定义属性不会反应在DOM上,只能使用事件格式
key = `${platform === 'mp-toutiao' || platform === 'mp-lark' ? 'bind:-' : ''}${ATTE_DATA_CUSTOM_HIDDEN}`
......
......@@ -294,8 +294,8 @@ const modes = ['legacy', 'auto', 'augmented']
const scopedSlotsCompiler = !platformOptions.scopedSlotsCompiler && platformOptions.betterScopedSlots ? modes[2]
: platformOptions.scopedSlotsCompiler
process.env.SCOPED_SLOTS_COMPILER = modes.includes(scopedSlotsCompiler) ? scopedSlotsCompiler : modes[1]
// 快手小程序抽象组件编译报错,如未指定 legacy 固定为 augmented 模式
if (process.env.UNI_PLATFORM === 'mp-kuaishou' && process.env.SCOPED_SLOTS_COMPILER !== modes[0]) {
// 快手小程序、小红书小程序 抽象组件编译报错,如未指定 legacy 固定为 augmented 模式
if ((process.env.UNI_PLATFORM === 'mp-kuaishou' || process.env.UNI_PLATFORM === 'mp-xhs') && process.env.SCOPED_SLOTS_COMPILER !== modes[0]) {
process.env.SCOPED_SLOTS_COMPILER = modes[2]
}
......
......@@ -4616,7 +4616,7 @@ function initProps (vm, propsOptions) {
defineReactive$$1(props, key, value, function () {
if (!isRoot && !isUpdatingChildComponent) {
{
if(vm.mpHost === 'mp-baidu' || vm.mpHost === 'mp-kuaishou'){//百度、快手 observer 在 setData callback 之后触发,直接忽略该 warn
if(vm.mpHost === 'mp-baidu' || vm.mpHost === 'mp-kuaishou' || vm.mpHost === 'mp-xhs'){//百度、快手、小红书 observer 在 setData callback 之后触发,直接忽略该 warn
return
}
//fixed by xxxxxx __next_tick_pending,uni://form-field 时不告警
......
......@@ -85,6 +85,7 @@ const getPlatformName = () => {
'mp-toutiao': 'tt',
'mp-qq': 'qq',
'mp-jd': 'jd',
'mp-xhs': 'xhs',
'quickapp-native': 'qn',
'mp-kuaishou': 'ks',
};
......
......@@ -83,6 +83,7 @@ const getPlatformName = () => {
'mp-toutiao': 'tt',
'mp-qq': 'qq',
'mp-jd': 'jd',
'mp-xhs': 'xhs',
'quickapp-native': 'qn',
'mp-kuaishou': 'ks',
};
......
......@@ -47,7 +47,7 @@ module.exports = function generateApp (compilation) {
// 框架预设样式 用于隐藏自定义组件
// TODO 分平台 import 不同 css
const platforms = ['mp-weixin', 'mp-qq', 'mp-jd', 'mp-toutiao', 'mp-lark']
const platforms = ['mp-weixin', 'mp-qq', 'mp-jd', 'mp-xhs', 'mp-toutiao', 'mp-lark']
const presetStyle = platforms.includes(process.env.UNI_PLATFORM) ? '[data-custom-hidden="true"],[bind-data-custom-hidden="true"]{display: none !important;}' : ''
if (compilation.assets[`common/main${ext}`]) { // 是否存在 main.css
......
module.exports = function (pagesJson, manifestJson) {
const {
app,
project
} = require('../mp')(pagesJson, manifestJson, require('./project.config.json'))
return [app, project]
}
{
"setting": {
"urlCheck": true,
"es6": false,
"postcss": false,
"minified": false,
"newFeature": true
},
"appid": "testAppId",
"projectname": ""
}
......@@ -35,6 +35,9 @@ import {
import {
initWebviewApi as initJDWebviewApi
} from 'uni-platforms/mp-jd/runtime/web-view'
import {
initWebviewApi as initXhsWebviewApi
} from 'uni-platforms/mp-xhs/runtime/web-view'
const UniAppJSBridgeReady = function () {
window.UniAppJSBridge = true
......@@ -55,6 +58,7 @@ const initWebviewApis = [
initKuaishouWebviewApi,
initLarkWebviewApi,
initJDWebviewApi,
initXhsWebviewApi,
initH5WebviewApi
]
......
import parsePage from 'uni-platform/runtime/wrapper/page-parser'
export default function createPage (vuePageOptions) {
if (__PLATFORM__ === 'mp-alipay') {
if (__PLATFORM__ === 'mp-alipay' || __PLATFORM__ === 'mp-xhs') {
return Page(parsePage(vuePageOptions))
} else {
return Component(parsePage(vuePageOptions))
......
......@@ -106,7 +106,7 @@ export default function parseBaseApp (vm, {
initRefs
}) {
initEventChannel()
if (__PLATFORM__ === 'mp-weixin' || __PLATFORM__ === 'mp-qq' || __PLATFORM__ === 'mp-jd' || __PLATFORM__ === 'mp-toutiao' || __PLATFORM__ ===
if (__PLATFORM__ === 'mp-weixin' || __PLATFORM__ === 'mp-qq' || __PLATFORM__ === 'mp-jd' || __PLATFORM__ === 'mp-xhs' || __PLATFORM__ === 'mp-toutiao' || __PLATFORM__ ===
'mp-kuaishou' || __PLATFORM__ === 'mp-alipay' || __PLATFORM__ === 'mp-baidu' || __PLATFORM__ === 'mp-lark') {
initScopedSlotsParams()
}
......
# `uni-mp-xhs`
> 处理运行时 API 兼容。
// import navigateTo from 'uni-helpers/navigate-to'
// import redirectTo from '../../../mp-weixin/helpers/redirect-to'
// import previewImage from '../../../mp-weixin/helpers/normalize-preview-image'
// import getSystemInfo from '../../../mp-weixin/helpers/system-info'
// import getUserProfile from '../../../mp-weixin/helpers/get-user-profile'
// 需要做转换的 API 列表
export const protocols = {
// navigateTo,
// redirectTo,
// previewImage,
// getSystemInfo,
// getSystemInfoSync: getSystemInfo,
// getUserProfile
}
// 不支持的 API 列表
// TODO: 补充
export const todos = [
'getSelectedTextRange'
]
// 存在兼容性的 API 列表
export const canIUses = []
export default {
oauth: ['xhs'],
share: ['xhs'],
payment: ['xhs'],
push: ['xhs']
}
import '../../mp-weixin/runtime/index'
const isXhs = window.xhs &&
window.xhs.miniProgram &&
/xhsminiapp/i.test(navigator.userAgent)
export function initWebviewApi (readyCallback) {
if (!isXhs) {
return
}
// todo 没有 XhsJSBridgeReady
// if (window.XhsJSBridgeReady && window.XhsJSBridgeReady.invoke) {
// setTimeout(readyCallback, 0)
// } else {
// document.addEventListener('XhsJSBridgeReady', readyCallback)
// }
return window.xhs.miniProgram
}
import parseBaseApp from '../../../mp-weixin/runtime/wrapper/app-parser'
export default function parseApp (vm) {
return parseBaseApp(vm)
}
// import parseBaseComponent from '../../../mp-weixin/runtime/wrapper/component-parser'
// export default function parseComponent (vueComponentOptions) {
// const componentOptions = parseBaseComponent(vueComponentOptions)
// // 小红书小程序 lifetimes 存在兼容问题
// const lifetimes = componentOptions.lifetimes
// Object.keys(lifetimes).forEach(key => {
// componentOptions[key] = lifetimes[key]
// })
// return componentOptions
// }
import parseBaseComponent from '../../../mp-weixin/runtime/wrapper/component-parser'
import { isPage } from '../../../mp-weixin/runtime/wrapper/util'
import {
fixSetDataStart,
fixSetDataEnd
} from '../../../mp-weixin/runtime/wrapper/fix-set-data'
export default function parseComponent (vueComponentOptions) {
const componentOptions = parseBaseComponent(vueComponentOptions)
const oldAttached = componentOptions.lifetimes.attached
componentOptions.lifetimes.attached = function attached () {
// 暂不区分版本
if (isPage.call(this)) {
fixSetDataStart(this)
setTimeout(() => {
fixSetDataEnd(this)
}, 0)
}
oldAttached.call(this)
}
return componentOptions
}
import Vue from 'vue'
import {
stringifyQuery
} from 'uni-shared/query'
import {
initData,
initHooks,
handleEvent,
initBehaviors,
initVueComponent,
PAGE_EVENT_HOOKS
} from 'uni-wrapper/util'
import { handleLink, initBehavior } from '../../../mp-weixin/runtime/wrapper/util'
import {
handleWrap,
initSpecialMethods
} from './util'
const hooks = [
'onShow',
'onHide',
'onUnload'
]
hooks.push(...PAGE_EVENT_HOOKS)
export default function parsePage (vuePageOptions) {
const [VueComponent, vueOptions] = initVueComponent(Vue, vuePageOptions)
const pageOptions = {
mixins: initBehaviors(vueOptions, initBehavior),
data: initData(vueOptions, Vue.prototype),
onLoad (query) {
const properties = this.props
const options = {
mpType: 'page',
mpInstance: this,
propsData: properties
}
// 初始化 vue 实例
this.$vm = new VueComponent(options)
initSpecialMethods(this)
// 触发首次 setData
this.$vm.$mount()
const copyQuery = Object.assign({}, query)
delete copyQuery.__id__
this.$page = {
fullPath: '/' + this.route + stringifyQuery(copyQuery)
}
this.options = query
this.$vm.$mp.query = query // 兼容 mpvue
this.$vm.__call_hook('onLoad', query)
},
onReady () {
// initChildVues(this)
this.$vm._isMounted = true
this.$vm.__call_hook('mounted')
this.$vm.__call_hook('onReady')
},
onUnload () {
this.$vm.__call_hook('onUnload')
this.$vm.$destroy()
},
// __r: handleRef,
__e: handleEvent,
__l: handleLink,
__w: handleWrap,
triggerEvent: function noop () {}
}
initHooks(pageOptions, hooks, vuePageOptions)
if (Array.isArray(vueOptions.wxsCallMethods)) {
vueOptions.wxsCallMethods.forEach(callMethod => {
pageOptions[callMethod] = function (args) {
return this.$vm[callMethod](args)
}
})
}
return pageOptions
}
import {
isFn,
hasOwn
} from 'uni-shared'
export const isComponent2 = xhs.canIUse('component2')
export const mocks = ['$id']
export function initSpecialMethods (mpInstance) {
if (!mpInstance.$vm) {
return
}
let path = mpInstance.is || mpInstance.route
if (!path) {
return
}
if (path.indexOf('/') === 0) {
path = path.substr(1)
}
const specialMethods = xhs.specialMethods && xhs.specialMethods[path]
if (specialMethods) {
specialMethods.forEach(method => {
if (isFn(mpInstance.$vm[method])) {
mpInstance[method] = function (event) {
if (hasOwn(event, 'markerId')) {
event.detail = typeof event.detail === 'object' ? event.detail : {}
event.detail.markerId = event.markerId
}
// TODO normalizeEvent
mpInstance.$vm[method](event)
}
}
})
}
}
export const handleWrap = function (mp, destory) {
const vueId = mp.props.vueId
const list = mp.props['data-event-list'].split(',')
list.forEach(eventName => {
const key = `${eventName}${vueId}`
if (destory) {
delete this[key]
} else {
// TODO remove handleRef
this[key] = function () {
mp.props[eventName].apply(this, arguments)
}
}
})
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册