提交 afcde0a1 编写于 作者: A Aero 提交者: qiang

added support for mp-kuaishou

上级 2b678939
......@@ -23,6 +23,10 @@ const PLATFORMS = {
prefix: 'tt',
title: '头条小程序'
},
'mp-kuaishou': {
prefix: 'ks',
title: '快手小程序'
},
'quickapp-webview': {
prefix: 'qa',
title: '快应用(Webview)版'
......@@ -73,4 +77,4 @@ module.exports = {
})
],
external: ['vue']
}
}
......@@ -18,6 +18,7 @@
"build:mp-baidu": "cross-env UNI_PLATFORM=mp-baidu rollup -c build/rollup.config.mp.js",
"build:mp-alipay": "cross-env UNI_PLATFORM=mp-alipay rollup -c build/rollup.config.mp.js",
"build:mp-toutiao": "cross-env UNI_PLATFORM=mp-toutiao rollup -c build/rollup.config.mp.js",
"build:mp-kuaishou": "cross-env UNI_PLATFORM=mp-kuaishou 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",
......
......@@ -146,4 +146,4 @@ module.exports = {
]
}
}
}
}
此差异已折叠。
{
"name": "@dcloudio/uni-mp-kuaishou",
"version": "2.0.0-23320190923002",
"description": "uni-app mp-kuaishou",
"main": "dist/index.js",
"repository": {
"type": "git",
"url": "git+https://github.com/aeroxy/uni-app.git",
"directory": "packages/uni-mp-kuaishou"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Aero Wang",
"license": "MIT"
}
......@@ -75,7 +75,8 @@ export const getPlatformName = () => {
'mp-alipay': 'ali',
'mp-baidu': 'bd',
'mp-toutiao': 'tt',
'mp-qq': 'qq'
'mp-qq': 'qq',
'mp-kuaishou': 'ks'
}
return platformList[process.env.VUE_APP_PLATFORM];
}
......@@ -385,4 +386,4 @@ const requestData = (done) => {
})
}
});
}
}
const compiler = require('../lib')
function assertCodegen (template, templateCode, renderCode = `with(this){}`, options = {}) {
const res = compiler.compile(template, {
resourcePath: 'test.wxml',
mp: Object.assign({
minified: true,
isTest: true,
platform: 'mp-kuaishou'
}, options)
})
expect(res.template).toBe(templateCode)
if (typeof renderCode === 'function') {
renderCode(res)
} else {
expect(res.render).toBe(renderCode)
}
}
describe('mp:compiler-mp-kuaishou', () => {
it('generate scoped slot', () => {
assertCodegen(
'<foo><template slot-scope="{bar}">{{ bar.foo }}</template></foo>',
`<foo generic:scoped-slots-default="test-foo-default" vue-id="1" bind:__l="__l" vue-slots="{{['default']}}"></foo>`,
function (res) {
expect(res.generic[0]).toBe('test-foo-default')
}
)
assertCodegen(
'<foo><view slot-scope="{bar}">{{ bar.foo }}</view></foo>',
`<foo generic:scoped-slots-default="test-foo-default" vue-id="1" bind:__l="__l" vue-slots="{{['default']}}"></foo>`,
function (res) {
expect(res.generic[0]).toBe('test-foo-default')
}
)
})
it('generate named scoped slot', () => {
assertCodegen(
'<foo><template slot="foo" slot-scope="{bar}">{{ bar.foo }}</template></foo>',
`<foo generic:scoped-slots-foo="test-foo-foo" vue-id="1" bind:__l="__l" vue-slots="{{['foo']}}"></foo>`,
function (res) {
expect(res.generic[0]).toBe('test-foo-foo')
}
)
assertCodegen(
'<foo><view slot="foo" slot-scope="{bar}">{{ bar.foo }}</view></foo>',
`<foo generic:scoped-slots-foo="test-foo-foo" vue-id="1" bind:__l="__l" vue-slots="{{['foo']}}"></foo>`,
function (res) {
expect(res.generic[0]).toBe('test-foo-foo')
}
)
})
it('generate scoped slot with multiline v-if', () => {
assertCodegen(
'<foo><template v-if="\nshow\n" slot-scope="{bar}">{{ bar.foo }}</template></foo>',
`<foo generic:scoped-slots-default="test-foo-default" vue-id="1" bind:__l="__l" vue-slots="{{['default']}}"></foo>`,
function (res) {
expect(res.generic[0]).toBe('test-foo-default')
}
)
assertCodegen(
'<foo><view v-if="\nshow\n" slot="foo" slot-scope="{bar}">{{ bar.foo }}</view></foo>',
`<foo generic:scoped-slots-foo="test-foo-foo" vue-id="1" bind:__l="__l" vue-slots="{{['foo']}}"></foo>`,
function (res) {
expect(res.generic[0]).toBe('test-foo-foo')
}
)
})
it('generate scoped slot', () => {
assertCodegen(// TODO vue-id
'<span><slot v-bind:user="user">{{ user.lastName }}</slot></span>',
`<label class="_span"><block wx:if="{{$slots.default}}"><scoped-slots-default user="{{user}}" bind:__l="__l"></scoped-slots-default></block><block wx:else>{{user.lastName}}</block></label>`,
function (res) {
expect(res.componentGenerics['scoped-slots-default']).toBe(true)
}
)
assertCodegen(
'<span><slot name="header" v-bind:user="user">{{ user.lastName }}</slot></span>',
`<label class="_span"><block wx:if="{{$slots.header}}"><scoped-slots-header user="{{user}}" bind:__l="__l"></scoped-slots-header></block><block wx:else>{{user.lastName}}</block></label>`,
function (res) {
expect(res.componentGenerics['scoped-slots-header']).toBe(true)
}
)
})
})
const mpWeixin = require('./mp-weixin')
module.exports = Object.assign({}, mpWeixin, {
prefix: 'ks:'
})
......@@ -16,6 +16,7 @@ module.exports = (api, options, rootOptions) => {
'dev:mp-baidu': 'cross-env NODE_ENV=development UNI_PLATFORM=mp-baidu vue-cli-service uni-build --watch',
'dev:mp-alipay': 'cross-env NODE_ENV=development UNI_PLATFORM=mp-alipay vue-cli-service uni-build --watch',
'dev:mp-toutiao': 'cross-env NODE_ENV=development UNI_PLATFORM=mp-toutiao vue-cli-service uni-build --watch',
'dev:mp-kuaishou': 'cross-env NODE_ENV=development UNI_PLATFORM=mp-kuaishou vue-cli-service uni-build --watch',
'dev:quickapp-native': 'cross-env NODE_ENV=development UNI_PLATFORM=quickapp-native vue-cli-service uni-build --watch',
'dev:quickapp-webview': 'cross-env NODE_ENV=development UNI_PLATFORM=quickapp-webview vue-cli-service uni-build --watch',
'dev:quickapp-webview-huawei': 'cross-env NODE_ENV=development UNI_PLATFORM=quickapp-webview-huawei vue-cli-service uni-build --watch',
......@@ -26,6 +27,7 @@ module.exports = (api, options, rootOptions) => {
'build:mp-baidu': 'cross-env NODE_ENV=production UNI_PLATFORM=mp-baidu vue-cli-service uni-build',
'build:mp-alipay': 'cross-env NODE_ENV=production UNI_PLATFORM=mp-alipay vue-cli-service uni-build',
'build:mp-toutiao': 'cross-env NODE_ENV=production UNI_PLATFORM=mp-toutiao vue-cli-service uni-build',
'build:mp-kuaishou': 'cross-env NODE_ENV=production UNI_PLATFORM=mp-kuaishou vue-cli-service uni-build',
'build:quickapp-native': 'cross-env NODE_ENV=production UNI_PLATFORM=quickapp-native vue-cli-service uni-build',
'build:quickapp-webview': 'cross-env NODE_ENV=production UNI_PLATFORM=quickapp-webview vue-cli-service uni-build',
'build:quickapp-webview-huawei': 'cross-env NODE_ENV=production UNI_PLATFORM=quickapp-webview-huawei vue-cli-service uni-build',
......@@ -80,4 +82,4 @@ module.exports = (api, options, rootOptions) => {
]
}
})
}
}
......@@ -742,7 +742,7 @@ if (inBrowser) {
Object.defineProperty(opts, 'passive', ({
get: function get () {
/* istanbul ignore next */
}
})); // https://github.com/facebook/flow/issues/285
window.addEventListener('test-passive', null, opts);
......@@ -781,10 +781,10 @@ var hasSymbol =
/* istanbul ignore if */ // $flow-disable-line
if (typeof Set !== 'undefined' && isNative(Set)) {
// use native Set when available.
} else {
// a non-standard Set polyfill that only works with primitive keys.
}
var ASSET_TYPES = [
......@@ -1636,19 +1636,19 @@ if (typeof MessageChannel !== 'undefined' && (
)) {
var channel = new MessageChannel();
channel.port1.onmessage = flushCallbacks;
} else {
/* istanbul ignore next */
}
// Determine microtask defer implementation.
/* istanbul ignore next, $flow-disable-line */
if (typeof Promise !== 'undefined' && isNative(Promise)) {
} else {
// fallback to macro
}
/**
......@@ -4748,11 +4748,47 @@ var swan$1 = mergePreset(basePrest, {
}
})
var ks = mergePreset(basePrest, {
prefix: prefix,
ext: "ksml",
directives: {
if: (prefix + "if"),
elseif: (prefix + "elif"),
else: (prefix + "else"),
for: (prefix + "for"),
forItem: (prefix + "for-item"),
forIndex: (prefix + "for-index"),
forKey: (prefix + "key"),
on: "bind",
onStop: "catch",
capture: "capture"
},
eventTypeMap: eventTypeMap$1,
findEventType: findEventType,
genBind: function genBind (event, type, tag) {
var modifiers = event.modifiers; if ( modifiers === void 0 ) modifiers = {};
var isCapture = /!/.test(type);
var realType = type.replace(/^[~|!]/, '');
var stop = modifiers.stop;
var mpType = realType;
var binder = stop ? 'catch' : 'bind';
binder = isCapture ? ("capture-" + binder) : binder;
if (type === 'change' && (tag === 'input' || tag === 'textarea')) {
mpType = 'blur';
} else {
mpType = mpType === 'click' ? 'tap' : mpType;
}
return ("" + binder + mpType)
}
})
var presets = {
wechat: wechat,
alipay: alipay,
swan: swan$1,
tt:tt//fixed by xxxxxx
tt: tt, //fixed by xxxxxx
ks: ks
}
var vbindReg = /^(v-bind:?|:)/;
......@@ -4977,7 +5013,7 @@ function addAttr$1 (node, name, value) {
attrsMap[name] = "" + value;
Object.assign(node, { attrs: attrs, attrsMap: attrsMap });
}
function isTag (node) {
......@@ -5170,7 +5206,7 @@ function walk$1 (node, state) {
} else if (
node.type === TYPE$1.TEXT || node.type === TYPE$1.STATIC_TEXT
) {
}
}
......@@ -5423,7 +5459,7 @@ TemplateGenerator.prototype.genImports = function genImports () {
var imports = ref.imports;
var components = ref._components||new Set();//fixed by xxxxxx
return Object.keys(imports)
.map(function (name) {
.map(function (name) {
//fixed by xxxxxx 过滤 import
// if(process.env.UNI_PLATFORM === 'mp-alipay'){
if(name==='_slots_'){
......@@ -5447,14 +5483,14 @@ TemplateGenerator.prototype.genElement = function genElement (el) {
return this.genVHtml(el)
} else if (this.isSlot(el)) {
//fixed by xxxxxx 记录是否定义slot
this._hasSlot = true;
this._hasSlot = true;
return this.genSlot(el)
} else if (this.isComponent(el)) {
//fixed by xxxxxx 记录自定义组件
if(!this._components){
this._components = new Set()
}
this._components.add(el.tag.toLowerCase().replace(/-/g,''))
this._components.add(el.tag.toLowerCase().replace(/-/g,''))
return this.genComponent(el)
} else if (el.type === 1) {
return this.genTag(el)
......
module.exports = function (pagesJson, manifestJson) {
const {
app,
project
} = require('../mp')(pagesJson, manifestJson, require('./project.config.json'))
return [app, project]
}
{
"description": "项目配置文件。",
"libVersion": "0.6.0",
"appid": "touristappid",
"projectname": ""
}
......@@ -26,6 +26,9 @@ import {
import {
initWebviewApi as initQuickappWebviewApi
} from 'uni-platforms/quickapp-webview/runtime/web-view'
import {
initWebviewApi as initKuaishouWebviewApi
} from 'uni-platforms/mp-kuaishou/runtime/web-view'
const UniAppJSBridgeReady = function () {
window.UniAppJSBridge = true
......@@ -43,6 +46,7 @@ const initWebviewApis = [
initBaiduWebviewApi,
initToutiaoWebviewApi,
initQuickappWebviewApi,
initKuaishouWebviewApi,
initH5WebviewApi
]
......@@ -69,4 +73,4 @@ if (!api.navigateTo) {
}
api.webView = webViewApi
export default api
export default api
export default {
args (fromArgs) {
let currentIndex = parseInt(fromArgs.current)
if (isNaN(currentIndex)) {
return
}
const urls = fromArgs.urls
if (!Array.isArray(urls)) {
return
}
const len = urls.length
if (!len) {
return
}
if (currentIndex < 0) {
currentIndex = 0
} else if (currentIndex >= len) {
currentIndex = len - 1
}
if (currentIndex > 0) {
fromArgs.current = urls[currentIndex]
fromArgs.urls = urls.filter(
(item, index) => index < currentIndex ? item !== urls[currentIndex] : true
)
} else {
fromArgs.current = urls[0]
}
return {
indicator: false,
loop: false
}
}
}
import previewImage from '../../helpers/normalize-preview-image'
export const protocols = {
previewImage
}
export const todos = [
'vibrate'
]
export const canIUses = []
export default {
oauth: ['kuaishou'],
share: ['kuaishou'],
payment: ['kspay'],
push: ['kuaishou']
}
import {
cached,
camelize
} from 'uni-shared'
const MPPage = Page
const MPComponent = Component
const customizeRE = /:/g
const customize = cached((str) => {
return camelize(str.replace(customizeRE, '-'))
})
function initTriggerEvent (mpInstance) {
const oldTriggerEvent = mpInstance.triggerEvent
mpInstance.triggerEvent = function (event, ...args) {
return oldTriggerEvent.apply(mpInstance, [customize(event), ...args])
}
}
function initHook (name, options) {
const oldHook = options[name]
if (!oldHook) {
options[name] = function () {
initTriggerEvent(this)
}
} else {
options[name] = function (...args) {
initTriggerEvent(this)
return oldHook.apply(this, args)
}
}
}
Page = function (options = {}) {
initHook('onLoad', options)
return MPPage(options)
}
Component = function (options = {}) {
initHook('created', options)
return MPComponent(options)
}
const isKuaishou = window.ks &&
window.ks.miniProgram &&
/micromessenger/i.test(navigator.userAgent) &&
/miniProgram/i.test(navigator.userAgent)
export function initWebviewApi (readyCallback) {
if (!isKuaishou) {
return
}
if (window.WeixinJSBridge && window.WeixinJSBridge.invoke) {
setTimeout(readyCallback, 0)
} else {
document.addEventListener('WeixinJSBridgeReady', readyCallback)
}
return window.ks.miniProgram
}
import Vue from 'vue'
import {
initHooks,
initMocks
} from 'uni-wrapper/util'
const hooks = [
'onShow',
'onHide',
'onError',
'onPageNotFound'
]
export default function parseBaseApp (vm, {
mocks,
initRefs
}) {
if (vm.$options.store) {
Vue.prototype.$store = vm.$options.store
}
Vue.prototype.mpHost = __PLATFORM__
Vue.mixin({
beforeCreate () {
if (!this.$options.mpType) {
return
}
this.mpType = this.$options.mpType
this.$mp = {
data: {},
[this.mpType]: this.$options.mpInstance
}
this.$scope = this.$options.mpInstance
delete this.$options.mpType
delete this.$options.mpInstance
if (this.mpType !== 'app') {
initRefs(this)
initMocks(this, mocks)
}
}
})
const appOptions = {
onLaunch (args) {
if (this.$vm) { // 已经初始化过了,主要是为了百度,百度 onShow 在 onLaunch 之前
return
}
this.$vm = vm
this.$vm.$mp = {
app: this
}
this.$vm.$scope = this
// vm 上也挂载 globalData
this.$vm.globalData = this.globalData
this.$vm._isMounted = true
this.$vm.__call_hook('mounted', args)
this.$vm.__call_hook('onLaunch', args)
}
}
// 兼容旧版本 globalData
appOptions.globalData = vm.$options.globalData || {}
// 将 methods 中的方法挂在 getApp() 中
const methods = vm.$options.methods
if (methods) {
Object.keys(methods).forEach(name => {
appOptions[name] = methods[name]
})
}
initHooks(appOptions, hooks)
return appOptions
}
import parseBaseApp from './app-base-parser'
import {
mocks,
initRefs
} from './util'
export default function parseApp (vm) {
return parseBaseApp(vm, {
mocks,
initRefs
})
}
import Vue from 'vue'
import {
initData,
initSlots,
initVueIds,
handleEvent,
initBehaviors,
initProperties,
initVueComponent
} from 'uni-wrapper/util'
import {
handleLink,
initBehavior
} from './util'
export default function parseBaseComponent (vueComponentOptions, {
isPage,
initRelation
} = {}) {
let [VueComponent, vueOptions] = initVueComponent(Vue, vueComponentOptions)
const options = {
multipleSlots: true,
addGlobalClass: true
}
const componentOptions = {
options,
data: initData(vueOptions, Vue.prototype),
behaviors: initBehaviors(vueOptions, initBehavior),
properties: initProperties(vueOptions.props, false, vueOptions.__file),
lifetimes: {
attached () {
const properties = this.properties
const options = {
mpType: isPage.call(this) ? 'page' : 'component',
mpInstance: this,
propsData: properties
}
initVueIds(properties.vueId, this)
// 处理父子关系
initRelation.call(this, {
vuePid: this._$vuePid,
vueOptions: options
})
// 初始化 vue 实例
this.$vm = new VueComponent(options)
// 处理$slots,$scopedSlots(暂不支持动态变化$slots)
initSlots(this.$vm, properties.vueSlots)
// 触发首次 setData
this.$vm.$mount()
},
ready () {
// 当组件 props 默认值为 true,初始化时传入 false 会导致 created,ready 触发, 但 attached 不触发
// https://developers.weixin.qq.com/community/develop/doc/00066ae2844cc0f8eb883e2a557800
if (this.$vm) {
this.$vm._isMounted = true
this.$vm.__call_hook('mounted')
this.$vm.__call_hook('onReady')
} else {
// this.is && console.warn(this.is + ' is not attached')
}
},
detached () {
this.$vm.$destroy()
}
},
pageLifetimes: {
show (args) {
this.$vm && this.$vm.__call_hook('onPageShow', args)
},
hide () {
this.$vm && this.$vm.__call_hook('onPageHide')
},
resize (size) {
this.$vm && this.$vm.__call_hook('onPageResize', size)
}
},
methods: {
__l: handleLink,
__e: handleEvent
}
}
if (Array.isArray(vueOptions.wxsCallMethods)) {
vueOptions.wxsCallMethods.forEach(callMethod => {
componentOptions.methods[callMethod] = function (args) {
return this.$vm[callMethod](args)
}
})
}
if (isPage) {
return componentOptions
}
return [componentOptions, VueComponent]
}
import parseBaseComponent from './component-base-parser'
import {
isPage,
initRelation
} from './util'
export default function parseComponent (vueComponentOptions) {
return parseBaseComponent(vueComponentOptions, {
isPage,
initRelation
})
}
import {
initHooks,
PAGE_EVENT_HOOKS
} from 'uni-wrapper/util'
import parseComponent from 'uni-platform/runtime/wrapper/component-parser'
const hooks = [
'onShow',
'onHide',
'onUnload'
]
hooks.push(...PAGE_EVENT_HOOKS)
export default function parseBasePage (vuePageOptions, {
isPage,
initRelation
}) {
const pageOptions = parseComponent(vuePageOptions, {
isPage,
initRelation
})
initHooks(pageOptions.methods, hooks, vuePageOptions)
pageOptions.methods.onLoad = function (args) {
this.$vm.$mp.query = args // 兼容 mpvue
this.$vm.__call_hook('onLoad', args)
}
return pageOptions
}
import parseBasePage from './page-base-parser'
import {
isPage,
initRelation
} from './util'
export default function parsePage (vuePageOptions) {
return parseBasePage(vuePageOptions, {
isPage,
initRelation
})
}
/* 快手也使用__wxExparserNodeId__和__wxWebviewId__ */
export const mocks = ['__route__', '__wxExparserNodeId__', '__wxWebviewId__']
export function findVmByVueId (vm, vuePid) {
const $children = vm.$children
// 优先查找直属
let parentVm = $children.find(childVm => childVm.$scope._$vueId === vuePid)
if (parentVm) {
return parentVm
}
// 反向递归查找
for (let i = $children.length - 1; i >= 0; i--) {
parentVm = findVmByVueId($children[i], vuePid)
if (parentVm) {
return parentVm
}
}
}
export function initBehavior (options) {
return Behavior(options)
}
export function isPage () {
return !!this.route
}
export function initRelation (detail) {
this.triggerEvent('__l', detail)
}
export function initRefs (vm) {
const mpInstance = vm.$scope
Object.defineProperty(vm, '$refs', {
get () {
const $refs = {}
const components = mpInstance.selectAllComponents('.vue-ref')
components.forEach(component => {
const ref = component.dataset.ref
$refs[ref] = component.$vm || component
})
const forComponents = mpInstance.selectAllComponents('.vue-ref-in-for')
forComponents.forEach(component => {
const ref = component.dataset.ref
if (!$refs[ref]) {
$refs[ref] = []
}
$refs[ref].push(component.$vm || component)
})
return $refs
}
})
}
export function handleLink (event) {
const {
vuePid,
vueOptions
} = event.detail || event.value // detail 是微信,value 是百度(dipatch)
let parentVm
if (vuePid) {
parentVm = findVmByVueId(this.$vm, vuePid)
}
if (!parentVm) {
parentVm = this.$vm
}
vueOptions.parent = parentVm
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册