el-form-renderer-vue3 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vite/deps_temp_ce3ed5bf/package.json +3 -0
- package/.vscode/extensions.json +3 -0
- package/LICENSE +661 -0
- package/README.en.md +36 -0
- package/README.md +252 -0
- package/index.html +13 -0
- package/package.json +34 -0
- package/public/vite.svg +1 -0
- package/src/App.vue +59 -0
- package/src/ChildCom.vue +24 -0
- package/src/assets/vue.svg +1 -0
- package/src/components/femessage/components/render-form-group.vue +48 -0
- package/src/components/femessage/components/render-form-item.vue +328 -0
- package/src/components/femessage/el-form-renderer.vue +284 -0
- package/src/components/femessage/util/CustomComponent.js +28 -0
- package/src/components/femessage/util/VNode.js +9 -0
- package/src/components/femessage/util/enable-when.js +26 -0
- package/src/components/femessage/util/transform-content.js +48 -0
- package/src/components/femessage/util/utils.js +127 -0
- package/src/el-form-renderer.md +220 -0
- package/src/main.js +15 -0
- package/src/router/index.js +160 -0
- package/src/style.css +89 -0
- package/src/view/AboutView.vue +40 -0
- package/src/view/HomeView.vue +134 -0
- package/src/view/MyInput.vue +46 -0
- package/src/view/checkboxGroup.vue +29 -0
- package/src/view/content.vue +176 -0
- package/src/view/deprecated.vue +37 -0
- package/src/view/disabled.vue +104 -0
- package/src/view/el.vue +24 -0
- package/src/view/format.vue +63 -0
- package/src/view/getcomponent.vue +51 -0
- package/src/view/getform.vue +50 -0
- package/src/view/hidden.vue +51 -0
- package/src/view/label.vue +25 -0
- package/src/view/next.vue +55 -0
- package/src/view/picker.vue +27 -0
- package/src/view/radioGroup.vue +38 -0
- package/src/view/readonly.vue +144 -0
- package/src/view/remote.vue +115 -0
- package/src/view/rules.vue +46 -0
- package/src/view/rulesPlus.vue +34 -0
- package/src/view/setoptios.vue +50 -0
- package/src/view/slot.vue +37 -0
- package/src/view/testAttrs.vue +17 -0
- package/src/view/update.vue +64 -0
- package/src/view/vmodel.vue +137 -0
- package/src/your-component.vue +55 -0
- package/vite.config.js +7 -0
package/README.en.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# form-render
|
|
2
|
+
|
|
3
|
+
#### Description
|
|
4
|
+
{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**}
|
|
5
|
+
|
|
6
|
+
#### Software Architecture
|
|
7
|
+
Software architecture description
|
|
8
|
+
|
|
9
|
+
#### Installation
|
|
10
|
+
|
|
11
|
+
1. xxxx
|
|
12
|
+
2. xxxx
|
|
13
|
+
3. xxxx
|
|
14
|
+
|
|
15
|
+
#### Instructions
|
|
16
|
+
|
|
17
|
+
1. xxxx
|
|
18
|
+
2. xxxx
|
|
19
|
+
3. xxxx
|
|
20
|
+
|
|
21
|
+
#### Contribution
|
|
22
|
+
|
|
23
|
+
1. Fork the repository
|
|
24
|
+
2. Create Feat_xxx branch
|
|
25
|
+
3. Commit your code
|
|
26
|
+
4. Create Pull Request
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
#### Gitee Feature
|
|
30
|
+
|
|
31
|
+
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
|
|
32
|
+
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
|
|
33
|
+
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
|
|
34
|
+
4. The most valuable open source project [GVP](https://gitee.com/gvp)
|
|
35
|
+
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
|
|
36
|
+
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
package/README.md
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
## 遗留问题 :待解决
|
|
2
|
+
|
|
3
|
+
select 为 multiple 多选时 必须初始化空数组(在 elementplus v-model 初始化 updateValue 时 为空数组会触发校验)
|
|
4
|
+
|
|
5
|
+
## Introduction
|
|
6
|
+
|
|
7
|
+
### WHAT
|
|
8
|
+
|
|
9
|
+
form-renderer 基于元素 element-plus,但不限于元素 element-plus 组件。在完全继承 element-plus 元素的 form 属性的基础上,进行了扩展。一些非表单组件或自定义组件,因此,用户可以使用一段 json 来呈现完整的表单。
|
|
10
|
+
|
|
11
|
+
### WHY
|
|
12
|
+
|
|
13
|
+
在我们的日常开发中,有很多有表单的页面,通常表单结构相似,逻辑重复。el 表单呈现器没有复杂的逻辑。它只转换 JSON 来呈现表单项,节省了编写业务逻辑的时间和精力,并减少了重复代码。
|
|
14
|
+
|
|
15
|
+
## Features
|
|
16
|
+
|
|
17
|
+
- 用 json 呈现表单
|
|
18
|
+
- 支持与自定义组件集成
|
|
19
|
+
- 支持 updateForm 方法批量更新表单数据
|
|
20
|
+
- 支持 setOptions 方法,动态更改选择选项
|
|
21
|
+
- 内容支持 inputFormat、outputFormat、trim 以处理组件的输入和输出值
|
|
22
|
+
- 支持 v-model
|
|
23
|
+
|
|
24
|
+
## Links
|
|
25
|
+
|
|
26
|
+
- [$attrs 和 $listeners (vue2&&vue3)](https://blog.csdn.net/qq_63358859/article/details/133699476?spm=1001.2014.3001.5501)
|
|
27
|
+
- [vue2 与 vue3 函数式组件](https://blog.csdn.net/qq_63358859/article/details/133635120?spm=1001.2014.3001.5501)
|
|
28
|
+
- [vue 2 与 vue3 获取模版引用 (ref)的区别](https://blog.csdn.net/qq_63358859/article/details/133532229?spm=1001.2014.3001.5501)
|
|
29
|
+
- [vue2 与 vue3 v-model 的区别](https://marketplace.visualstudio.com/items?itemName=FEMessage.fem-vscode-helper)
|
|
30
|
+
- [vue2 版本](https://blog.csdn.net/qq_63358859/article/details/130442636?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522169684271816800180612618%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=169684271816800180612618&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-7-130442636-null-null.nonecase&utm_term=render&spm=1018.2226.3001.4450)
|
|
31
|
+
- [中文文档](https://gitee.com/childe-jia/form-render/wikis/%E6%96%87%E6%A1%A3/%E4%BB%8B%E7%BB%8D)
|
|
32
|
+
|
|
33
|
+
## Props
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
export default {
|
|
37
|
+
// ...
|
|
38
|
+
props: {
|
|
39
|
+
/**
|
|
40
|
+
* support all el-form's props
|
|
41
|
+
* @see: https://element.eleme.io/#/zh-CN/component/form#form-attributes
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* 表单项的配置数组,每个表单项代表一个原子表单项
|
|
46
|
+
* the form config's array, each item represents a form-item
|
|
47
|
+
*/
|
|
48
|
+
content: {
|
|
49
|
+
type: Array, // type:Content[], check Content's definition below
|
|
50
|
+
required: true
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* disable all form-items
|
|
55
|
+
*/
|
|
56
|
+
disabled: {
|
|
57
|
+
type: Boolean,
|
|
58
|
+
default: false
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* 表单项的typescript定义
|
|
65
|
+
* 支持所有el-form-item's props。表单项组件本身的props定义在el上
|
|
66
|
+
* definition of form-item written in typescript.
|
|
67
|
+
* support all el-form-item's props. The component's props need to be set at prop el
|
|
68
|
+
*/
|
|
69
|
+
interface Content {
|
|
70
|
+
// 每一个原子都存在 id,用于存储该原子的值,不能重复
|
|
71
|
+
// key of form-item value in form value. Must be unique
|
|
72
|
+
id: string
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* 可以是element提供的所有表单组件类型,如传入'input',则渲染出'el-input'
|
|
76
|
+
* 当type="group"时,可以创造复杂对象类型的表单数据,配合items使用。此时getFormValue()返回的是对象类型的数据,对象的每个属性对应items里的每一项
|
|
77
|
+
* support all element's form component, e.g., type 'input' will render as 'el-input'.
|
|
78
|
+
* you can create nested form value with type 'group' and use items to define that form value's shape. The type of this form value will be 'object'
|
|
79
|
+
*/
|
|
80
|
+
type: string
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* 当type="group"时使用
|
|
84
|
+
* items内依然遵循同一层级的id不重复的原则
|
|
85
|
+
* using with type 'group'
|
|
86
|
+
* the `id` in each item of items must be unique
|
|
87
|
+
*/
|
|
88
|
+
items: Content[]
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* 默认值
|
|
92
|
+
* FIXME: 别用关键字做 key
|
|
93
|
+
*/
|
|
94
|
+
default?: any
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* 当 type === 'input' 时展示文本值
|
|
98
|
+
* 当 type === 'select' 时展示对应 label
|
|
99
|
+
* 对于其他组件等同于 disabled = true
|
|
100
|
+
*/
|
|
101
|
+
readonly = false
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* @deprecated
|
|
105
|
+
*/
|
|
106
|
+
enableWhen?: object | string
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* 传入一个方法,并返回 boolean,返回 true 时则隐藏该表单项
|
|
110
|
+
* formValue 为当前 form 的值,item 为当前表单项的定义
|
|
111
|
+
* hide the form-item when return true
|
|
112
|
+
* formValue is same as what getFormValue returns, and item is the config of this form-item
|
|
113
|
+
*/
|
|
114
|
+
hidden?: (formValue: Object, item: Content) => boolean
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* 具有选择功能的原子表单可用此定义可选项
|
|
118
|
+
* use with type: select, radio-group, radio-button, checkbox-group, checkbox-button
|
|
119
|
+
*/
|
|
120
|
+
options?: {label: string; value?: any}[]
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* 配置remote.url,即可远程配置组件的某个prop!
|
|
124
|
+
* remote接受以下属性:
|
|
125
|
+
* url: 远程接口的地址
|
|
126
|
+
* prop: 要注入的 prop 的名称,默认为 options
|
|
127
|
+
* request: 可选,请求方法
|
|
128
|
+
* dataPath: 可选,data在响应体中的路径
|
|
129
|
+
* onResponse: 可选,处理请求回来的数据
|
|
130
|
+
* onError: 可选,处理请求出错的情况
|
|
131
|
+
* 另外,针对 select、radio-group、checkbox-group,远程数据能自动映射成 el-option 选项!以下属性仅在此情况使用
|
|
132
|
+
* label: 可选,可直接配置远程数据中用作 label 的key
|
|
133
|
+
* value: 可选,可直接配置远程数据中用作 value 的key
|
|
134
|
+
* @see https://zhuanlan.zhihu.com/p/97827063
|
|
135
|
+
*
|
|
136
|
+
* use remote to set one prop! remote accept following props:
|
|
137
|
+
* url: remote api address
|
|
138
|
+
* prop: prop name that data inject
|
|
139
|
+
* request: optional, customize how to get your options
|
|
140
|
+
* dataPath: optional, data's path in response
|
|
141
|
+
* onResponse: optional, deal with your response
|
|
142
|
+
* onError: optional, deal with request error
|
|
143
|
+
* and, we treat select、radio-group、checkbox-group specially and the resp will be map as an el-option's group! following props only suitable for this case
|
|
144
|
+
* label: optional, label key in resp
|
|
145
|
+
* value: optional, value key in resp
|
|
146
|
+
*/
|
|
147
|
+
remote?: {
|
|
148
|
+
url: string
|
|
149
|
+
request = () => this.$axios.get(url).then(resp => resp.data)
|
|
150
|
+
prop = 'options'
|
|
151
|
+
dataPath = ''
|
|
152
|
+
onResponse = resp => {
|
|
153
|
+
if (dataPath) resp = _get(resp, dataPath)
|
|
154
|
+
switch (this.data.type) {
|
|
155
|
+
case 'select':
|
|
156
|
+
case 'checkbox-group':
|
|
157
|
+
case 'radio-group':
|
|
158
|
+
return resp.map(item => ({
|
|
159
|
+
label: item[label],
|
|
160
|
+
value: item[value]
|
|
161
|
+
}))
|
|
162
|
+
default:
|
|
163
|
+
return resp
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
onError = error => console.error(error.message)
|
|
167
|
+
label = 'label'
|
|
168
|
+
value = 'value'
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
attrs?: object // html attributes
|
|
172
|
+
/**
|
|
173
|
+
* 用于定义具体原子表单(如el-input)的属性,比如定义el-input的placeholder
|
|
174
|
+
* use to define props of the actual component of this form-item, such as placeholder of el-input
|
|
175
|
+
*/
|
|
176
|
+
el?: object
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* 使用自定义组件
|
|
180
|
+
* component适用于渲染局部注册组件和自定义组件,而type适用于带el-前缀的全局组件
|
|
181
|
+
* custom component
|
|
182
|
+
* use it when element's form components are not enough
|
|
183
|
+
*/
|
|
184
|
+
component?: Vue
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* 是否覆盖自定义组件内置的校验规则
|
|
188
|
+
* `true` 为覆盖, 默认为 `false`
|
|
189
|
+
* whether to override the validation rules written in custom components
|
|
190
|
+
* `true` to override, default `false`
|
|
191
|
+
*/
|
|
192
|
+
overrideRules: boolean
|
|
193
|
+
|
|
194
|
+
label?: string //set el-form-item's label
|
|
195
|
+
trim = true // trim value at change event
|
|
196
|
+
|
|
197
|
+
// 用于处理输入值,输入的值包括:1. default;2. v-model;3. updateForm。参数为整个表单的值对象或 updateForm 传入的对象
|
|
198
|
+
// 如果 inputFormat 返回 undefined,则不会更新此表单项
|
|
199
|
+
// obj is param you passed to updateForm. You can use this function to hijack this process and customize the form value
|
|
200
|
+
inputFormat?: (obj: any) => any
|
|
201
|
+
|
|
202
|
+
// 用于处理输出值,参数为对应组件返回值
|
|
203
|
+
// 如果处理后的值是对象类型,会覆盖(Object.assign)到整个表单的值上
|
|
204
|
+
// used to hijack the getFormValue's process and customize the return value
|
|
205
|
+
outputFormat?: (val: any) => any
|
|
206
|
+
|
|
207
|
+
// set el-form-item's rules
|
|
208
|
+
rules?: object
|
|
209
|
+
|
|
210
|
+
// @deprecated
|
|
211
|
+
atChange?: (id: string, value: any) => void
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* 监听表单项发出的事件
|
|
215
|
+
* listen to any events emitted by component of form item
|
|
216
|
+
* @param {any[]} args - what that event emits
|
|
217
|
+
* @param {function} updateForm - same as methods.updateForm
|
|
218
|
+
*/
|
|
219
|
+
on?: {
|
|
220
|
+
[eventName: string]: (args: any[], updateForm: function) => void
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* a tour of typescript
|
|
226
|
+
*/
|
|
227
|
+
interface obj {
|
|
228
|
+
a: string // type string
|
|
229
|
+
b?: string // type string, optional
|
|
230
|
+
c = true // type boolean, optional, default true
|
|
231
|
+
d: string[] // type array, each item must be string
|
|
232
|
+
e: any // could be any valid js type
|
|
233
|
+
f: (a: number) => void // type function, which receives a param 'a' as number and return nothing
|
|
234
|
+
h: Vue // instance of Vue
|
|
235
|
+
i: {[a: string]: number} // type object, whose key is type string, and value is type number
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
## Methods
|
|
240
|
+
|
|
241
|
+
support all [el-form's methods](https://element.eleme.io/#/zh-CN/component/form#form-methods)
|
|
242
|
+
|
|
243
|
+
## Slots
|
|
244
|
+
|
|
245
|
+
| Slot | Description |
|
|
246
|
+
| -------- | ------------------------------------------- |
|
|
247
|
+
| default | insert at bottom |
|
|
248
|
+
| id:hello | insert before form-item whose id is 'hello' |
|
|
249
|
+
|
|
250
|
+
## Inspiration
|
|
251
|
+
|
|
252
|
+
thanks to [el-form-renderer](https://github.com/femessage/el-form-renderer/)
|
package/index.html
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>Vite + Vue</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<div id="app"></div>
|
|
11
|
+
<script type="module" src="/src/main.js"></script>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
|
|
3
|
+
"name": "el-form-renderer-vue3",
|
|
4
|
+
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"dev": "vite",
|
|
9
|
+
"build": "vite build",
|
|
10
|
+
"preview": "vite preview"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@element-plus/icons-vue": "^2.1.0",
|
|
14
|
+
"axios": "^1.5.1",
|
|
15
|
+
"element-plus": "^2.3.14",
|
|
16
|
+
"lodash.clonedeep": "^4.5.0",
|
|
17
|
+
"lodash.frompairs": "^4.0.1",
|
|
18
|
+
"lodash.get": "^4.4.2",
|
|
19
|
+
"lodash.has": "^4.5.2",
|
|
20
|
+
"lodash.includes": "^4.3.0",
|
|
21
|
+
"lodash.isequal": "^4.5.0",
|
|
22
|
+
"lodash.isplainobject": "^4.0.6",
|
|
23
|
+
"lodash.kebabcase": "^4.1.1",
|
|
24
|
+
"lodash.set": "^4.3.2",
|
|
25
|
+
"lodash.topairs": "^4.3.0",
|
|
26
|
+
"vue": "^3.3.4",
|
|
27
|
+
"vue-router": "4"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@vitejs/plugin-vue": "^4.2.3",
|
|
31
|
+
"vite": "^4.4.5"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
package/public/vite.svg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
package/src/App.vue
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<nav class="box">
|
|
3
|
+
<router-link to="/">base</router-link> |
|
|
4
|
+
|
|
5
|
+
<router-link to="/checkboxGroup">checkbox-group</router-link> |
|
|
6
|
+
|
|
7
|
+
<router-link to="/content">content</router-link> |
|
|
8
|
+
|
|
9
|
+
<router-link to="/picker">date-picker</router-link> |
|
|
10
|
+
|
|
11
|
+
<router-link to="/deprecated">deprecated</router-link> |
|
|
12
|
+
|
|
13
|
+
<router-link to="/disabled">disabled</router-link> |
|
|
14
|
+
|
|
15
|
+
<router-link to="/el">el</router-link> |
|
|
16
|
+
|
|
17
|
+
<router-link to="/getcomponent">get-component-by-id</router-link> |
|
|
18
|
+
|
|
19
|
+
<router-link to="/getform">get-form-value</router-link> |
|
|
20
|
+
|
|
21
|
+
<router-link to="/hidden">hidden</router-link> |
|
|
22
|
+
|
|
23
|
+
<router-link to="/next">next-tick</router-link> |
|
|
24
|
+
|
|
25
|
+
<router-link to="/about">on</router-link> |
|
|
26
|
+
|
|
27
|
+
<router-link to="/radioGroup">radio-group</router-link> |
|
|
28
|
+
|
|
29
|
+
<router-link to="/readonly">readonly</router-link> |
|
|
30
|
+
|
|
31
|
+
<router-link to="/remote">remote</router-link> |
|
|
32
|
+
|
|
33
|
+
<router-link to="/rules">rules</router-link> |
|
|
34
|
+
|
|
35
|
+
<router-link to="/rulesPlus">rulesPlus</router-link> |
|
|
36
|
+
|
|
37
|
+
<router-link to="/setoptios">set-options </router-link> |
|
|
38
|
+
|
|
39
|
+
<router-link to="/label">slot-label</router-link> |
|
|
40
|
+
|
|
41
|
+
<router-link to="/slot">slot</router-link> |
|
|
42
|
+
|
|
43
|
+
<router-link to="/update">update-form</router-link> |
|
|
44
|
+
|
|
45
|
+
<router-link to="/vmodel">v-model</router-link> |
|
|
46
|
+
|
|
47
|
+
<router-link to="/format">value-format</router-link> |
|
|
48
|
+
|
|
49
|
+
<router-link to="/MyInput">MyInput</router-link> |
|
|
50
|
+
|
|
51
|
+
<router-link to="/testAttrs">testAttrs</router-link> |
|
|
52
|
+
</nav>
|
|
53
|
+
<router-view></router-view>
|
|
54
|
+
</template>
|
|
55
|
+
<style>
|
|
56
|
+
.box {
|
|
57
|
+
margin: 20px 0;
|
|
58
|
+
}
|
|
59
|
+
</style>
|
package/src/ChildCom.vue
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<button class="btn" @click="onClick" v-bind="$attrs">click me</button>
|
|
4
|
+
<br />
|
|
5
|
+
<span>Fallthrough attribute: {{ $attrs }}</span>
|
|
6
|
+
</div>
|
|
7
|
+
</template>
|
|
8
|
+
|
|
9
|
+
<script setup>
|
|
10
|
+
import { useAttrs } from "vue";
|
|
11
|
+
defineOptions({
|
|
12
|
+
inheritAttrs: false,
|
|
13
|
+
});
|
|
14
|
+
defineProps({
|
|
15
|
+
msg: {
|
|
16
|
+
type: String,
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
const attrs = useAttrs();
|
|
20
|
+
console.log(attrs);
|
|
21
|
+
const onClick = () => {
|
|
22
|
+
console.log("子组件");
|
|
23
|
+
};
|
|
24
|
+
</script>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<template v-for="(item, index) in data.items">
|
|
4
|
+
<slot :name="`id:${item.id}`" />
|
|
5
|
+
<slot :name="`$id:${item.id}`" />
|
|
6
|
+
|
|
7
|
+
<render-form-item
|
|
8
|
+
:ref="
|
|
9
|
+
(el) => {
|
|
10
|
+
customComponent[`formItem-${item.id}`] = el;
|
|
11
|
+
}
|
|
12
|
+
"
|
|
13
|
+
:prop="`${data.id}.${item.id}`"
|
|
14
|
+
:data="item"
|
|
15
|
+
:value="value"
|
|
16
|
+
:item-value="itemValue[item.id]"
|
|
17
|
+
:disabled="disabled"
|
|
18
|
+
:readonly="readonly"
|
|
19
|
+
:options="options[item.id]"
|
|
20
|
+
@updateValue="updateValue"
|
|
21
|
+
/>
|
|
22
|
+
</template>
|
|
23
|
+
</div>
|
|
24
|
+
</template>
|
|
25
|
+
<script setup>
|
|
26
|
+
import RenderFormItem from "./render-form-item.vue";
|
|
27
|
+
const emit = defineEmits(["updateValue"]);
|
|
28
|
+
import { ref } from "vue";
|
|
29
|
+
let props = defineProps({
|
|
30
|
+
data: Object,
|
|
31
|
+
itemValue: {},
|
|
32
|
+
value: Object,
|
|
33
|
+
disabled: Boolean,
|
|
34
|
+
readonly: Boolean,
|
|
35
|
+
options: Object,
|
|
36
|
+
});
|
|
37
|
+
let customComponent = ref([]);
|
|
38
|
+
const updateValue = ({ id, value }) => {
|
|
39
|
+
emit("updateValue", {
|
|
40
|
+
id: props.data.id,
|
|
41
|
+
value: {
|
|
42
|
+
...props.itemValue,
|
|
43
|
+
[id]: value,
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
defineExpose({ customComponent });
|
|
48
|
+
</script>
|