Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
菜鸟程序猿_c
uni-app
提交
9c0077d7
U
uni-app
项目概览
菜鸟程序猿_c
/
uni-app
与 Fork 源项目一致
Fork自
DCloud / uni-app
通知
1
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,发现更多精彩内容 >>
提交
9c0077d7
编写于
10月 20, 2021
作者:
fxy060608
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
wip(mp): v-model (Component)
上级
4084674e
变更
11
隐藏空白更改
内联
并排
Showing
11 changed file
with
239 addition
and
53 deletion
+239
-53
packages/uni-cli-shared/src/mp/event.ts
packages/uni-cli-shared/src/mp/event.ts
+11
-1
packages/uni-mp-compiler/__tests__/vModel.spec.ts
packages/uni-mp-compiler/__tests__/vModel.spec.ts
+34
-0
packages/uni-mp-compiler/package.json
packages/uni-mp-compiler/package.json
+1
-0
packages/uni-mp-compiler/src/ast.ts
packages/uni-mp-compiler/src/ast.ts
+14
-5
packages/uni-mp-compiler/src/errors.ts
packages/uni-mp-compiler/src/errors.ts
+24
-1
packages/uni-mp-compiler/src/template/codegen.ts
packages/uni-mp-compiler/src/template/codegen.ts
+0
-2
packages/uni-mp-compiler/src/transforms/transformElement.ts
packages/uni-mp-compiler/src/transforms/transformElement.ts
+31
-29
packages/uni-mp-compiler/src/transforms/vBind.ts
packages/uni-mp-compiler/src/transforms/vBind.ts
+3
-11
packages/uni-mp-compiler/src/transforms/vModel.ts
packages/uni-mp-compiler/src/transforms/vModel.ts
+111
-0
packages/uni-mp-compiler/src/transforms/vOn.ts
packages/uni-mp-compiler/src/transforms/vOn.ts
+9
-3
yarn.lock
yarn.lock
+1
-1
未找到文件。
packages/uni-cli-shared/src/mp/event.ts
浏览文件 @
9c0077d7
...
...
@@ -19,5 +19,15 @@ export function formatMiniProgramEvent(
return
`capture-
${
eventType
}
:
${
eventName
}
`
}
// bind:foo-bar
return
eventType
+
(
eventName
.
indexOf
(
'
-
'
)
>
-
1
?
'
:
'
:
''
)
+
eventName
return
eventType
+
(
isSimpleExpr
(
eventName
)
?
''
:
'
:
'
)
+
eventName
}
function
isSimpleExpr
(
name
:
string
)
{
if
(
name
.
indexOf
(
'
-
'
)
>
-
1
)
{
return
false
}
if
(
name
.
indexOf
(
'
:
'
)
>
-
1
)
{
return
false
}
return
true
}
packages/uni-mp-compiler/__tests__/vModel.spec.ts
0 → 100644
浏览文件 @
9c0077d7
import
{
assert
}
from
'
./testUtils
'
describe
(
'
compiler: transform v-model
'
,
()
=>
{
test
(
`component v-model`
,
()
=>
{
assert
(
`<Comp v-model="model" />`
,
`<comp class="vue-ref" modelValue="{{a}}" bindupdateModelValue="{{b}}"/>`
,
`(_ctx, _cache) => {
return { a: _ctx.model, b: _vOn($event => _ctx.model = $event.detail.__args__[0]) }
}`
)
})
test
(
`component v-model with cache`
,
()
=>
{
assert
(
`<Comp v-model="model" />`
,
`<comp class="vue-ref" modelValue="{{a}}" bindupdateModelValue="{{b}}"/>`
,
`(_ctx, _cache) => {
return { a: _ctx.model, b: _vOn($event => _ctx.model = $event.detail.__args__[0]) }
}`
,
{
cacheHandlers
:
true
,
}
)
})
// test(`input,textarea v-model`, () => {
// assert(
// `<input v-model="model" />`,
// `<input value="{{a}}" bindinput="{{b}}" />`,
// `(_ctx, _cache) => {
// return { a: _ctx.model, b: _vOn(($event)=>_ctx.model = $event.detail.value) }
// }`
// )
// })
})
packages/uni-mp-compiler/package.json
浏览文件 @
9c0077d7
...
...
@@ -23,6 +23,7 @@
"@babel/parser"
:
"^7.15.0"
,
"@babel/types"
:
"^7.15.0"
,
"@vue/compiler-core"
:
"^3.2.20"
,
"@vue/compiler-dom"
:
"^3.2.20"
,
"estree-walker"
:
"^2.0.2"
}
}
packages/uni-mp-compiler/src/ast.ts
浏览文件 @
9c0077d7
...
...
@@ -199,20 +199,29 @@ export function parseStringLiteral(
return
stringLiteral
(
''
)
}
export
function
createBind
DirectiveNode
(
function
create
DirectiveNode
(
name
:
string
,
value
:
string
arg
:
string
,
exp
:
string
):
DirectiveNode
{
return
{
type
:
NodeTypes
.
DIRECTIVE
,
name
:
'
bind
'
,
name
,
modifiers
:
[],
loc
:
locStub
,
arg
:
createSimpleExpression
(
name
,
true
),
exp
:
createSimpleExpression
(
value
,
false
),
arg
:
createSimpleExpression
(
arg
,
true
),
exp
:
createSimpleExpression
(
exp
,
false
),
}
}
export
function
createOnDirectiveNode
(
name
:
string
,
value
:
string
)
{
return
createDirectiveNode
(
'
on
'
,
name
,
value
)
}
export
function
createBindDirectiveNode
(
name
:
string
,
value
:
string
)
{
return
createDirectiveNode
(
'
bind
'
,
name
,
value
)
}
export
function
createAttributeNode
(
name
:
string
,
content
:
string
...
...
packages/uni-mp-compiler/src/errors.ts
浏览文件 @
9c0077d7
import
{
CompilerError
,
createCompilerError
,
SourceLocation
,
}
from
'
@vue/compiler-core
'
export
const
enum
MPErrorCodes
{
X_V_ON_NO_ARGUMENT
,
X_V_ON_DYNAMIC_EVENT
,
...
...
@@ -10,7 +16,7 @@ export const enum MPErrorCodes {
X_DYNAMIC_COMPONENT_NOT_SUPPORTED
,
}
export
const
e
rrorMessages
:
Record
<
number
,
string
>
=
{
const
MPE
rrorMessages
:
Record
<
number
,
string
>
=
{
[
MPErrorCodes
.
X_V_ON_NO_ARGUMENT
]:
'
v-on="" is not supported
'
,
[
MPErrorCodes
.
X_V_ON_DYNAMIC_EVENT
]:
'
v-on:[event]="" is not supported.
'
,
[
MPErrorCodes
.
X_V_BIND_NO_ARGUMENT
]:
'
v-bind="" is not supported.
'
,
...
...
@@ -23,3 +29,20 @@ export const errorMessages: Record<number, string> = {
[
MPErrorCodes
.
X_NOT_SUPPORTED
]:
'
not supported:
'
,
[
MPErrorCodes
.
X_V_IS_NOT_SUPPORTED
]:
'
v-is not supported
'
,
}
export
interface
MPCompilerError
extends
CompilerError
{
code
:
MPErrorCodes
}
export
function
createMPCompilerError
(
code
:
MPErrorCodes
,
loc
?:
SourceLocation
,
additionalMessage
?:
string
)
{
return
createCompilerError
(
code
,
loc
,
MPErrorMessages
,
additionalMessage
)
as
MPCompilerError
}
packages/uni-mp-compiler/src/template/codegen.ts
浏览文件 @
9c0077d7
...
...
@@ -303,8 +303,6 @@ function genDirectiveNode(
if
(
prop
.
arg
)
{
push
(
`slot="
${(
prop
.
arg
as
SimpleExpressionNode
).
content
}
"`
)
}
}
else
if
(
prop
.
name
===
'
model
'
)
{
// TODO
}
else
if
(
prop
.
name
===
'
show
'
)
{
push
(
`hidden="{{!
${(
prop
.
exp
as
SimpleExpressionNode
).
content
}
}}"`
)
}
else
if
(
prop
.
arg
&&
prop
.
exp
)
{
...
...
packages/uni-mp-compiler/src/transforms/transformElement.ts
浏览文件 @
9c0077d7
...
...
@@ -16,8 +16,9 @@ import {
findDir
,
locStub
,
AttributeNode
,
DirectiveNode
,
}
from
'
@vue/compiler-core
'
import
{
errorMessages
,
MPErrorCodes
}
from
'
../errors
'
import
{
createMPCompilerError
,
MPErrorCodes
}
from
'
../errors
'
import
{
BindingComponentTypes
,
...
...
@@ -25,6 +26,7 @@ import {
TransformContext
,
}
from
'
../transform
'
import
{
createAttributeNode
}
from
'
../ast
'
import
{
transformModel
}
from
'
./vModel
'
export
interface
DirectiveTransformResult
{
props
:
Property
[]
...
...
@@ -101,20 +103,15 @@ function processComponent(node: ElementNode, context: TransformContext) {
// 1. dynamic component
if
(
isComponentTag
(
tag
))
{
return
context
.
onError
(
createCompilerError
(
create
MP
CompilerError
(
MPErrorCodes
.
X_DYNAMIC_COMPONENT_NOT_SUPPORTED
,
node
.
loc
,
errorMessages
node
.
loc
)
)
}
if
(
findDir
(
node
,
'
is
'
))
{
return
context
.
onError
(
createCompilerError
(
MPErrorCodes
.
X_V_IS_NOT_SUPPORTED
,
node
.
loc
,
errorMessages
)
createMPCompilerError
(
MPErrorCodes
.
X_V_IS_NOT_SUPPORTED
,
node
.
loc
)
)
}
// TODO not supported
...
...
@@ -125,12 +122,7 @@ function processComponent(node: ElementNode, context: TransformContext) {
const
builtIn
=
isCoreComponent
(
tag
)
||
context
.
isBuiltInComponent
(
tag
)
if
(
builtIn
)
{
return
context
.
onError
(
createCompilerError
(
MPErrorCodes
.
X_NOT_SUPPORTED
,
node
.
loc
,
errorMessages
,
tag
)
createMPCompilerError
(
MPErrorCodes
.
X_NOT_SUPPORTED
,
node
.
loc
,
tag
)
)
}
...
...
@@ -147,12 +139,7 @@ function processComponent(node: ElementNode, context: TransformContext) {
const
dotIndex
=
tag
.
indexOf
(
'
.
'
)
if
(
dotIndex
>
0
)
{
return
context
.
onError
(
createCompilerError
(
MPErrorCodes
.
X_NOT_SUPPORTED
,
node
.
loc
,
errorMessages
,
tag
)
createMPCompilerError
(
MPErrorCodes
.
X_NOT_SUPPORTED
,
node
.
loc
,
tag
)
)
}
...
...
@@ -253,12 +240,11 @@ function processProps(node: ElementNode, context: TransformContext) {
// v-bind=""
if
(
!
arg
)
{
context
.
onError
(
createCompilerError
(
create
MP
CompilerError
(
isVBind
?
MPErrorCodes
.
X_V_BIND_NO_ARGUMENT
:
MPErrorCodes
.
X_V_ON_NO_ARGUMENT
,
loc
,
errorMessages
loc
)
)
continue
...
...
@@ -269,12 +255,11 @@ function processProps(node: ElementNode, context: TransformContext) {
// v-bind:[a.b]=""
if
(
!
(
arg
.
type
===
NodeTypes
.
SIMPLE_EXPRESSION
&&
arg
.
isStatic
))
{
context
.
onError
(
createCompilerError
(
create
MP
CompilerError
(
isVBind
?
MPErrorCodes
.
X_V_BIND_DYNAMIC_ARGUMENT
:
MPErrorCodes
.
X_V_ON_DYNAMIC_EVENT
,
loc
,
errorMessages
loc
)
)
continue
...
...
@@ -293,11 +278,28 @@ function processProps(node: ElementNode, context: TransformContext) {
const
directiveTransform
=
context
.
directiveTransforms
[
name
]
if
(
directiveTransform
)
{
prop
.
exp
=
directiveTransform
(
prop
,
node
,
context
).
props
[
0
]
.
value
as
ExpressionNode
const
{
props
}
=
directiveTransform
(
prop
,
node
,
context
)
if
(
props
.
length
)
{
prop
.
exp
=
props
[
0
].
value
as
ExpressionNode
}
}
}
}
processVModel
(
node
,
context
)
}
function
processVModel
(
node
:
ElementNode
,
context
:
TransformContext
)
{
const
{
props
}
=
node
const
dirs
:
DirectiveNode
[]
=
[]
for
(
let
i
=
0
;
i
<
props
.
length
;
i
++
)
{
const
prop
=
props
[
i
]
if
(
prop
.
type
===
NodeTypes
.
DIRECTIVE
&&
prop
.
name
===
'
model
'
)
{
dirs
.
push
(...
transformModel
(
prop
,
node
,
context
))
props
.
splice
(
i
,
1
)
i
--
}
}
props
.
push
(...
dirs
)
}
function
isComponentTag
(
tag
:
string
)
{
...
...
packages/uni-mp-compiler/src/transforms/vBind.ts
浏览文件 @
9c0077d7
...
...
@@ -8,7 +8,7 @@ import {
createSimpleExpression
,
}
from
'
@vue/compiler-core
'
import
{
DirectiveTransform
}
from
'
../transform
'
import
{
errorMessages
,
MPErrorCodes
}
from
'
../errors
'
import
{
createMPCompilerError
,
MPErrorCodes
}
from
'
../errors
'
export
const
transformBind
:
DirectiveTransform
=
(
dir
,
_node
,
context
)
=>
{
const
{
exp
,
modifiers
,
loc
}
=
dir
...
...
@@ -37,20 +37,12 @@ export const transformBind: DirectiveTransform = (dir, _node, context) => {
if
(
modifiers
.
includes
(
'
prop
'
))
{
context
.
onWarn
(
createCompilerError
(
MPErrorCodes
.
X_V_BIND_MODIFIER_PROP
,
loc
,
errorMessages
)
createMPCompilerError
(
MPErrorCodes
.
X_V_BIND_MODIFIER_PROP
,
loc
)
)
}
if
(
modifiers
.
includes
(
'
attr
'
))
{
context
.
onWarn
(
createCompilerError
(
MPErrorCodes
.
X_V_BIND_MODIFIER_ATTR
,
loc
,
errorMessages
)
createMPCompilerError
(
MPErrorCodes
.
X_V_BIND_MODIFIER_ATTR
,
loc
)
)
}
...
...
packages/uni-mp-compiler/src/transforms/vModel.ts
0 → 100644
浏览文件 @
9c0077d7
import
{
Property
,
transformModel
as
baseTransform
,
ElementTypes
,
findProp
,
NodeTypes
,
DirectiveNode
,
ElementNode
,
ExpressionNode
,
}
from
'
@vue/compiler-core
'
import
{
DOMErrorCodes
,
createDOMCompilerError
}
from
'
@vue/compiler-dom
'
import
{
camelize
}
from
'
@vue/shared
'
import
{
createBindDirectiveNode
,
createOnDirectiveNode
}
from
'
../ast
'
import
{
genExpr
}
from
'
../codegen
'
import
{
TransformContext
}
from
'
../transform
'
import
{
wrapperVOn
}
from
'
./vOn
'
export
const
transformModel
=
(
dir
:
DirectiveNode
,
node
:
ElementNode
,
context
:
TransformContext
)
=>
{
const
baseResult
=
baseTransform
(
dir
,
node
,
context
as
any
)
// base transform has errors OR component v-model (only need props)
if
(
!
baseResult
.
props
.
length
||
node
.
tagType
===
ElementTypes
.
COMPONENT
)
{
return
transformComponentVModel
(
baseResult
.
props
,
context
)
}
if
(
dir
.
arg
)
{
context
.
onError
(
createDOMCompilerError
(
DOMErrorCodes
.
X_V_MODEL_ARG_ON_ELEMENT
,
dir
.
arg
.
loc
)
)
}
function
checkDuplicatedValue
()
{
const
value
=
findProp
(
node
,
'
value
'
)
if
(
value
)
{
context
.
onError
(
createDOMCompilerError
(
DOMErrorCodes
.
X_V_MODEL_UNNECESSARY_VALUE
,
value
.
loc
)
)
}
}
const
{
tag
}
=
node
if
(
tag
===
'
input
'
||
tag
===
'
textarea
'
)
{
checkDuplicatedValue
()
}
else
{
context
.
onError
(
createDOMCompilerError
(
DOMErrorCodes
.
X_V_MODEL_ON_INVALID_ELEMENT
,
dir
.
loc
)
)
}
// native vmodel doesn't need the `modelValue` props since they are also
// passed to the runtime as `binding.value`. removing it reduces code size.
baseResult
.
props
=
baseResult
.
props
.
filter
(
(
p
)
=>
!
(
p
.
key
.
type
===
NodeTypes
.
SIMPLE_EXPRESSION
&&
p
.
key
.
content
===
'
modelValue
'
)
)
return
[]
}
function
transformComponentVModel
(
props
:
Property
[],
context
:
TransformContext
):
DirectiveNode
[]
{
if
(
props
.
length
!==
2
)
{
return
[]
}
const
{
key
:
modelValueArg
,
value
:
modelValeExpr
}
=
props
[
0
]
const
{
key
:
onUpdateArg
,
value
:
onUpdateExpr
}
=
props
[
1
]
if
(
modelValueArg
.
type
!==
NodeTypes
.
SIMPLE_EXPRESSION
)
{
return
[]
}
if
(
onUpdateArg
.
type
!==
NodeTypes
.
SIMPLE_EXPRESSION
||
!
onUpdateArg
.
content
.
startsWith
(
'
onUpdate:
'
)
)
{
return
[]
}
const
vBindModelValue
=
createBindDirectiveNode
(
modelValueArg
.
content
,
genExpr
(
modelValeExpr
as
ExpressionNode
)
)
const
vOnUpdate
=
createOnDirectiveNode
(
camelize
(
onUpdateArg
.
content
.
replace
(
'
onUpdate:
'
,
'
update-
'
)),
genExpr
(
wrapperVOn
(
// onUpdateExpr 通常是 ExpressionNode 或者被 cache 的 ExpressionNode
(
onUpdateExpr
.
type
===
NodeTypes
.
JS_CACHE_EXPRESSION
?
onUpdateExpr
.
value
:
onUpdateExpr
)
as
ExpressionNode
,
context
)
).
replace
(
`= $event`
,
`= $event.detail.__args__[0]`
)
)
return
[
vBindModelValue
,
vOnUpdate
]
}
packages/uni-mp-compiler/src/transforms/vOn.ts
浏览文件 @
9c0077d7
...
...
@@ -159,9 +159,15 @@ export const transformOn: DirectiveTransform = (
// context.cache(ret.props[0].value) as ExpressionNode,
// context
// )
ret
.
props
[
0
].
value
=
wrapper
(
ret
.
props
[
0
].
value
as
ExpressionNode
,
context
)
ret
.
props
[
0
].
value
=
wrapperVOn
(
ret
.
props
[
0
].
value
as
ExpressionNode
,
context
)
}
else
{
ret
.
props
[
0
].
value
=
wrapper
(
ret
.
props
[
0
].
value
as
ExpressionNode
,
context
)
ret
.
props
[
0
].
value
=
wrapperVOn
(
ret
.
props
[
0
].
value
as
ExpressionNode
,
context
)
}
// mark the key as handler for props normalization check
...
...
@@ -169,7 +175,7 @@ export const transformOn: DirectiveTransform = (
return
ret
}
function
wrapper
(
value
:
ExpressionNode
,
context
:
TransformContext
)
{
export
function
wrapperVOn
(
value
:
ExpressionNode
,
context
:
TransformContext
)
{
return
createCompoundExpression
([
`
${
context
.
helperString
(
V_ON
)}
(`
,
value
,
...
...
yarn.lock
浏览文件 @
9c0077d7
...
...
@@ -2774,7 +2774,7 @@
estree-walker "^2.0.2"
source-map "^0.6.1"
"@vue/compiler-dom@3.2.20":
"@vue/compiler-dom@3.2.20"
, "@vue/compiler-dom@^3.2.20"
:
version "3.2.20"
resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.2.20.tgz#8e0ef354449c0faf41519b00bfc2045eae01dcb5"
integrity sha512-QnI77ec/JtV7R0YBbcVayYTDCRcI9OCbxiUQK6izVyqQO0658n0zQuoNwe+bYgtqnvGAIqTR3FShTd5y4oOjdg==
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录