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

wip(mp): mp-kuaishou

上级 370c4aaa
......@@ -171,6 +171,7 @@ declare namespace UniApp {
'mp-toutiao'?: PagesJsonPageStyle
'mp-weixin'?: PagesJsonPageStyle
'mp-kuaishou'?: PagesJsonPageStyle
'mp-lark'?: PagesJsonPageStyle
'quickapp-webview'?: PagesJsonPageStyle
'quickapp-webview-huawei'?: PagesJsonPageStyle
'quickapp-webview-union'?: PagesJsonPageStyle
......
......@@ -59,10 +59,14 @@ function parsePagesJson(
) {
nvuePages.push(pagePath)
}
const windowOptions: PageWindowOptions = {}
if (platform === 'mp-baidu') {
// 仅百度小程序需要页面配置 component:true
// 快手小程序反而不能配置 component:true,故不能统一添加,目前硬编码处理
windowOptions.component = true
}
pageJsons[pagePath] = extend(
{
component: true,
},
windowOptions,
parseWindowOptions(style, platform, windowOptionsMap) as PageWindowOptions
)
}
......
......@@ -21,7 +21,7 @@ type Style = 'v2' | string
type RestartStrategy = 'homePage' | 'homePageAndLatestPage' | string
export interface PageWindowOptions extends ShareWindowOptions {
component: true // 百度小程序页面必须配置component: true
component?: true // 百度小程序页面必须配置component: true
disableScroll?: boolean // false
usingComponents?: UsingComponents
initialRenderingCache?: 'static' | string
......
......@@ -4,6 +4,12 @@ import { LINEFEED } from '@dcloudio/uni-shared'
import { normalizeMiniProgramFilename } from '../utils'
export interface MiniProgramCompilerOptions {
/**
* 需要延迟渲染的组件,通常是某个组件的某个事件会立刻触发,需要延迟到首次 render 之后,比如微信 editor 的 ready 事件,快手 switch 的 change
*/
lazyElement?: {
[name: string]: string[]
}
event?: {
format(
name: string,
......
......@@ -8,6 +8,15 @@ export * from './transformPageHead'
export * from './transformComponent'
export * from './transformEvent'
export * from './transformTag'
export {
ATTR_DATASET_EVENT_OPTS,
createTransformOn,
defaultMatch as matchTransformOn,
} from './vOn'
export {
createTransformModel,
defaultMatch as matchTransformModel,
} from './vModel'
export const transformMatchMedia = createTransformTag({
'match-media': 'uni-match-media',
......
import {
ComponentNode,
DirectiveNode,
DirectiveTransform,
ElementNode,
SimpleExpressionNode,
TransformContext,
} from '@vue/compiler-core'
import { isUserComponent } from '../utils'
import { addEventOpts, createCustomEventExpr } from './vOn'
export function defaultMatch(node: ElementNode, context: TransformContext) {
return isUserComponent(node, context)
}
interface CreateTransformModelOptions {
match: typeof defaultMatch
}
/**
* 百度、快手小程序的自定义组件,不支持动态事件绑定,故 v-model 也需要调整
* @param baseTransformModel
* @returns
*/
export function createTransformModel(
baseTransformModel: DirectiveTransform,
{ match }: CreateTransformModelOptions = {
match: defaultMatch,
}
): DirectiveTransform {
return (dir, node, context, augmentor) => {
const res = baseTransformModel(dir, node, context, augmentor)
if (!match(node, context)) {
return res
}
const props = res.props as unknown as DirectiveNode[]
if (props[1]) {
// input,textarea 的 v-model 事件可能会被合并到已有的 input 中
const { arg, exp } = props[1]
addEventOpts(
(arg as SimpleExpressionNode).content,
exp as SimpleExpressionNode,
node as ComponentNode
)
props[1].exp = createCustomEventExpr()
}
return res
}
}
import {
ExpressionNode,
DirectiveNode,
findProp,
isStaticExp,
NodeTypes,
locStub,
createSimpleExpression,
createCompoundExpression,
CompoundExpressionNode,
DirectiveTransform,
ElementNode,
TransformContext,
ElementTypes,
} from '@vue/compiler-core'
import { isUserComponent } from '../utils'
export function defaultMatch(
name: string,
node: ElementNode,
context: TransformContext
) {
return isCustomEvent(name) && isUserComponent(node, context)
}
interface CreateTransformOnOptions {
match: typeof defaultMatch
}
/**
* 百度、快手小程序的自定义组件,不支持动态事件绑定,故转换为静态事件 + dataset
* @param baseTransformOn
* @returns
*/
export function createTransformOn(
baseTransformOn: DirectiveTransform,
{ match }: CreateTransformOnOptions = {
match: defaultMatch,
}
): DirectiveTransform {
return (dir, node, context, augmentor) => {
const res = baseTransformOn(dir, node, context, augmentor)
const { name, arg, exp } = dir
if (name !== 'on' || !arg || !exp || !isStaticExp(arg)) {
return res
}
if (!match(arg.content, node, context)) {
return res
}
const value = res.props[0].value as ExpressionNode
res.props[0].value = createCustomEventExpr()
addEventOpts(arg.content, value, node)
return res
}
}
export function createCustomEventExpr() {
return createSimpleExpression('__e', true)
}
export function addEventOpts(
event: string,
value: ExpressionNode,
node: ElementNode
) {
const attrName =
node.tagType === ElementTypes.COMPONENT
? ATTR_DATA_EVENT_OPTS
: ATTR_DATASET_EVENT_OPTS
const opts = findProp(node, attrName, true) as DirectiveNode
if (!opts) {
node.props.push(createDataEventOptsProp(attrName, event, value))
} else {
const children = (opts.exp as CompoundExpressionNode).children
children.splice(
children.length - 2,
0,
createDataEventOptsProperty(event, value)
)
}
}
const ATTR_DATA_EVENT_OPTS = 'eO'
export const ATTR_DATASET_EVENT_OPTS = 'data-e-o'
function createDataEventOptsProperty(event: string, exp: ExpressionNode) {
return createCompoundExpression([`'${event}'`, ': ', exp, ','])
}
function createDataEventOptsProp(
name: string,
event: string,
exp: ExpressionNode
): DirectiveNode {
return {
type: NodeTypes.DIRECTIVE,
name: 'bind',
loc: locStub,
modifiers: [],
arg: createSimpleExpression(name, true),
exp: createCompoundExpression([
'{',
createDataEventOptsProperty(event, exp),
'}',
]),
}
}
const builtInEvents = [
'__l', // 快手使用了该事件
'tap',
'longtap',
'longpress',
'touchstart',
'touchmove',
'touchcancel',
'touchend',
'touchforcechange',
'transitionend',
'animationstart',
'animationiteration',
'animationend',
]
function isCustomEvent(name: string) {
return !builtInEvents.includes(name)
}
......@@ -5,7 +5,6 @@ var path = require('path');
var uniShared = require('@dcloudio/uni-shared');
var uniCliShared = require('@dcloudio/uni-cli-shared');
var uniMpCompiler = require('@dcloudio/uni-mp-compiler');
var compilerCore = require('@vue/compiler-core');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
......@@ -57,97 +56,14 @@ const transformFor = (node, context) => {
};
/**
* 百度小程序的自定义组件,不支持动态事件绑定,故转换为静态事件 + dataset
* @param dir
* @param node
* @param context
* @param augmentor
* @returns
* 百度小程序的自定义组件,不支持动态事件绑定
*/
const transformOn = (dir, node, context, augmentor) => {
const res = uniMpCompiler.transformOn(dir, node, context, augmentor);
const { name, arg, exp } = dir;
if (name !== 'on' ||
!arg ||
!exp ||
!compilerCore.isStaticExp(arg) ||
!isCustomEvent(arg.content) ||
!uniCliShared.isUserComponent(node, context)) {
return res;
}
const value = res.props[0].value;
res.props[0].value = createCustomEventExpr();
addEventOpts(arg.content, value, node);
return res;
};
function createCustomEventExpr() {
return compilerCore.createSimpleExpression('__e', true);
}
function addEventOpts(event, value, node) {
const opts = compilerCore.findProp(node, ATTR_DATA_EVENT_OPTS, true);
if (!opts) {
node.props.push(createDataEventOptsProp(event, value));
}
else {
const children = opts.exp.children;
children.splice(children.length - 2, 0, createDataEventOptsProperty(event, value));
}
}
const ATTR_DATA_EVENT_OPTS = 'eO';
function createDataEventOptsProperty(event, exp) {
return compilerCore.createCompoundExpression([`'${event}'`, ': ', exp, ',']);
}
function createDataEventOptsProp(event, exp) {
return {
type: 7 /* DIRECTIVE */,
name: 'bind',
loc: compilerCore.locStub,
modifiers: [],
arg: compilerCore.createSimpleExpression(ATTR_DATA_EVENT_OPTS, true),
exp: compilerCore.createCompoundExpression([
'{',
createDataEventOptsProperty(event, exp),
'}',
]),
};
}
const builtInEvents = [
'tap',
'longtap',
'longpress',
'touchstart',
'touchmove',
'touchcancel',
'touchend',
'touchforcechange',
'transitionend',
'animationstart',
'animationiteration',
'animationend',
];
function isCustomEvent(name) {
return !builtInEvents.includes(name);
}
const transformOn = uniCliShared.createTransformOn(uniMpCompiler.transformOn);
/**
* 百度小程序的自定义组件,不支持动态事件绑定,故 v-model 也需要调整
* @param dir
* @param node
* @param context
* @param augmentor
* @returns
*/
const transformModel = (dir, node, context, augmentor) => {
const res = uniMpCompiler.transformModel(dir, node, context, augmentor);
const props = res.props;
if (props.length < 2 || !uniCliShared.isUserComponent(node, context)) {
return res;
}
const { arg, exp } = props[1];
addEventOpts(arg.content, exp, node);
props[1].exp = createCustomEventExpr();
return res;
};
const transformModel = uniCliShared.createTransformModel(uniMpCompiler.transformModel);
const nodeTransforms = [uniCliShared.transformRef, transformFor, uniCliShared.transformMatchMedia];
const directiveTransforms = {
......
......@@ -132,6 +132,7 @@ function createEmitFn(oldEmit, ctx) {
const scope = ctx.$scope;
if (scope && event) {
const detail = { __args__: args };
// 百度小程序,快手小程序,自定义组件不能绑定动态事件
{
detail.__ins__ = scope;
}
......@@ -406,6 +407,32 @@ function findVmByVueId(instance, vuePid) {
return parentVm;
}
}
}
const EVENT_OPTS = 'eO';
/**
* 需要搭配:
* ./componentInstance/index.ts:24 triggerEvent 时传递 __ins__
* ./componentProps.ts:49 增加 properties eO
* @param this
* @param event
* @returns
*/
function handleEvent(event) {
const { type, target: { dataset }, detail: { __ins__ }, } = event;
let methodName = type;
// 快手小程序的 __l 方法也会走此处逻辑,但没有 __ins__
if (__ins__) {
// 自定义事件,通过 triggerEvent 传递 __ins__
methodName = (__ins__.properties[EVENT_OPTS] || {})[type];
}
else if (dataset && dataset[EVENT_OPTS]) {
// 快手小程序 input 等内置组件的 input 事件也会走此逻辑,所以从 dataset 中读取
methodName = dataset[EVENT_OPTS][type];
}
if (!this[methodName]) {
return console.warn(type + ' not found');
}
this[methodName](event);
}
const PROP_TYPES = [String, Number, Boolean, Object, Array, null];
......@@ -890,15 +917,7 @@ function parse$1(componentOptions) {
};
delete methods.__l;
// 百度小程序自定义组件,不支持绑定动态事件,故由 __e 分发
methods.__e = handleCustomEvent;
}
function handleCustomEvent(event) {
const { type, detail: { __ins__ }, } = event;
const methodName = (__ins__.properties.eO || {})[type];
if (!methodName) {
return console.warn(type + ' not found');
}
this[methodName](event);
methods.__e = handleEvent;
}
var parseComponentOptions = /*#__PURE__*/Object.freeze({
......
import { isUserComponent } from '@dcloudio/uni-cli-shared'
import {
DirectiveNode,
DirectiveTransform,
SimpleExpressionNode,
transformModel as baseTransformModel,
} from '@dcloudio/uni-mp-compiler'
import { ComponentNode } from '@vue/compiler-core'
import { addEventOpts, createCustomEventExpr } from './vOn'
import { createTransformModel } from '@dcloudio/uni-cli-shared'
import { transformModel as baseTransformModel } from '@dcloudio/uni-mp-compiler'
/**
* 百度小程序的自定义组件,不支持动态事件绑定,故 v-model 也需要调整
* @param dir
* @param node
* @param context
* @param augmentor
* @returns
*/
export const transformModel: DirectiveTransform = (
dir,
node,
context,
augmentor
) => {
const res = baseTransformModel(dir, node, context, augmentor)
const props = res.props as unknown as DirectiveNode[]
if (props.length < 2 || !isUserComponent(node, context)) {
return res
}
const { arg, exp } = props[1]
addEventOpts(
(arg as SimpleExpressionNode).content,
exp as SimpleExpressionNode,
node as ComponentNode
)
props[1].exp = createCustomEventExpr()
return res
}
export const transformModel = createTransformModel(baseTransformModel)
import { isUserComponent } from '@dcloudio/uni-cli-shared'
import {
DirectiveTransform,
transformOn as baseTransformOn,
} from '@dcloudio/uni-mp-compiler'
import {
ExpressionNode,
DirectiveNode,
findProp,
isStaticExp,
NodeTypes,
locStub,
createSimpleExpression,
createCompoundExpression,
CompoundExpressionNode,
ComponentNode,
} from '@vue/compiler-core'
import { createTransformOn } from '@dcloudio/uni-cli-shared'
import { transformOn as baseTransformOn } from '@dcloudio/uni-mp-compiler'
/**
* 百度小程序的自定义组件,不支持动态事件绑定,故转换为静态事件 + dataset
* @param dir
* @param node
* @param context
* @param augmentor
* @returns
* 百度小程序的自定义组件,不支持动态事件绑定
*/
export const transformOn: DirectiveTransform = (
dir,
node,
context,
augmentor
) => {
const res = baseTransformOn(dir, node, context, augmentor)
const { name, arg, exp } = dir
if (
name !== 'on' ||
!arg ||
!exp ||
!isStaticExp(arg) ||
!isCustomEvent(arg.content) ||
!isUserComponent(node, context)
) {
return res
}
const value = res.props[0].value as ExpressionNode
res.props[0].value = createCustomEventExpr()
addEventOpts(arg.content, value, node)
return res
}
export function createCustomEventExpr() {
return createSimpleExpression('__e', true)
}
export function addEventOpts(
event: string,
value: ExpressionNode,
node: ComponentNode
) {
const opts = findProp(node, ATTR_DATA_EVENT_OPTS, true) as DirectiveNode
if (!opts) {
node.props.push(createDataEventOptsProp(event, value))
} else {
const children = (opts.exp as CompoundExpressionNode).children
children.splice(
children.length - 2,
0,
createDataEventOptsProperty(event, value)
)
}
}
const ATTR_DATA_EVENT_OPTS = 'eO'
function createDataEventOptsProperty(event: string, exp: ExpressionNode) {
return createCompoundExpression([`'${event}'`, ': ', exp, ','])
}
function createDataEventOptsProp(
event: string,
exp: ExpressionNode
): DirectiveNode {
return {
type: NodeTypes.DIRECTIVE,
name: 'bind',
loc: locStub,
modifiers: [],
arg: createSimpleExpression(ATTR_DATA_EVENT_OPTS, true),
exp: createCompoundExpression([
'{',
createDataEventOptsProperty(event, exp),
'}',
]),
}
}
const builtInEvents = [
'tap',
'longtap',
'longpress',
'touchstart',
'touchmove',
'touchcancel',
'touchend',
'touchforcechange',
'transitionend',
'animationstart',
'animationiteration',
'animationend',
]
function isCustomEvent(name: string) {
return !builtInEvents.includes(name)
}
export const transformOn = createTransformOn(baseTransformOn)
......@@ -4,12 +4,13 @@ import {
MPComponentInstance,
MPComponentOptions,
initMocks,
handleEvent,
} from '@dcloudio/uni-mp-core'
import { ON_LOAD, ON_SHOW } from '@dcloudio/uni-shared'
import {
fixSetDataStart,
fixSetDataEnd,
} from '../../../uni-mp-weixin/src/runtime/fixSetData'
} from '@dcloudio/uni-mp-weixin/src/runtime/fixSetData'
export { handleLink, initLifetimes } from '@dcloudio/uni-mp-weixin'
......@@ -84,25 +85,5 @@ export function parse(componentOptions: MPComponentOptions) {
}
delete methods.__l
// 百度小程序自定义组件,不支持绑定动态事件,故由 __e 分发
methods.__e = handleCustomEvent
}
function handleCustomEvent(
this: MPComponentInstance,
event: {
type: string
detail: {
__ins__: MPComponentInstance & { eO: Record<string, string> }
}
}
) {
const {
type,
detail: { __ins__ },
} = event
const methodName = (__ins__.properties.eO || {})[type]
if (!methodName) {
return console.warn(type + ' not found')
}
;(this as any)[methodName](event)
methods.__e = handleEvent
}
......@@ -2,7 +2,6 @@ import { ElementNode } from '@vue/compiler-core'
import { compile } from '../src'
import { MPErrorCodes } from '../src/errors'
import { CompilerOptions } from '../src/options'
import { assert } from './testUtils'
function parseWithVOn(template: string, options: CompilerOptions = {}) {
const { ast } = compile(template, {
......@@ -18,22 +17,6 @@ function parseWithVOn(template: string, options: CompilerOptions = {}) {
}
describe('compiler(mp): transform v-on', () => {
test('lazy element', () => {
assert(
`<editor/>`,
`<editor/>`,
`(_ctx, _cache) => {
return {}
}`
)
assert(
`<editor @ready="ready"/>`,
`<block wx:if="{{r0}}"><editor bindready="{{a}}"/></block>`,
`(_ctx, _cache) => {
return { a: _o(_ctx.ready) }
}`
)
})
test('should error if dynamic event', () => {
const onError = jest.fn()
parseWithVOn(`<div v-on:[event]="onClick" />`, { onError })
......
......@@ -93,6 +93,7 @@ export function baseCompile(template: string, options: CompilerOptions = {}) {
emitFile,
event,
slot,
lazyElement,
} = options.miniProgram
genTemplate(ast, {
class: clazz,
......@@ -102,6 +103,7 @@ export function baseCompile(template: string, options: CompilerOptions = {}) {
emitFile,
event,
slot,
lazyElement,
})
}
......
......@@ -29,6 +29,7 @@ interface TemplateCodegenContext {
scopeId?: string | null
event: MiniProgramCompilerOptions['event']
slot: MiniProgramCompilerOptions['slot']
lazyElement: MiniProgramCompilerOptions['lazyElement']
push(code: string): void
}
......@@ -41,6 +42,7 @@ export function generate(
emitFile,
filename,
directive,
lazyElement,
}: TemplateCodegenOptions
) {
const context: TemplateCodegenContext = {
......@@ -49,6 +51,7 @@ export function generate(
code: '',
scopeId,
directive,
lazyElement,
push(code) {
context.code += code
},
......@@ -79,7 +82,7 @@ export function genNode(
return genComponent(node, context)
} else if (node.tagType === ElementTypes.TEMPLATE) {
return genTemplate(node, context)
} else if (isLazyElement(node)) {
} else if (isLazyElement(node, context)) {
return genLazyElement(node, context)
}
return genElement(node, context)
......@@ -189,12 +192,11 @@ function genComponent(node: ComponentNode, context: TemplateCodegenContext) {
return genElement(node, context)
}
const lazyElementMap: Record<string, string[]> = {
editor: ['ready'],
}
function isLazyElement(node: ElementNode) {
const events = lazyElementMap[node.tag]
function isLazyElement(node: ElementNode, context: TemplateCodegenContext) {
if (!context.lazyElement) {
return false
}
const events = context.lazyElement[node.tag]
return (
events &&
node.props.some(
......
import { camelize } from '@vue/shared'
import { camelize, isString, isSymbol } from '@vue/shared'
import {
Property,
transformModel as baseTransform,
......@@ -18,6 +18,7 @@ import { DOMErrorCodes, createDOMCompilerError } from '@vue/compiler-dom'
import {
createBindDirectiveNode,
createOnDirectiveNode,
ATTR_DATASET_EVENT_OPTS,
} from '@dcloudio/uni-cli-shared'
import { V_ON } from '../runtimeHelpers'
import { genExpr } from '../codegen'
......@@ -103,16 +104,100 @@ function transformElementVModel(
},
})
if (dirs.length === 2) {
const inputDir = findInputDirectiveNode(node.props)
if (inputDir && inputDir.exp) {
// 合并到已有的 input 事件中
inputDir.exp = combineVOn(dirs[1].exp!, inputDir.exp, context)
// 快手小程序的 input v-model 被转换到 data-e-o 中,补充到 data-e-o 中
const inputExp = findDatasetEventOpts(node)
if (inputExp) {
inputExp.children[2] = combineVOn(
dirs[1].exp!,
inputExp.children[2] as ExpressionNode,
context
)
dirs.length = 1
} else {
const inputDir = findInputDirectiveNode(node.props)
if (inputDir && inputDir.exp) {
// 合并到已有的 input 事件中
inputDir.exp = combineVOn(dirs[1].exp!, inputDir.exp, context)
dirs.length = 1
}
}
}
return { props: dirs }
}
/**
* {
* "type": 7,
* "name": "bind",
* "loc": {},
* "modifiers": [],
* "arg": {
* "type": 4,
* "loc": {},
* "content": "data-e-o",
* "isStatic": true,
* "constType": 3
* },
* "exp": {
* "type": 8,
* "loc": {},
* "children": ["{", {
* "type": 8,
* "loc": {},
* "children": ["'input'", ": ", {
* "type": 8,
* "loc": {},
* "children": ["_o(", {
* "type": 4,
* "content": "_ctx.input",
* "isStatic": false,
* "constType": 0,
* "loc": {}
* }, ")"]
* }, ","]
* }, "}"]
* }
* }
* @param node
* @returns
*/
function findDatasetEventOpts(node: ElementNode) {
const eventOptsProp = findProp(
node,
ATTR_DATASET_EVENT_OPTS,
true,
false
) as DirectiveNode
if (!eventOptsProp) {
return
}
const { exp } = eventOptsProp
if (exp?.type !== NodeTypes.COMPOUND_EXPRESSION) {
return
}
for (let i = 0; i < exp.children.length; i++) {
const childExp = exp.children[i]
if (isSymbol(childExp) || isString(childExp)) {
continue
}
if (childExp.type !== NodeTypes.COMPOUND_EXPRESSION) {
continue
}
if (childExp.children[0] !== `'input'`) {
continue
}
const inputExp = childExp.children[2]
if (
isSymbol(inputExp) ||
isString(inputExp) ||
inputExp.type !== NodeTypes.COMPOUND_EXPRESSION
) {
continue
}
return childExp
}
}
function parseVOn(exp: ExpressionNode, context: TransformContext) {
return genExpr(exp).slice(context.helperString(V_ON).length + 1, -1)
}
......
......@@ -29,6 +29,7 @@ export {
initVueIds,
initWxsCallMethods,
findVmByVueId,
handleEvent,
} from './runtime/util'
// protocols
......
......@@ -20,7 +20,8 @@ function createEmitFn(oldEmit: Function, ctx: Record<string, any>) {
const scope = ctx.$scope as MPComponentInstance
if (scope && event) {
const detail: Record<string, any> = { __args__: args }
if (__PLATFORM__ === 'mp-baidu') {
// 百度小程序,快手小程序,自定义组件不能绑定动态事件
if (__PLATFORM__ === 'mp-baidu' || __PLATFORM__ === 'mp-kuaishou') {
detail.__ins__ = scope
}
scope.triggerEvent(event, detail)
......
......@@ -46,7 +46,7 @@ function normalizePropType(type: unknown, defaultValue: unknown) {
function initDefaultProps(isBehavior: boolean = false) {
const properties: Component.PropertyOption = {}
if (!isBehavior) {
if (__PLATFORM__ === 'mp-baidu') {
if (__PLATFORM__ === 'mp-baidu' || __PLATFORM__ === 'mp-kuaishou') {
// 百度小程序自定义组件不支持绑定动态事件,动态dataset,故通过props传递事件信息
// event-opts
properties.eO = {
......@@ -58,12 +58,6 @@ function initDefaultProps(isBehavior: boolean = false) {
type: null, // 均不指定类型,避免 property received type-uncompatible value 警告
value: '',
}
if (__PLATFORM__ === 'mp-toutiao') {
// 用于字节跳动小程序模拟抽象节点
properties.generic = {
type: Object,
}
}
// 小程序不能直接定义 $slots 的 props,所以通过 vueSlots 转换到 $slots
properties.vS = {
type: null,
......
......@@ -124,3 +124,45 @@ export function findVmByVueId(
}
}
}
const EVENT_OPTS = 'eO'
/**
* 需要搭配:
* ./componentInstance/index.ts:24 triggerEvent 时传递 __ins__
* ./componentProps.ts:49 增加 properties eO
* @param this
* @param event
* @returns
*/
export function handleEvent(
this: MPComponentInstance,
event: {
type: string
target: {
dataset: Record<string, any>
}
detail: {
__ins__: MPComponentInstance & { eO: Record<string, string> }
}
}
) {
const {
type,
target: { dataset },
detail: { __ins__ },
} = event
let methodName: string = type
// 快手小程序的 __l 方法也会走此处逻辑,但没有 __ins__
if (__ins__) {
// 自定义事件,通过 triggerEvent 传递 __ins__
methodName = (__ins__.properties[EVENT_OPTS] || {})[type]
} else if (dataset && dataset[EVENT_OPTS]) {
// 快手小程序 input 等内置组件的 input 事件也会走此逻辑,所以从 dataset 中读取
methodName = dataset[EVENT_OPTS][type]
}
if (!(this as any)[methodName]) {
return console.warn(type + ' not found')
}
;(this as any)[methodName](event)
}
import { assert } from './testUtils'
describe('mp-kuaishou: transform component', () => {
test('lazy element', () => {
assert(
`<switch/>`,
`<switch/>`,
`(_ctx, _cache) => {
return {}
}`
)
assert(
`<switch @change="change"/>`,
`<block ks:if="{{r0}}"><switch bindchange="{{a}}"/></block>`,
`(_ctx, _cache) => {
return { a: _o(_ctx.change) }
}`
)
})
})
import { isNativeTag } from '@dcloudio/uni-shared'
import { compile, CompilerOptions } from '@dcloudio/uni-mp-compiler'
import { compilerOptions, miniProgram } from '../src/compiler/options'
export function assert(
template: string,
templateCode: string,
renderCode: string,
options: CompilerOptions = {}
) {
const res = compile(template, {
mode: 'module',
filename: 'foo.vue',
prefixIdentifiers: true,
inline: true,
isNativeTag,
generatorOpts: {
concise: true,
},
miniProgram: {
...miniProgram,
emitFile({ source }) {
// console.log(source)
if (!options.onError) {
expect(source).toBe(templateCode)
}
return ''
},
},
...compilerOptions,
...options,
})
if (!options.onError) {
expect(res.code).toBe(renderCode)
}
}
import { assert } from './testUtils'
describe('mp-kuaishou: transform v-model', () => {
test(`component v-model`, () => {
assert(
`<Comp v-model="model" />`,
`<comp v-i="2a9ec0b0-0" bind:__l="__l" eO="{{a}}" modelValue="{{b}}" bindupdateModelValue="__e"/>`,
`(_ctx, _cache) => {
return { a: { 'updateModelValue': _o($event => _ctx.model = $event) }, b: _ctx.model }
}`
)
})
test(`component v-model with cache`, () => {
assert(
`<Comp v-model="model" />`,
`<comp v-i="2a9ec0b0-0" bind:__l="__l" eO="{{a}}" modelValue="{{b}}" bindupdateModelValue="__e"/>`,
`(_ctx, _cache) => {
return { a: { 'updateModelValue': _o($event => _ctx.model = $event) }, b: _ctx.model }
}`,
{
cacheHandlers: true,
}
)
})
test(`input,textarea v-model`, () => {
assert(
`<input v-model="model" />`,
`<input data-e-o="{{a}}" value="{{b}}" bindinput="__e"/>`,
`(_ctx, _cache) => {
return { a: { 'input': _o($event => _ctx.model = $event.detail.value) }, b: _ctx.model }
}`
)
assert(
`<textarea v-model="model" />`,
`<textarea data-e-o="{{a}}" value="{{b}}" bindinput="__e"/>`,
`(_ctx, _cache) => {
return { a: { 'input': _o($event => _ctx.model = $event.detail.value) }, b: _ctx.model }
}`
)
})
test(`input v-model + v-on`, () => {
assert(
`<input @input="input" v-model="model" />`,
`<input bindinput="__e" data-e-o="{{a}}" value="{{b}}"/>`,
`(_ctx, _cache) => {
return { a: { 'input': _o([$event => _ctx.model = $event.detail.value, _ctx.input]) }, b: _ctx.model }
}`
)
assert(
`<input v-model="model" @input="input" />`,
`<input bindinput="__e" data-e-o="{{a}}" value="{{b}}"/>`,
`(_ctx, _cache) => {
return { a: { 'input': _o([$event => _ctx.model = $event.detail.value, _ctx.input]) }, b: _ctx.model }
}`
)
})
})
import { assert } from './testUtils'
describe('mp-kuaishou: transform v-on', () => {
describe('input,textarea', () => {
test(`input`, () => {
assert(
`<input @input="input"/>`,
`<input bindinput="__e" data-e-o="{{a}}"/>`,
`(_ctx, _cache) => {
return { a: { 'input': _o(_ctx.input) } }
}`
)
})
test(`textarea`, () => {
assert(
`<textarea @input="input"></textarea>`,
`<textarea bindinput="__e" data-e-o="{{a}}"></textarea>`,
`(_ctx, _cache) => {
return { a: { 'input': _o(_ctx.input) } }
}`
)
})
})
describe('component', () => {
test(`built-in event`, () => {
assert(
`<custom @tap="tap"/>`,
`<custom bindtap="{{a}}" v-i="2a9ec0b0-0" bind:__l="__l"/>`,
`(_ctx, _cache) => {
return { a: _o(_ctx.tap) }
}`
)
})
test(`custom event`, () => {
assert(
`<custom @click="click"/>`,
`<custom bindclick="__e" v-i="2a9ec0b0-0" bind:__l="__l" eO="{{a}}"/>`,
`(_ctx, _cache) => {
return { a: { 'click': _o(_ctx.click) } }
}`
)
}),
test(`multi custom event`, () => {
assert(
`<custom @unmount="unmount" @custom-mount="mount();created();"/>`,
`<custom bindunmount="__e" bind:custom-mount="__e" v-i="2a9ec0b0-0" bind:__l="__l" eO="{{a}}"/>`,
`(_ctx, _cache) => {
return { a: { 'custom-mount': _o($event => { _ctx.mount(); _ctx.created(); }), 'unmount': _o(_ctx.unmount) } }
}`
)
})
})
})
{
"input": {
"src/runtime/index.ts": "dist/uni.mp.esm.js",
"src/api/index.ts": "dist/uni.api.esm.js"
},
"alias": {
"entries": [
{
"find": "@dcloudio/uni-platform",
"replacement": "packages/uni-mp-kuaishou/src/platform/index.ts"
},
{
"find": "@dcloudio/uni-mp-platform",
"replacement": "packages/uni-mp-core/src/platform/index.ts"
}
[
{
"input": {
"src/compiler/index.ts": "dist/uni.compiler.js"
},
"output": {
"format": "cjs"
},
"external": [
"@vue/compiler-core",
"@dcloudio/uni-shared",
"@dcloudio/uni-cli-shared",
"@dcloudio/uni-mp-vite",
"@dcloudio/uni-mp-compiler"
]
},
"replacements": {
"__GLOBAL__": "ks",
"__PLATFORM__": "\"mp-kuaishou\"",
"__PLATFORM_TITLE__": "快手小程序"
},
"external": ["@dcloudio/uni-i18n", "@vue/shared", "vue"]
}
{
"input": {
"src/runtime/index.ts": "dist/uni.mp.esm.js",
"src/api/index.ts": "dist/uni.api.esm.js"
},
"alias": {
"entries": [
{
"find": "@dcloudio/uni-platform",
"replacement": "packages/uni-mp-kuaishou/src/platform/index.ts"
},
{
"find": "@dcloudio/uni-mp-platform",
"replacement": "packages/uni-mp-core/src/platform/index.ts"
}
]
},
"replacements": {
"__GLOBAL__": "ks",
"__PLATFORM__": "\"mp-kuaishou\"",
"__PLATFORM_TITLE__": "快手小程序"
},
"external": ["@dcloudio/uni-i18n", "@vue/shared", "vue"]
}
]
'use strict';
var initMiniProgramPlugin = require('@dcloudio/uni-mp-vite');
var path = require('path');
var uniShared = require('@dcloudio/uni-shared');
var uniCliShared = require('@dcloudio/uni-cli-shared');
var uniMpCompiler = require('@dcloudio/uni-mp-compiler');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var initMiniProgramPlugin__default = /*#__PURE__*/_interopDefaultLegacy(initMiniProgramPlugin);
var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
var description = "项目配置文件";
var packOptions = {
ignore: [
]
};
var setting = {
urlCheck: false,
es6: true,
enhance: false,
postcss: true,
preloadBackgroundData: false,
minified: true,
newFeature: false,
coverView: true,
nodeModules: false,
autoAudits: false,
showShadowRootInWxmlPanel: true,
scopeDataCheck: false,
uglifyFileName: false,
checkInvalidKey: true,
checkSiteMap: true,
uploadWithSourceMap: true,
compileHotReLoad: false,
babelSetting: {
ignore: [
],
disablePlugins: [
],
outputPath: ""
},
useIsolateContext: true,
useCompilerModule: false,
userConfirmedUseCompilerModuleSwitch: false
};
var compileType = "miniprogram";
var libVersion = "";
var appid = "";
var projectname = "";
var debugOptions = {
hidedInDevtools: [
]
};
var scripts = {
};
var isGameTourist = false;
var simulatorPluginLibVersion = {
};
var condition = {
search: {
current: -1,
list: [
]
},
conversation: {
current: -1,
list: [
]
},
game: {
current: -1,
list: [
]
},
plugin: {
current: -1,
list: [
]
},
gamePlugin: {
current: -1,
list: [
]
},
miniprogram: {
current: -1,
list: [
]
}
};
var source = {
description: description,
packOptions: packOptions,
setting: setting,
compileType: compileType,
libVersion: libVersion,
appid: appid,
projectname: projectname,
debugOptions: debugOptions,
scripts: scripts,
isGameTourist: isGameTourist,
simulatorPluginLibVersion: simulatorPluginLibVersion,
condition: condition
};
/**
* 快手小程序的自定义组件,不支持动态事件绑定
*/
const transformOn = uniCliShared.createTransformOn(uniMpCompiler.transformOn, {
match: (name, node, context) => {
if (name === 'input' && (node.tag === 'input' || node.tag === 'textarea')) {
return true;
}
return uniCliShared.matchTransformOn(name, node, context);
},
});
/**
* 快手小程序的自定义组件,不支持动态事件绑定,故 v-model 也需要调整,其中 input、textarea 也不支持
*/
const transformModel = uniCliShared.createTransformModel(uniMpCompiler.transformModel, {
match: (node, context) => {
if (node.tag === 'input' || node.tag === 'textarea') {
return true;
}
return uniCliShared.matchTransformModel(node, context);
},
});
const nodeTransforms = [uniCliShared.transformRef, uniCliShared.transformComponentLink];
const directiveTransforms = {
on: transformOn,
model: transformModel,
};
const compilerOptions = {
isNativeTag: uniShared.isNativeTag,
isCustomElement: uniShared.isCustomElement,
nodeTransforms,
directiveTransforms,
};
const miniProgram = {
class: {
array: false,
},
slot: {
fallbackContent: false,
dynamicSlotNames: false,
},
directive: 'ks:',
lazyElement: {
switch: ['change'],
},
};
const projectConfigFilename = 'project.config.json';
const options = {
vite: {
inject: {
uni: [path__default["default"].resolve(__dirname, 'uni.api.esm.js'), 'default'],
},
alias: {
'uni-mp-runtime': path__default["default"].resolve(__dirname, 'uni.mp.esm.js'),
},
copyOptions: {
assets: ['kscomponents'],
},
},
global: 'ks',
app: {
darkmode: false,
subpackages: true,
},
project: {
filename: projectConfigFilename,
source,
},
template: Object.assign(Object.assign({}, miniProgram), { filter: undefined, extname: '.ksml', compilerOptions }),
style: {
extname: '.css',
},
};
const uniMiniProgramKuaishouPlugin = {
name: 'vite:uni-mp-kuaishou',
config() {
return {
define: {
__VUE_CREATED_DEFERRED__: false,
},
build: {
// css 中不支持引用本地资源
assetsInlineLimit: 40 * 1024, // 40kb
},
};
},
};
var index = [uniMiniProgramKuaishouPlugin, ...initMiniProgramPlugin__default["default"](options)];
module.exports = index;
......@@ -132,6 +132,10 @@ function createEmitFn(oldEmit, ctx) {
const scope = ctx.$scope;
if (scope && event) {
const detail = { __args__: args };
// 百度小程序,快手小程序,自定义组件不能绑定动态事件
{
detail.__ins__ = scope;
}
scope.triggerEvent(event, detail);
}
return oldEmit.apply(this, [event, ...args]);
......@@ -403,6 +407,32 @@ function findVmByVueId(instance, vuePid) {
return parentVm;
}
}
}
const EVENT_OPTS = 'eO';
/**
* 需要搭配:
* ./componentInstance/index.ts:24 triggerEvent 时传递 __ins__
* ./componentProps.ts:49 增加 properties eO
* @param this
* @param event
* @returns
*/
function handleEvent(event) {
const { type, target: { dataset }, detail: { __ins__ }, } = event;
let methodName = type;
// 快手小程序的 __l 方法也会走此处逻辑,但没有 __ins__
if (__ins__) {
// 自定义事件,通过 triggerEvent 传递 __ins__
methodName = (__ins__.properties[EVENT_OPTS] || {})[type];
}
else if (dataset && dataset[EVENT_OPTS]) {
// 快手小程序 input 等内置组件的 input 事件也会走此逻辑,所以从 dataset 中读取
methodName = dataset[EVENT_OPTS][type];
}
if (!this[methodName]) {
return console.warn(type + ' not found');
}
this[methodName](event);
}
const PROP_TYPES = [String, Number, Boolean, Object, Array, null];
......@@ -427,6 +457,14 @@ function normalizePropType(type, defaultValue) {
function initDefaultProps(isBehavior = false) {
const properties = {};
if (!isBehavior) {
{
// 百度小程序自定义组件不支持绑定动态事件,动态dataset,故通过props传递事件信息
// event-opts
properties.eO = {
type: null,
value: '',
};
}
properties.vI = {
type: null,
value: '',
......@@ -764,12 +802,13 @@ var baseParseOptions = /*#__PURE__*/Object.freeze({
initLifetimes: initLifetimes
});
const createApp = initCreateApp();
const createPage = initCreatePage(baseParseOptions);
const createComponent$1 = initCreateComponent(baseParseOptions);
wx.createApp = global.createApp = createApp;
wx.createPage = createPage;
wx.createComponent = createComponent$1;
function parse$1(pageOptions) {
// 快手小程序自定义组件,不支持绑定动态事件,故由 __e 分发
pageOptions.methods.__e = handleEvent;
}
var parsePageOptions = extend({}, baseParseOptions, {
parse: parse$1,
});
/**
* 用于延迟调用 setData
......@@ -823,11 +862,15 @@ function parse(componentOptions) {
}
oldAttached.call(this);
};
// 快手小程序自定义组件,不支持绑定动态事件,故由 __e 分发
componentOptions.methods.__e = handleEvent;
}
var parseComponentOptions = extend({}, baseParseOptions, {
parse,
});
const createApp = initCreateApp();
const createPage = initCreatePage(parsePageOptions);
const createComponent = initCreateComponent(parseComponentOptions);
ks.EventChannel = EventChannel;
ks.createApp = global.createApp = createApp;
......
......@@ -14,7 +14,9 @@
"license": "Apache-2.0",
"uni-app": {
"name": "mp-kuaishou",
"title": "快手小程序"
"title": "快手小程序",
"apply": "mp-kuaishou",
"main": "dist/uni.compiler.js"
},
"gitHead": "7bcc3303c15141d377645a4995ce186f10ed6b78"
}
import { Plugin } from 'vite'
import initMiniProgramPlugin from '@dcloudio/uni-mp-vite'
import { options } from './options'
const uniMiniProgramKuaishouPlugin: Plugin = {
name: 'vite:uni-mp-kuaishou',
config() {
return {
define: {
__VUE_CREATED_DEFERRED__: false,
},
build: {
// css 中不支持引用本地资源
assetsInlineLimit: 40 * 1024, // 40kb
},
}
},
}
export default [uniMiniProgramKuaishouPlugin, ...initMiniProgramPlugin(options)]
import path from 'path'
import type { CompilerOptions } from '@vue/compiler-core'
import { isNativeTag, isCustomElement } from '@dcloudio/uni-shared'
import {
MiniProgramCompilerOptions,
transformComponentLink,
transformRef,
} from '@dcloudio/uni-cli-shared'
import { UniMiniProgramPluginOptions } from '@dcloudio/uni-mp-vite'
import source from './project.config.json'
import { transformOn } from './transforms/vOn'
import { transformModel } from './transforms/vModel'
const nodeTransforms = [transformRef, transformComponentLink]
const directiveTransforms = {
on: transformOn,
model: transformModel,
}
export const compilerOptions: CompilerOptions = {
isNativeTag,
isCustomElement,
nodeTransforms,
directiveTransforms,
}
export const miniProgram: MiniProgramCompilerOptions = {
class: {
array: false,
},
slot: {
fallbackContent: false,
dynamicSlotNames: false,
},
directive: 'ks:',
lazyElement: {
switch: ['change'],
},
}
const projectConfigFilename = 'project.config.json'
export const options: UniMiniProgramPluginOptions = {
vite: {
inject: {
uni: [path.resolve(__dirname, 'uni.api.esm.js'), 'default'],
},
alias: {
'uni-mp-runtime': path.resolve(__dirname, 'uni.mp.esm.js'),
},
copyOptions: {
assets: ['kscomponents'],
},
},
global: 'ks',
app: {
darkmode: false,
subpackages: true,
},
project: {
filename: projectConfigFilename,
source,
},
template: {
/* eslint-disable no-restricted-syntax */
...miniProgram,
filter: undefined,
extname: '.ksml',
compilerOptions,
},
style: {
extname: '.css',
},
}
{
"description": "项目配置文件",
"packOptions": {
"ignore": []
},
"setting": {
"urlCheck": false,
"es6": true,
"enhance": false,
"postcss": true,
"preloadBackgroundData": false,
"minified": true,
"newFeature": false,
"coverView": true,
"nodeModules": false,
"autoAudits": false,
"showShadowRootInWxmlPanel": true,
"scopeDataCheck": false,
"uglifyFileName": false,
"checkInvalidKey": true,
"checkSiteMap": true,
"uploadWithSourceMap": true,
"compileHotReLoad": false,
"babelSetting": {
"ignore": [],
"disablePlugins": [],
"outputPath": ""
},
"useIsolateContext": true,
"useCompilerModule": false,
"userConfirmedUseCompilerModuleSwitch": false
},
"compileType": "miniprogram",
"libVersion": "",
"appid": "",
"projectname": "",
"debugOptions": {
"hidedInDevtools": []
},
"scripts": {},
"isGameTourist": false,
"simulatorPluginLibVersion": {},
"condition": {
"search": {
"current": -1,
"list": []
},
"conversation": {
"current": -1,
"list": []
},
"game": {
"current": -1,
"list": []
},
"plugin": {
"current": -1,
"list": []
},
"gamePlugin": {
"current": -1,
"list": []
},
"miniprogram": {
"current": -1,
"list": []
}
}
}
import {
createTransformModel,
matchTransformModel,
} from '@dcloudio/uni-cli-shared'
import { transformModel as baseTransformModel } from '@dcloudio/uni-mp-compiler'
/**
* 快手小程序的自定义组件,不支持动态事件绑定,故 v-model 也需要调整,其中 input、textarea 也不支持
*/
export const transformModel = createTransformModel(baseTransformModel, {
match: (node, context) => {
if (node.tag === 'input' || node.tag === 'textarea') {
return true
}
return matchTransformModel(node, context)
},
})
import { createTransformOn, matchTransformOn } from '@dcloudio/uni-cli-shared'
import { transformOn as baseTransformOn } from '@dcloudio/uni-mp-compiler'
/**
* 快手小程序的自定义组件,不支持动态事件绑定
*/
export const transformOn = createTransformOn(baseTransformOn, {
match: (name, node, context) => {
if (name === 'input' && (node.tag === 'input' || node.tag === 'textarea')) {
return true
}
return matchTransformOn(name, node, context)
},
})
import { EventChannel } from '@dcloudio/uni-shared'
import { initCreateComponent } from '@dcloudio/uni-mp-core'
import { createApp, createPage } from '@dcloudio/uni-mp-weixin/src/runtime'
import {
initCreateApp,
initCreatePage,
initCreateComponent,
} from '@dcloudio/uni-mp-core'
import '@dcloudio/uni-mp-polyfill'
import parsePageOptions from './parsePageOptions'
import parseComponentOptions from './parseComponentOptions'
export { createApp, createPage } from '@dcloudio/uni-mp-weixin/src/runtime'
export const createApp = initCreateApp()
export const createPage = initCreatePage(parsePageOptions)
export const createComponent = initCreateComponent(parseComponentOptions)
;(ks as any).EventChannel = EventChannel
;(ks as any).createApp = (global as any).createApp = createApp
......
import { extend } from '@vue/shared'
import { MPComponentInstance, MPComponentOptions } from '@dcloudio/uni-mp-core'
import {
handleEvent,
MPComponentInstance,
MPComponentOptions,
} from '@dcloudio/uni-mp-core'
import * as baseParseOptions from '@dcloudio/uni-mp-weixin/src/runtime/parseOptions'
import {
fixSetDataStart,
......@@ -19,6 +23,9 @@ export function parse(componentOptions: MPComponentOptions) {
}
oldAttached!.call(this)
}
// 快手小程序自定义组件,不支持绑定动态事件,故由 __e 分发
componentOptions.methods!.__e = handleEvent
}
export default extend({}, baseParseOptions, {
......
import { extend } from '@vue/shared'
import { handleEvent, MPComponentOptions } from '@dcloudio/uni-mp-core'
import * as baseParseOptions from '@dcloudio/uni-mp-weixin/src/runtime/parseOptions'
export function parse(pageOptions: MPComponentOptions) {
// 快手小程序自定义组件,不支持绑定动态事件,故由 __e 分发
pageOptions.methods!.__e = handleEvent
}
export default extend({}, baseParseOptions, {
parse,
})
......@@ -434,12 +434,6 @@ function initDefaultProps(isBehavior = false) {
type: null,
value: '',
};
{
// 用于字节跳动小程序模拟抽象节点
properties.generic = {
type: Object,
};
}
// 小程序不能直接定义 $slots 的 props,所以通过 vueSlots 转换到 $slots
properties.vS = {
type: null,
......
......@@ -46,6 +46,7 @@ export interface UniMiniProgramPluginOptions {
event?: MiniProgramCompilerOptions['event']
class: MiniProgramCompilerOptions['class']
slot: MiniProgramCompilerOptions['slot']
lazyElement?: MiniProgramCompilerOptions['lazyElement']
filter?: {
lang: string
extname: string
......@@ -79,6 +80,7 @@ export function uniMiniProgramPlugin(
class: template.class,
filter: template.filter ? { lang: template.filter.lang } : undefined,
directive: template.directive,
lazyElement: template.lazyElement,
emitFile,
slot: template.slot,
},
......
......@@ -57,7 +57,7 @@ export function getFilterFiles(
export function getTemplateFiles(
template: UniMiniProgramPluginOptions['template']
) {
const files = findMiniProgramTemplateFiles(template.filter!.generate)
const files = findMiniProgramTemplateFiles(template.filter?.generate)
clearMiniProgramTemplateFiles()
return files
}
......
import { assert } from './testUtils'
describe('mp-baidu: transform component', () => {
describe('mp-weixin: transform component', () => {
test('lazy element', () => {
assert(
`<editor/>`,
`<editor/>`,
`(_ctx, _cache) => {
return {}
}`
)
assert(
`<editor @ready="ready"/>`,
`<block wx:if="{{r0}}"><editor bindready="{{a}}"/></block>`,
`(_ctx, _cache) => {
return { a: _o(_ctx.ready) }
}`
)
})
test(`match-media`, () => {
assert(
`<match-media/>`,
......
......@@ -16,7 +16,7 @@ var packOptions = {
]
};
var setting = {
urlCheck: true,
urlCheck: false,
es6: true,
postcss: false,
minified: false,
......@@ -76,6 +76,9 @@ const miniProgram = {
dynamicSlotNames: true,
},
directive: 'wx:',
lazyElement: {
editor: ['ready'],
},
};
const projectConfigFilename = 'project.config.json';
const options = {
......
......@@ -33,6 +33,9 @@ export const miniProgram: MiniProgramCompilerOptions = {
dynamicSlotNames: true,
},
directive: 'wx:',
lazyElement: {
editor: ['ready'],
},
}
const projectConfigFilename = 'project.config.json'
......
......@@ -4,7 +4,7 @@
"ignore": []
},
"setting": {
"urlCheck": true,
"urlCheck": false,
"es6": true,
"postcss": false,
"minified": false,
......
'use strict';
var version = "3.0.0-alpha-3021020211027001";
var version = "3.0.0-alpha-3021220211102002";
const STAT_VERSION = version;
const STAT_URL = 'https://tongji.dcloud.io/uni/stat';
......
var version = "3.0.0-alpha-3021020211027001";
var version = "3.0.0-alpha-3021220211102002";
const STAT_VERSION = version;
const STAT_URL = 'https://tongji.dcloud.io/uni/stat';
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册