手寫程式碼?
meta(json)需要手寫嗎?別鬧,手寫多麻煩呀,我這麼懶怎麼可能手寫,這輩子都別想,所以要弄個工具出來,我們們說幹就幹。
這個工具,說白了本身就是一個表單,一個meta屬性對應一個meta的屬性,合在一起就是一個完整的meta了,只是不同的元件屬性不同,需要區分對待不能混為一談。
先看看工具啥樣的
【工具截圖】
是不是挺難看?我沒有藝術細胞,大家多擔待。等找到支援3.0的UI,就可以做一個漂亮的頁面了,現在先實現功能。
左面是表單,右面是控制元件展示、控制元件值以及生成的meta。
流程
- 父級把需要生成的meta,通過屬性傳遞進來,
- 把屬性值設定給內部的固定meta,
- 根據控制元件型別篩選出來需要的屬性。
- 然後依據固定meta生成表單,顯示需要的屬性。
- 填寫內容生成需要的json
前四步都是內部流程,不用管,只需要第五步填內容即可。
程式碼
雞生蛋還是蛋生雞?
想做一個工具生成meta,然後這個工具還想用meta繫結的方式來做。
似乎是個死迴圈。
meta
破解之法就是,先寫個簡潔的meta
{
"101": {
"controlId": 101,
"colName": "controlId",
"controlType": 101,
}
}
然後複製三份,用這三個先繫結出來一個表單,然後在加屬性,在繫結表單,一層一層迴圈出來的。
{
"101": {
"controlId": 101,
"colName": "controlId",
"controlType": 131,
"isClear": false,
"defaultValue": "",
"autofocus": false,
"disabled": false,
"required": true,
"readonly": false,
"pattern": "",
"class": "",
"placeholder": "請輸入元件編號",
"title": "元件編號",
"autocomplete": "on",
"min": "0",
"max": "9999",
"step": "1"
}
這是一個完整的meta,把一個表單需要的meta都籌齊了就可以召喚神龍了。好吧,是建立表單。
表單程式碼
<template>
<div class="home">
<div><h1>表單元素元件meta生成工具</h1></div>
<div style="background-color:#dddddd;height:600px;width:400px;float:left;">
<!--表單-->
<table>
<tr v-for="(key,index) in trList" :key="index"><!--遍歷需要的meta-->
<td align="right">{{helpMeta[key].colName}}:<!--名稱-->
</td>
<td align="left"><!--控制元件-->
<nfInput :modelValue="modelValue[helpMeta[key].colName]" :meta="helpMeta[key]" @getvalue="sendValue"/>
{{helpMeta[key].title}}
</td>
</tr>
</table>
</div>
</div>
</template>
用v-for迴圈,把表單迴圈出來,我這麼懶,才不會一行一行的寫tr呢。
因為每種元件需要的屬性不同,所以需要做個陣列存放元件需要的屬性的ID,這樣迴圈陣列即可繫結出來需要的屬性了。
meta的模板
<template>
<div class="home">
<div align="left" style="padding:5px;background-color:#FFFFEE;height:600px;width:400px;float:left;">
<!--效果和json-->
測試:<nfInput v-model="testValue" :meta="baseMeta" /> ==》 {{testValue}}
<div align="left" style="padding:15px;background-color:#FFEEEE;height:400px;width:400px;clear:both">
{<br>
<span v-for="(item, key, index) in tmpMeta" :key="index">
<span v-if="typeof item === 'number' && !isNaN(item)"> "{{key}}": {{item}}, <br></span>
<span v-if="typeof item === 'string'"> "{{key}}": "{{item}}", <br></span>
<span v-if="typeof(item) ==='boolean'"> "{{key}}": {{item}}, <br></span>
<span v-if="typeof(item) ==='object'">
"{{key}}": [<br>
<span v-for="(opt, index) in item" :key="'opt'+index"> {{opt}}, <br></span>
]<br>
</span>
</span>
}
</div>
</div>
</div>
</template>
這是生成需要的json的模板,直接用模板的方式來實現,這樣可以根據需要調整格式。
比如json檔案要求key要用雙引號引起來,而js裡面key就不需要雙引號,
而eslint又要求字串只能用單引號。
要求不一樣怎麼辦?做不同的模板唄。
data
data: function () {
return {
testValue: '測試',
helpMeta: {}, // 建立表單需要的meta
baseMeta: { // 固定屬性的
controlId: 101,
colName: 'abc',
controlType: 101,
isClear: true,
defaultValue: '',
autofocus: false,
disabled: false,
required: true,
readonly: false,
pattern: '',
class: '',
placeholder: '請輸入',
title: '',
autocomplete: 'on',
size: 10,
maxlength: 10,
min: 0,
max: 9999,
step: 1,
rows: 5,
cols: 50,
optionKey: 'beixuan',
optionList: []
},
tmpMeta: {}, // 按需生成屬性的
trList: [103],
type: {}, // 各種元件型別需要的屬性ID陣列
numberList: []
}
}
created: function () {
// 讀取json
const json = require('@/components/metahelp.json')
// 給data賦值
this.helpMeta = json.helpMeta
this.helpMeta[103].optionList = json.dic.ControlTypeList
this.type = json.type
this.trList = this.type[103] // 預設使用文字框的屬性
}
發現個問題,在setup裡面似乎無法讀取屬性(prop)的值,所以還是用data、created 的方式來做。
變幻
methods: {
sendValue: function (value, colName) {
// 根據欄位名判斷,設定需要的屬性
if (colName === 'controlType') {
this.trList = this.type[value]
}
// 給對應欄位賦值
this.baseMeta[colName] = value
// 根據型別拼接物件
this.tmpMeta = {}
for (var i = 0; i < this.trList.length; i += 1) {
var item = this.trList[i]
var key = this.helpMeta[item].colName
this.tmpMeta[key] = this.baseMeta[key]
}
// 提交給父級元件
this.$emit('update:modelValue', this.tmpMeta)
}
}
這個是依據元件型別拼接需要的屬性,然後提交給父級元件的程式碼
這段確實有點繞,自己都暈。因為我懶,不想寫那麼多程式碼。
one more thing
寫這段程式碼,花了好長時間,主要是對vue不太熟悉,另外上了點年齡,反應有點慢。
寫這篇部落格一比較卡文,原因就是思路很混亂,這個就比較狠危險了。
對了,完整程式碼在這裡: https://github.com/naturefwvue/nfComponents