Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
yangkaifeng
uni-app
提交
743c8786
U
uni-app
项目概览
yangkaifeng
/
uni-app
与 Fork 源项目一致
Fork自
DCloud / uni-app
通知
3
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
U
uni-app
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1
Issue
1
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
743c8786
编写于
12月 30, 2021
作者:
fxy060608
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
fix(mp-weixin): v-for + key + v-on (question/137217)
上级
39a907e8
变更
14
展开全部
隐藏空白更改
内联
并排
Showing
14 changed file
with
131 addition
and
22 deletion
+131
-22
packages/uni-app-plus/dist/uni-app-view.umd.js
packages/uni-app-plus/dist/uni-app-view.umd.js
+3
-3
packages/uni-cli-shared/src/mp/template.ts
packages/uni-cli-shared/src/mp/template.ts
+2
-1
packages/uni-h5/dist/uni-h5.cjs.js
packages/uni-h5/dist/uni-h5.cjs.js
+1
-1
packages/uni-h5/dist/uni-h5.es.js
packages/uni-h5/dist/uni-h5.es.js
+2
-2
packages/uni-mp-compiler/src/transforms/vModel.ts
packages/uni-mp-compiler/src/transforms/vModel.ts
+10
-3
packages/uni-mp-compiler/src/transforms/vOn.ts
packages/uni-mp-compiler/src/transforms/vOn.ts
+24
-2
packages/uni-mp-qq/dist/uni.compiler.js
packages/uni-mp-qq/dist/uni.compiler.js
+3
-0
packages/uni-mp-qq/src/compiler/options.ts
packages/uni-mp-qq/src/compiler/options.ts
+3
-0
packages/uni-mp-vue/dist/vue.runtime.esm.js
packages/uni-mp-vue/dist/vue.runtime.esm.js
+11
-4
packages/uni-mp-vue/src/helpers/index.ts
packages/uni-mp-vue/src/helpers/index.ts
+1
-1
packages/uni-mp-vue/src/helpers/vOn.ts
packages/uni-mp-vue/src/helpers/vOn.ts
+22
-5
packages/uni-mp-weixin/__tests__/vOn.spec.ts
packages/uni-mp-weixin/__tests__/vOn.spec.ts
+43
-0
packages/uni-mp-weixin/dist/uni.compiler.js
packages/uni-mp-weixin/dist/uni.compiler.js
+3
-0
packages/uni-mp-weixin/src/compiler/options.ts
packages/uni-mp-weixin/src/compiler/options.ts
+3
-0
未找到文件。
packages/uni-app-plus/dist/uni-app-view.umd.js
浏览文件 @
743c8786
此差异已折叠。
点击以展开。
packages/uni-cli-shared/src/mp/template.ts
浏览文件 @
743c8786
...
...
@@ -11,7 +11,8 @@ export interface MiniProgramCompilerOptions {
[
name
:
string
]:
{
name
:
'
on
'
|
'
bind
'
;
arg
:
string
[]
}[]
}
event
?:
{
format
(
key
?:
boolean
format
?(
name
:
string
,
opts
:
{
isCatch
?:
boolean
;
isCapture
?:
boolean
;
isComponent
?:
boolean
}
):
string
...
...
packages/uni-h5/dist/uni-h5.cjs.js
浏览文件 @
743c8786
...
...
@@ -4386,7 +4386,7 @@ var PickerView = /* @__PURE__ */ defineBuiltInComponent({
function
getItemIndex
(
vnode
)
{
let
columnVNodes
=
columnsRef
.
value
;
{
columnVNodes
=
columnVNodes
.
filter
((
ref
)
=>
typeof
ref
.
type
!==
"
symbol
"
);
columnVNodes
=
columnVNodes
.
filter
((
vnode2
)
=>
vnode2
.
type
!==
vue
.
Comment
);
}
let
index2
=
columnVNodes
.
indexOf
(
vnode
);
return
index2
!==
-
1
?
index2
:
ColumnsPreRef
.
value
.
indexOf
(
vnode
);
...
...
packages/uni-h5/dist/uni-h5.es.js
浏览文件 @
743c8786
import { withModifiers, createVNode, getCurrentInstance, ref, defineComponent, openBlock, createElementBlock, provide, computed, watch, onUnmounted, inject, onBeforeUnmount, mergeProps, injectHook, reactive, onActivated, onMounted, nextTick, onBeforeMount, withDirectives, vShow, shallowRef, watchEffect, isVNode, Fragment, markRaw, createTextVNode, onBeforeActivate, onBeforeDeactivate, createBlock, renderList, onDeactivated, createApp, Transition, effectScope, withCtx, KeepAlive, resolveDynamicComponent, createElementVNode, normalizeStyle, renderSlot } from "vue";
import { withModifiers, createVNode, getCurrentInstance, ref, defineComponent, openBlock, createElementBlock, provide, computed, watch, onUnmounted, inject, onBeforeUnmount, mergeProps, injectHook, reactive, onActivated, onMounted, nextTick, onBeforeMount, withDirectives, vShow, shallowRef, watchEffect, isVNode, Fragment, markRaw,
Comment,
createTextVNode, onBeforeActivate, onBeforeDeactivate, createBlock, renderList, onDeactivated, createApp, Transition, effectScope, withCtx, KeepAlive, resolveDynamicComponent, createElementVNode, normalizeStyle, renderSlot } from "vue";
import { isString, extend, stringifyStyle, parseStringStyle, isPlainObject, isFunction, capitalize, camelize, isArray, hasOwn, isObject, toRawType, makeMap as makeMap$1, isPromise, hyphenate, invokeArrayFns as invokeArrayFns$1 } from "@vue/shared";
import { once, UNI_STORAGE_LOCALE, I18N_JSON_DELIMITERS, passive, initCustomDataset, resolveComponentInstance, addLeadingSlash, invokeArrayFns, resolveOwnerVm, resolveOwnerEl, ON_WXS_INVOKE_CALL_METHOD, normalizeTarget, ON_RESIZE, ON_APP_ENTER_FOREGROUND, ON_APP_ENTER_BACKGROUND, ON_SHOW, ON_HIDE, ON_PAGE_SCROLL, ON_REACH_BOTTOM, EventChannel, SCHEME_RE, DATA_RE, getCustomDataset, LINEFEED, ON_ERROR, callOptions, ON_LAUNCH, PRIMARY_COLOR, removeLeadingSlash, getLen, debounce, ON_LOAD, UniLifecycleHooks, NAVBAR_HEIGHT, parseQuery, ON_UNLOAD, ON_REACH_BOTTOM_DISTANCE, decodedQuery, WEB_INVOKE_APPSERVICE, ON_WEB_INVOKE_APP_SERVICE, updateElementStyle, ON_BACK_PRESS, parseUrl, addFont, scrollTo, RESPONSIVE_MIN_WIDTH, formatDateTime, ON_NAVIGATION_BAR_BUTTON_TAP, ON_NAVIGATION_BAR_SEARCH_INPUT_CLICKED, ON_NAVIGATION_BAR_SEARCH_INPUT_FOCUS_CHANGED, ON_NAVIGATION_BAR_SEARCH_INPUT_CHANGED, ON_NAVIGATION_BAR_SEARCH_INPUT_CONFIRMED, ON_PULL_DOWN_REFRESH } from "@dcloudio/uni-shared";
import { initVueI18n, isI18nStr, LOCALE_EN, LOCALE_ES, LOCALE_FR, LOCALE_ZH_HANS, LOCALE_ZH_HANT } from "@dcloudio/uni-i18n";
...
...
@@ -10125,7 +10125,7 @@ var PickerView = /* @__PURE__ */ defineBuiltInComponent({
function getItemIndex(vnode) {
let columnVNodes = columnsRef.value;
{
columnVNodes = columnVNodes.filter((
ref2) => typeof ref2.type !== "symbol"
);
columnVNodes = columnVNodes.filter((
vnode2) => vnode2.type !== Comment
);
}
let index2 = columnVNodes.indexOf(vnode);
return index2 !== -1 ? index2 : ColumnsPreRef.value.indexOf(vnode);
...
...
packages/uni-mp-compiler/src/transforms/vModel.ts
浏览文件 @
743c8786
...
...
@@ -37,6 +37,7 @@ export const transformModel: DirectiveTransform = (
if
(
!
baseResult
.
props
.
length
||
node
.
tagType
===
ElementTypes
.
COMPONENT
)
{
return
transformComponentVModel
(
baseResult
.
props
,
node
,
context
)
as
unknown
as
DirectiveTransformResult
}
...
...
@@ -96,7 +97,7 @@ function transformElementVModel(
node
:
ElementNode
,
context
:
TransformContext
)
{
const
dirs
=
transformVModel
(
props
,
context
,
{
const
dirs
=
transformVModel
(
props
,
node
,
context
,
{
binding
:
'
value
'
,
event
:
'
input
'
,
formatEventCode
(
code
)
{
...
...
@@ -110,6 +111,7 @@ function transformElementVModel(
inputExp
.
children
[
2
]
=
combineVOn
(
dirs
[
1
].
exp
!
,
inputExp
.
children
[
2
]
as
ExpressionNode
,
node
,
context
)
dirs
.
length
=
1
...
...
@@ -117,7 +119,7 @@ function transformElementVModel(
const
inputDir
=
findInputDirectiveNode
(
node
.
props
)
if
(
inputDir
&&
inputDir
.
exp
)
{
// 合并到已有的 input 事件中
inputDir
.
exp
=
combineVOn
(
dirs
[
1
].
exp
!
,
inputDir
.
exp
,
context
)
inputDir
.
exp
=
combineVOn
(
dirs
[
1
].
exp
!
,
inputDir
.
exp
,
node
,
context
)
dirs
.
length
=
1
}
}
...
...
@@ -205,6 +207,7 @@ function parseVOn(exp: ExpressionNode, context: TransformContext) {
function
combineVOn
(
exp1
:
ExpressionNode
,
exp2
:
ExpressionNode
,
node
:
ElementNode
,
context
:
TransformContext
)
{
return
wrapperVOn
(
...
...
@@ -215,16 +218,18 @@ function combineVOn(
parseVOn
(
exp2
,
context
),
`]`
,
]),
node
,
context
)
}
function
transformComponentVModel
(
props
:
Property
[],
node
:
ElementNode
,
context
:
TransformContext
)
{
return
{
props
:
transformVModel
(
props
,
context
,
{
props
:
transformVModel
(
props
,
node
,
context
,
{
formatEventCode
(
code
)
{
return
code
},
...
...
@@ -234,6 +239,7 @@ function transformComponentVModel(
function
transformVModel
(
props
:
Property
[],
node
:
ElementNode
,
context
:
TransformContext
,
{
binding
,
...
...
@@ -273,6 +279,7 @@ function transformVModel(
(
onUpdateExpr
.
type
===
NodeTypes
.
JS_CACHE_EXPRESSION
?
onUpdateExpr
.
value
:
onUpdateExpr
)
as
ExpressionNode
,
node
,
context
)
)
...
...
packages/uni-mp-compiler/src/transforms/vOn.ts
浏览文件 @
743c8786
import
{
isDirectiveNode
}
from
'
@dcloudio/uni-cli-shared
'
import
{
createCompilerError
,
createCompoundExpression
,
...
...
@@ -13,8 +14,11 @@ import {
SimpleExpressionNode
,
TO_HANDLER_KEY
,
DirectiveTransform
,
ElementNode
,
findProp
,
}
from
'
@vue/compiler-core
'
import
{
camelize
,
toHandlerKey
}
from
'
@vue/shared
'
import
{
genExpr
}
from
'
..
'
import
{
V_ON
}
from
'
../runtimeHelpers
'
import
{
TransformContext
}
from
'
../transform
'
import
{
DirectiveTransformResult
}
from
'
./transformElement
'
...
...
@@ -165,11 +169,13 @@ export const transformOn: DirectiveTransform = (
// )
ret
.
props
[
0
].
value
=
wrapperVOn
(
ret
.
props
[
0
].
value
as
ExpressionNode
,
node
,
context
)
}
else
{
ret
.
props
[
0
].
value
=
wrapperVOn
(
ret
.
props
[
0
].
value
as
ExpressionNode
,
node
,
context
)
}
...
...
@@ -192,7 +198,11 @@ function isFilterExpr(value: ExpressionNode, context: TransformContext) {
return
false
}
export
function
wrapperVOn
(
value
:
ExpressionNode
,
context
:
TransformContext
)
{
export
function
wrapperVOn
(
value
:
ExpressionNode
,
node
:
ElementNode
,
context
:
TransformContext
)
{
if
(
isBuiltInIdentifier
(
value
))
{
return
value
}
...
...
@@ -200,10 +210,22 @@ export function wrapperVOn(value: ExpressionNode, context: TransformContext) {
if
(
isFilterExpr
(
value
,
context
))
{
return
value
}
const
keys
:
string
[]
=
[]
if
(
context
.
miniProgram
.
event
?.
key
&&
context
.
inVFor
)
{
const
keyProp
=
findProp
(
node
,
'
key
'
)
// 仅对 v-for 中 item.id 类型做处理,使用索引无需处理,避免引发更多问题
if
(
keyProp
&&
isDirectiveNode
(
keyProp
)
&&
keyProp
.
exp
)
{
const
keyCode
=
genExpr
(
keyProp
.
exp
)
if
(
keyCode
&&
keyCode
.
includes
(
'
.
'
))
{
keys
.
push
(
'
,
'
)
keys
.
push
(
genExpr
(
keyProp
.
exp
))
}
}
}
return
createCompoundExpression
([
`
${
context
.
helperString
(
V_ON
)}
(`
,
value
,
...
keys
,
`)`
,
])
}
packages/uni-mp-qq/dist/uni.compiler.js
浏览文件 @
743c8786
...
...
@@ -99,6 +99,9 @@ const miniProgram = {
fallbackContent
:
false
,
dynamicSlotNames
:
true
,
},
event
:
{
key
:
true
,
},
directive
:
'
qq:
'
,
component
:
{
dir
:
COMPONENTS_DIR
,
...
...
packages/uni-mp-qq/src/compiler/options.ts
浏览文件 @
743c8786
...
...
@@ -30,6 +30,9 @@ export const miniProgram: MiniProgramCompilerOptions = {
fallbackContent
:
false
,
dynamicSlotNames
:
true
,
},
event
:
{
key
:
true
,
},
directive
:
'
qq:
'
,
component
:
{
dir
:
COMPONENTS_DIR
,
...
...
packages/uni-mp-vue/dist/vue.runtime.esm.js
浏览文件 @
743c8786
...
...
@@ -5279,10 +5279,17 @@ function getCreateApp() {
}
}
function
vOn
(
value
)
{
function
vOn
(
value
,
key
)
{
const
instance
=
getCurrentInstance
();
const
name
=
'
e
'
+
instance
.
$ei
++
;
const
mpInstance
=
instance
.
ctx
.
$scope
;
const
ctx
=
instance
.
ctx
;
// 微信小程序,QQ小程序,当 setData diff 的时候,若事件不主动同步过去,会导致事件绑定不更新,(question/137217)
const
extraKey
=
typeof
key
!==
'
undefined
'
&&
(
ctx
.
$mpPlatform
===
'
mp-weixin
'
||
ctx
.
$mpPlatform
===
'
mp-qq
'
)
&&
(
isString
(
key
)
||
typeof
key
===
'
number
'
)
?
'
_
'
+
key
:
''
;
const
name
=
'
e
'
+
instance
.
$ei
++
+
extraKey
;
const
mpInstance
=
ctx
.
$scope
;
if
(
!
value
)
{
// remove
delete
mpInstance
[
name
];
...
...
@@ -5486,7 +5493,7 @@ function setupDevtoolsPlugin() {
// noop
}
const
o
=
(
value
)
=>
vOn
(
value
);
const
o
=
(
value
,
key
)
=>
vOn
(
value
,
key
);
const
f
=
(
source
,
renderItem
)
=>
vFor
(
source
,
renderItem
);
const
d
=
(
names
)
=>
dynamicSlot
(
names
);
const
r
=
(
name
,
props
,
key
)
=>
renderSlot
(
name
,
props
,
key
);
...
...
packages/uni-mp-vue/src/helpers/index.ts
浏览文件 @
743c8786
...
...
@@ -18,7 +18,7 @@ export { setupDevtoolsPlugin } from './devtools'
export
{
findComponentPropsData
,
pruneComponentPropsCache
}
from
'
./renderProps
'
export
const
o
:
typeof
vOn
=
(
value
)
=>
vOn
(
value
)
export
const
o
:
typeof
vOn
=
(
value
,
key
)
=>
vOn
(
value
,
key
)
export
const
f
:
typeof
vFor
=
(
source
:
any
,
renderItem
:
(...
args
:
any
[])
=>
VForItem
...
...
packages/uni-mp-vue/src/helpers/vOn.ts
浏览文件 @
743c8786
import
{
extend
,
isArray
,
isPlainObject
,
hasOwn
,
NOOP
}
from
'
@vue/shared
'
import
{
extend
,
isArray
,
isPlainObject
,
hasOwn
,
NOOP
,
isString
,
}
from
'
@vue/shared
'
import
{
callWithAsyncErrorHandling
,
ComponentInternalInstance
,
...
...
@@ -13,13 +20,23 @@ interface Invoker {
value
:
EventValue
}
export
function
vOn
(
value
:
EventValue
|
undefined
)
{
export
function
vOn
(
value
:
EventValue
|
undefined
,
key
?:
number
|
string
)
{
const
instance
=
getCurrentInstance
()
!
as
unknown
as
{
$ei
:
number
ctx
:
{
$scope
:
Record
<
string
,
any
>
}
ctx
:
{
$scope
:
Record
<
string
,
any
>
;
$mpPlatform
:
UniApp
.
PLATFORM
}
}
const
name
=
'
e
'
+
instance
.
$ei
++
const
mpInstance
=
instance
.
ctx
.
$scope
const
ctx
=
instance
.
ctx
// 微信小程序,QQ小程序,当 setData diff 的时候,若事件不主动同步过去,会导致事件绑定不更新,(question/137217)
const
extraKey
=
typeof
key
!==
'
undefined
'
&&
(
ctx
.
$mpPlatform
===
'
mp-weixin
'
||
ctx
.
$mpPlatform
===
'
mp-qq
'
)
&&
(
isString
(
key
)
||
typeof
key
===
'
number
'
)
?
'
_
'
+
key
:
''
const
name
=
'
e
'
+
instance
.
$ei
++
+
extraKey
const
mpInstance
=
ctx
.
$scope
if
(
!
value
)
{
// remove
delete
mpInstance
[
name
]
...
...
packages/uni-mp-weixin/__tests__/vOn.spec.ts
0 → 100644
浏览文件 @
743c8786
import
{
assert
}
from
'
./testUtils
'
describe
(
'
mp-weixin: transform v-on
'
,
()
=>
{
test
(
'
basic
'
,
()
=>
{
assert
(
`<view v-on:click="onClick"/>`
,
`<view bindtap="{{a}}"/>`
,
`(_ctx, _cache) => {
return { a: _o(_ctx.onClick) }
}`
)
assert
(
`<custom v-on:click="onClick"/>`
,
`<custom bindclick="{{a}}" u-i="2a9ec0b0-0" bind:__l="__l"/>`
,
`(_ctx, _cache) => {
return { a: _o(_ctx.onClick) }
}`
)
})
test
(
'
v-for with v-on
'
,
()
=>
{
assert
(
`<view v-for="item of arr" :key="item._id" @click="show(item)">{{ item.text }}</view>`
,
`<view wx:for="{{a}}" wx:for-item="item" wx:key="b" bindtap="{{item.c}}">{{item.a}}</view>`
,
`(_ctx, _cache) => {
return { a: _f(_ctx.arr, (item, k0, i0) => { return { a: _t(item.text), b: item._id, c: _o($event => _ctx.show(item), item._id) }; }) }
}`
)
assert
(
`<view v-for="item in items" @click="test(item)"/>`
,
`<view wx:for="{{a}}" wx:for-item="item" bindtap="{{item.a}}"/>`
,
`(_ctx, _cache) => {
return { a: _f(_ctx.items, (item, k0, i0) => { return { a: _o($event => _ctx.test(item)) }; }) }
}`
)
assert
(
`<view v-for="(item,index) in items" :key="index" @click="test(item)"/>`
,
`<view wx:for="{{a}}" wx:for-item="item" wx:key="a" bindtap="{{item.b}}"/>`
,
`(_ctx, _cache) => {
return { a: _f(_ctx.items, (item, index, i0) => { return { a: index, b: _o($event => _ctx.test(item)) }; }) }
}`
)
})
})
packages/uni-mp-weixin/dist/uni.compiler.js
浏览文件 @
743c8786
...
...
@@ -76,6 +76,9 @@ const miniProgram = {
fallbackContent
:
false
,
dynamicSlotNames
:
true
,
},
event
:
{
key
:
true
,
},
directive
:
'
wx:
'
,
lazyElement
:
{
canvas
:
[{
name
:
'
bind
'
,
arg
:
[
'
canvas-id
'
,
'
id
'
]
}],
...
...
packages/uni-mp-weixin/src/compiler/options.ts
浏览文件 @
743c8786
...
...
@@ -32,6 +32,9 @@ export const miniProgram: MiniProgramCompilerOptions = {
fallbackContent
:
false
,
dynamicSlotNames
:
true
,
},
event
:
{
key
:
true
,
},
directive
:
'
wx:
'
,
lazyElement
:
{
canvas
:
[{
name
:
'
bind
'
,
arg
:
[
'
canvas-id
'
,
'
id
'
]
}],
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录