整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          牛X Vue+element-ui 可視化表單設(shè)計生成器

          天給大家推薦一款超逼格的Vue可拖拽表單設(shè)計器組件FormGenerator。

          form-generator 基于 Vue.js+ElementUI 高效表單設(shè)計組件,star高達(dá)1.7K+

          功能特點

          • 可視化設(shè)計表單
          • 一鍵生成原生的vue單頁表單代碼,保持100%拓展性
          • 在線編輯器修改生成的代碼,并實時預(yù)覽
          • 表單柵格化布局
          • 支持表單校驗
          • 快速查閱組件的官方文檔

          vscode插件

          在上文的設(shè)計器的基礎(chǔ)上,封裝了一個vscode插件。突破網(wǎng)頁不能寫入文件的限制。

          請在vscode中搜索 jakHuang 或 Form Generator Plugin

          安裝使用

          # 下載項目
          git clone https://github.com/JakHuang/form-generator.git
          
          # 進(jìn)入目錄
          cd form-generator
          
          # 安裝依賴
          npm install
          
          # 本地開發(fā)
          npm run dev
          
          # 構(gòu)建
          npm run build

          支持生成的代碼直接運行在基于Element的vue項目中。也可導(dǎo)出JSON表單,使用配套的解析器將JSON解析成真實的表單。

          # 預(yù)覽地址
          https://mrhj.gitee.io/form-generator/
          
          # 倉庫地址
          https://github.com/JakHuang/form-generator

          ok,就分享到這里。希望對大家有所幫助,歡迎一起交流討論!

          眾號【傳智播客博學(xué)谷】回復(fù)關(guān)鍵詞:前端 PS Java(100G) Python(80G) 大數(shù)據(jù) 區(qū)塊鏈 測試 PPT JS(40g+300教程) HTML 簡歷 領(lǐng)取相關(guān)學(xué)習(xí)資料!

          一、HTML

          1、<image>標(biāo)簽上title屬性與alt屬性的區(qū)別是什么?

          alt屬性是為了給那些不能看到你文檔中圖像的瀏覽者提供文字說明的。且長度必須少于100個英文字符或者用戶必須保證替換文字盡可能的短。

          這包括那些使用本來就不支持圖像顯示或者圖像顯示被關(guān)閉的瀏覽器的用戶,視覺障礙的用戶和使用屏幕閱讀器的用戶等。

          title屬性為設(shè)置該屬性的元素提供建議性的信息。使用title屬性提供非本質(zhì)的額外信息。參考《alt和title屬性的區(qū)別及應(yīng)用》

          2、分別寫出以下幾個HTML標(biāo)簽:文字加粗、下標(biāo)、居中、字體

          加粗:<b>、<strong>

          下標(biāo):<sub>

          居中:<center>

          字體:<font>、<basefont>、參考《HTML標(biāo)簽列表》

          3、請寫出至少5個html5新增的標(biāo)簽,并說明其語義和應(yīng)用場景

          section:定義文檔中的一個章節(jié)

          nav:定義只包含導(dǎo)航鏈接的章節(jié)

          header:定義頁面或章節(jié)的頭部。它經(jīng)常包含 logo、頁面標(biāo)題和導(dǎo)航性的目錄。

          footer:定義頁面或章節(jié)的尾部。它經(jīng)常包含版權(quán)信息、法律信息鏈接和反饋建議用的地址。

          aside:定義和頁面內(nèi)容關(guān)聯(lián)度較低的內(nèi)容——如果被刪除,剩下的內(nèi)容仍然很合理。

          參考《HTML5 標(biāo)簽列表》

          4、請說說你對標(biāo)簽語義化的理解?

          a. 去掉或者丟失樣式的時候能夠讓頁面呈現(xiàn)出清晰的結(jié)構(gòu)

          b. 有利于SEO:和搜索引擎建立良好溝通,有助于爬蟲抓取更多的有效信息:爬蟲依賴于標(biāo)簽來確定上下文和各個關(guān)鍵字的權(quán)重;

          c. 方便其他設(shè)備解析(如屏幕閱讀器、盲人閱讀器、移動設(shè)備)以意義的方式來渲染網(wǎng)頁;

          d. 便于團(tuán)隊開發(fā)和維護(hù),語義化更具可讀性,遵循W3C標(biāo)準(zhǔn)的團(tuán)隊都遵循這個標(biāo)準(zhǔn),可以減少差異化。

          5、Doctype作用? 嚴(yán)格模式與混雜模式如何區(qū)分?它們有何意義?

          聲明位于文檔中的最前面,處于 標(biāo)簽之前。告知瀏覽器以何種模式來渲染文檔。

          嚴(yán)格模式的排版和 JS 運作模式是,以該瀏覽器支持的最高標(biāo)準(zhǔn)運行。

          在混雜模式中,頁面以寬松的向后兼容的方式顯示。模擬老式瀏覽器的行為以防止站點無法工作。

          DOCTYPE不存在或格式不正確會導(dǎo)致文檔以混雜模式呈現(xiàn)。

          6、你知道多少種Doctype文檔類型?

          標(biāo)簽可聲明三種 DTD 類型,分別表示嚴(yán)格版本、過渡版本以及基于框架的 HTML 文檔。

          HTML 4.01 規(guī)定了三種文檔類型:Strict、Transitional 以及 Frameset。

          XHTML 1.0 規(guī)定了三種 XML 文檔類型:Strict、Transitional 以及 Frameset。

          Standards (標(biāo)準(zhǔn))模式(也就是嚴(yán)格呈現(xiàn)模式)用于呈現(xiàn)遵循最新標(biāo)準(zhǔn)的網(wǎng)頁,

          Quirks(包容)模式(也就是松散呈現(xiàn)模式或者兼容模式)用于呈現(xiàn)為傳統(tǒng)瀏覽器而設(shè)計的網(wǎng)頁。

          7、HTML與XHTML——二者有什么區(qū)別

          a. XHTML 元素必須被正確地嵌套。

          b. XHTML 元素必須被關(guān)閉。

          c. 標(biāo)簽名必須用小寫字母。

          d. XHTML 文檔必須擁有根元素。

          參考《XHTML 與 HTML 之間的差異》

          8、html5有哪些新特性、移除了那些元素?

          a. HTML5 現(xiàn)在已經(jīng)不是 SGML 的子集,主要是關(guān)于圖像,位置,存儲,多任務(wù)等功能的增加。

          b. 拖拽釋放(Drag and drop) API

          c. 語義化更好的內(nèi)容標(biāo)簽(header,nav,footer,aside,article,section)

          d. 音頻、視頻API(audio,video)

          e. 畫布(Canvas) API

          f. 地理(Geolocation) API

          g. 本地離線存儲 localStorage 長期存儲數(shù)據(jù),瀏覽器關(guān)閉后數(shù)據(jù)不丟失

          h. sessionStorage 的數(shù)據(jù)在頁面會話結(jié)束時會被清除

          i. 表單控件,calendar、date、time、email、url、search

          j. 新的技術(shù)webworker, websocket等

          移除的元素:

          a. 純表現(xiàn)的元素:basefont,big,center, s,strike,tt,u;

          b. 對可用性產(chǎn)生負(fù)面影響的元素:frame,frameset,noframes;

          9、iframe的優(yōu)缺點?

          優(yōu)點:

          a. 解決加載緩慢的第三方內(nèi)容如圖標(biāo)和廣告等的加載問題

          b. iframe無刷新文件上傳

          c. iframe跨域通信

          缺點:

          a. iframe會阻塞主頁面的Onload事件

          b. 無法被一些搜索引擎索引到

          c. 頁面會增加服務(wù)器的http請求

          d. 會產(chǎn)生很多頁面,不容易管理。

          參考《iframe的一些記錄》

          10、Quirks模式是什么?它和Standards模式有什么區(qū)別?

          在寫程序時我們也會經(jīng)常遇到這樣的問題,如何保證原來的接口不變,又提供更強(qiáng)大的功能,尤其是新功能不兼容舊功能時。IE6以前的頁面大家都不會去寫DTD,所以IE6就假定 如果寫了DTD,就意味著這個頁面將采用對CSS支持更好的布局,而如果沒有,則采用兼容之前的布局方式。這就是Quirks模式(怪癖模式,詭異模式,怪異模式)。

          區(qū)別:總體會有布局、樣式解析和腳本執(zhí)行三個方面的區(qū)別。

          a. 盒模型:在W3C標(biāo)準(zhǔn)中,如果設(shè)置一個元素的寬度和高度,指的是元素內(nèi)容的寬度和高度,而在Quirks 模式下,IE的寬度和高度還包含了padding和border。

          b. 設(shè)置行內(nèi)元素的高寬:在Standards模式下,給等行內(nèi)元素設(shè)置wdith和height都不會生效,而在quirks模式下,則會生效。

          c. 設(shè)置百分比的高度:在standards模式下,一個元素的高度是由其包含的內(nèi)容來決定的,如果父元素沒有設(shè)置百分比的高度,子元素設(shè)置一個百分比的高度是無效的用

          d. 設(shè)置水平居中:使用margin:0 auto在standards模式下可以使元素水平居中,但在quirks模式下卻會失效。

          11、請闡述table的缺點

          a. 太深的嵌套,比如table>tr>td>h3,會導(dǎo)致搜索引擎讀取困難,而且,最直接的損失就是大大增加了冗余代碼量。

          b. 靈活性差,比如要將tr設(shè)置border等屬性,是不行的,得通過td

          c. 代碼臃腫,當(dāng)在table中套用table的時候,閱讀代碼會顯得異常混亂

          d. 混亂的colspan與rowspan,用來布局時,頻繁使用他們會造成整個文檔順序混亂。

          e. 不夠語義

          參考《為什么說table表格布局不好?》

          12、簡述一下src與href的區(qū)別

          src用于替換當(dāng)前元素;href用于在當(dāng)前文檔和引用資源之間確立聯(lián)系。

          src是source的縮寫,指向外部資源的位置,指向的內(nèi)容將會嵌入到文檔中當(dāng)前標(biāo)簽所在位置

          href是Hypertext Reference的縮寫,指向網(wǎng)絡(luò)資源所在位置,建立和當(dāng)前元素(錨點)或當(dāng)前文檔(鏈接)之間的鏈接

          公眾號【傳智播客博學(xué)谷】回復(fù)關(guān)鍵詞:前端 PS Java Python 大數(shù)據(jù) 區(qū)塊鏈 測試 PPT JS HTML 簡歷 領(lǐng)取相關(guān)學(xué)習(xí)資料!

          于Vue和Quasar的前端SPA項目實戰(zhàn)之拖拽表單定制(十六)

          回顧

          通過前一篇文章 「開源免費」基于Vue和Quasar的動態(tài)表單設(shè)計器(五)的介紹,實現(xiàn)了元數(shù)據(jù)中動態(tài)表單設(shè)計功能,支持常見的數(shù)據(jù)類型和索引,然后實現(xiàn)了動態(tài)表單的crud增刪改查功能,所有的表單頁面都是默認(rèn)的風(fēng)格。本文主要介紹拖拽表單定制功能,通過拖拽的方式定制表單錄入和編輯頁面,滿足了個性化需求。

          簡介

          針對元數(shù)據(jù)表的每個字段,通過拖拽方式?jīng)Q定是否顯示或者隱藏,然后還可以配置顯示的寬度。最終以json格式保存到后臺數(shù)據(jù)庫,運行時根據(jù)配置動態(tài)渲染錄入和編輯表單form頁面。針對不同的設(shè)備(電腦,平板,手機(jī))都可以單獨定制。

          UI界面

          頁面構(gòu)建


          頁面構(gòu)建

          運行時


          運行時

          代碼

          說明

          采用開源框架vuesortable,基于vue的實現(xiàn)排序,支持拖拽。頁面構(gòu)建分為左中右三個部分,左邊為候選字段,中間為需要顯示的字段,右邊可以針對每個字段單獨設(shè)置一些屬性,比如寬度等。

          數(shù)據(jù)表

          創(chuàng)建表單tableFormBuilder,用于存儲頁面構(gòu)建json數(shù)據(jù),包括類型type、設(shè)備device、內(nèi)容body等字段, 充分利用crudapi功能,API部分零代碼實現(xiàn)。

          tableFormBuilder


          tableFormBuilder

          核心代碼

          頁面構(gòu)建

          <draggable
            class="dragArea list-group row"
            :list="selectedList"
            group="people"
            @change="log"
          >
            <div class="list-group-item q-pa-md" 
              v-for="formElement in selectedList"
              :key="formElement.columnId"
              :class="formElement | classFormat(currentElement)"
              @click="selectForEdit(formElement)"
            > 
              <div>
                <div 
                  v-bind:class="{ 'required': !formElement.column.nullable}">
                  {{formElement.column.caption}}:
                </div>
                <q-input v-if="isStringType(formElement)"
                  readonly
                  :placeholder="formElement.column.description"
                  :type="formElement.isPwd ? 'password' : 'text'"
                  v-model="formElement.column.value" >
                  <template v-slot:append v-if="!formElement.isText" >
                    <q-icon
                      :name="formElement.isPwd ? 'visibility_off' : 'visibility'"
                      class="cursor-pointer"
                      @click="formElement.isPwd = !formElement.isPwd"
                    />
                  </template>
                </q-input>
          
                <q-editor readonly v-else-if="isTextType(formElement)"
                  v-model="textValue"
                  :placeholder="formElement.column.description" >
                </q-editor>
          
                <q-input v-else-if="isDateTimeType(formElement)" readonly>
                  <template v-slot:prepend>
                    <q-icon name="event" class="cursor-pointer">
                      <q-popup-proxy ref="qDateProxy" transition-show="scale" transition-hide="scale">
                        <q-date
                        mask="YYYY-MM-DD HH:mm:ss"
                        @input="hideRefPopProxyAction('qDateProxy')" />
                      </q-popup-proxy>
                    </q-icon>
                  </template>
          
                  <template v-slot:append>
                    <q-icon name="access_time" class="cursor-pointer">
                      <q-popup-proxy ref="qTimeProxy" transition-show="scale" transition-hide="scale">
                        <q-time mask="YYYY-MM-DD HH:mm:ss"
                        format24h with-seconds
                        @input="hideRefPopProxyAction('qTimeProxy')" />
                      </q-popup-proxy>
                    </q-icon>
                  </template>
                </q-input>
          
                <q-input v-else-if="isDateType(formElement)" readonly>
                  <template v-slot:append>
                    <q-icon name="event" class="cursor-pointer">
                      <q-popup-proxy ref="qDateProxy" transition-show="scale" transition-hide="scale">
                        <q-date
                        mask="YYYY-MM-DD"
                        @input="hideRefPopProxyAction('qDateProxy')" />
                      </q-popup-proxy>
                    </q-icon>
                  </template>
                </q-input>
          
                <q-input v-else-if="isTimeType(formElement)" readonly>
                  <template v-slot:append>
                    <q-icon name="access_time" class="cursor-pointer">
                      <q-popup-proxy ref="qTimeProxy" transition-show="scale" transition-hide="scale">
                        <q-time  mask="HH:mm:ss"
                        format24h with-seconds
                        @input="hideRefPopProxyAction('qTimeProxy')" />
                      </q-popup-proxy>
                    </q-icon>
                  </template>
                </q-input>
          
                <q-toggle v-else-if="isBoolType(formElement)" readonly
                  v-model="formElement.column.value">
                </q-toggle>
          
                <q-input readonly
                  v-else-if="isNumberType(formElement)"
                  :placeholder="formElement.column.description"
                  type="number"
                  v-model="formElement.column.value" >
                </q-input>
          
                <CFile v-else-if="isAttachmentType(formElement)"
                  v-model="formElement.column.value" >
                </CFile>
          
                <q-input v-else
                  readonly
                  :placeholder="formElement.column.description"
                  :type="formElement.isPwd ? 'password' : 'text'"
                  v-model="formElement.column.value" >
                  <template v-slot:append v-if="!formElement.isText" >
                    <q-icon
                      :name="formElement.isPwd ? 'visibility_off' : 'visibility'"
                      class="cursor-pointer"
                      @click="formElement.isPwd = !formElement.isPwd"
                    />
                  </template>
                </q-input>
              </div>
              <div class="row reverse editable-element-action-buttons">
                <div class="justify-end q-pt-xs">
                  <q-btn 
                    @click="deleteElement(formElement)"
                    v-if="isSelectedForEdit(formElement)" 
                    class="editable-element-button" 
                    color="red" 
                    icon="delete" 
                    round unelevated  size="xs">
                    <q-tooltip>移除</q-tooltip>
                  </q-btn>
                </div>
              </div>
            </div>
          </draggable>
          

          通過draggable標(biāo)簽實現(xiàn)

          運行時渲染

          <div v-if="selectedList.length > 0" class="row">
            <div class="list-group-item q-pa-md" 
              v-for="formElement in selectedList"
              :key="formElement.columnId"
              :class="formElement | classFormat">
              <div>
                <div 
                  v-bind:class="{ 'required': !formElement.column.nullable}">
                  {{formElement.column.caption}}:
                </div>
          
                <div class="row items-baseline content-center"
                  style="border-bottom: 1px solid rgba(0,0,0,0.12)" 
                  v-if="formElement.column.relationTableName">
                  <div class="col-11">
                    <span>{{ formElement.column.value | relationDataFormat(formElement.column) }}</span>
                  </div>
                  <div class="col-1">
                    <q-btn round dense flat icon="zoom_in" 
                    @click="openDialogClickAction(formElement.column)" />
                  </div>
                </div>
          
                <q-input v-else-if="isStringType(formElement.column.dataType)"
                  v-model="formElement.column.value"
                  :placeholder="formElement.column.description"
                  :type="formElement.isPwd ? 'password' : 'text'" >
                  <template v-slot:append v-if="!formElement.isText" >
                    <q-icon
                      :name="formElement.isPwd ? 'visibility_off' : 'visibility'"
                      class="cursor-pointer"
                      @click="formElement.isPwd = !formElement.isPwd"
                    />
                  </template>
                </q-input>
          
                <q-editor  v-else-if="isTextType(formElement.column.dataType)"
                  v-model="formElement.column.value"
                  :placeholder="formElement.column.description" >
                </q-editor>
          
                <q-input v-else-if="isDateTimeType(formElement.column.dataType)"
                  v-model="formElement.column.value" >
                  <template v-slot:prepend>
                    <q-icon name="event" class="cursor-pointer">
                      <q-popup-proxy ref="qDateProxy" transition-show="scale" transition-hide="scale">
                        <q-date v-model="formElement.column.value"
                        mask="YYYY-MM-DD HH:mm:ss"
                        @input="hideRefPopProxyAction('qDateProxy')" />
                      </q-popup-proxy>
                    </q-icon>
                  </template>
          
                  <template v-slot:append>
                    <q-icon name="access_time" class="cursor-pointer">
                      <q-popup-proxy ref="qTimeProxy" transition-show="scale" transition-hide="scale">
                        <q-time  v-model="formElement.column.value"
                        mask="YYYY-MM-DD HH:mm:ss"
                        format24h with-seconds
                        @input="hideRefPopProxyAction('qTimeProxy')" />
                      </q-popup-proxy>
                    </q-icon>
                  </template>
                </q-input>
          
                 <q-input v-else-if="isDateType(formElement.column.dataType)" 
                  v-model="formElement.column.value">
                  <template v-slot:append>
                    <q-icon name="event" class="cursor-pointer">
                      <q-popup-proxy ref="qDateProxy" transition-show="scale" transition-hide="scale">
                        <q-date  v-model="formElement.column.value"
                        mask="YYYY-MM-DD"
                        @input="hideRefPopProxyAction('qDateProxy')" />
                      </q-popup-proxy>
                    </q-icon>
                  </template>
                </q-input>
          
                <q-input v-else-if="isTimeType(formElement.column.dataType)"
                 v-model="formElement.column.value" >
                  <template v-slot:append>
                    <q-icon name="access_time" class="cursor-pointer">
                      <q-popup-proxy ref="qTimeProxy" transition-show="scale" transition-hide="scale">
                        <q-time   v-model="formElement.column.value" 
                        mask="HH:mm:ss"
                        format24h with-seconds
                        @input="hideRefPopProxyAction('qTimeProxy')" />
                      </q-popup-proxy>
                    </q-icon>
                  </template>
                </q-input>
          
                <q-toggle v-else-if="isBoolType(formElement.column.dataType)"
                 v-model="formElement.column.value" >
                </q-toggle>
          
                <q-input 
                  v-else-if="isNumberType(formElement.column.dataType)"
                  v-model="formElement.column.value"
                  :placeholder="formElement.column.description"
                  type="number">
                </q-input>
          
                <CFile v-else-if="isAttachmentType(formElement.column.dataType)"
                 v-model="formElement.column.value"
                 @input="(data)=>{
                  formElement.column.value = data.url;
                 }"></CFile>
          
                <q-input v-else
                  v-model="formElement.column.value"
                  :placeholder="formElement.column.description"
                  :type="formElement.isPwd ? 'password' : 'text'" >
                  <template v-slot:append v-if="!formElement.isText" >
                    <q-icon
                      :name="formElement.isPwd ? 'visibility_off' : 'visibility'"
                      class="cursor-pointer"
                      @click="formElement.isPwd = !formElement.isPwd"
                    />
                  </template>
                </q-input>
              </div>
            </div>
          </div>
          

          判斷是否存在定制頁面,如果存在動態(tài)渲染,否則采用默認(rèn)頁面布局。

          例子

          以產(chǎn)品為例,配置好錄入頁面之后,運行時原來的默認(rèn)錄入頁面用新的頁面代替,新的表單頁面和之前配置的表單頁面一致,功能不受影響,可以正常的錄入數(shù)據(jù)。

          小結(jié)

          本文主要通過拖拽方式實現(xiàn)表單定制功能,使用非常方便,零代碼定制表單錄入和編輯頁面,滿足了個性化需求,整個過程無需寫代碼。

          crudapi簡介

          crudapi是crud+api組合,表示增刪改查接口,是一款零代碼可配置的產(chǎn)品。使用crudapi可以告別枯燥無味地增刪改查代碼,讓您更加專注業(yè)務(wù),節(jié)約大量成本,從而提高工作效率。crudapi的目標(biāo)是讓處理數(shù)據(jù)變得更簡單,所有人都可以免費使用!無需編程,通過配置自動生成crud增刪改查RESTful API,提供后臺UI管理業(yè)務(wù)數(shù)據(jù)?;谥髁鞯拈_源框架,擁有自主知識產(chǎn)權(quán),支持二次開發(fā)。crudapi屬于產(chǎn)品級的零代碼平臺,不同于自動代碼生成器,不需要生成Controller、Service、Repository、Entity等業(yè)務(wù)代碼,程序運行起來就可以使用,真正0代碼,可以覆蓋基本的和業(yè)務(wù)無關(guān)的CRUD RESTful API。

          請點擊官網(wǎng)原文鏈接了解更多和源碼:基于Vue和Quasar的前端SPA項目實戰(zhàn)之拖拽表單定制(十六) | crudapi


          主站蜘蛛池模板: 中文字幕一区在线观看| 国产一区内射最近更新| 精品一区二区三区在线观看| 国产在线观看一区精品| 国产成人高清亚洲一区久久| 国产激情一区二区三区四区| 日本精品夜色视频一区二区| 久久精品无码一区二区三区| 色噜噜狠狠一区二区| 国产日韩视频一区| 无码人妻一区二区三区免费n鬼沢| 精品黑人一区二区三区| 老湿机一区午夜精品免费福利| 熟女少妇精品一区二区| 亚洲av乱码中文一区二区三区| 一本岛一区在线观看不卡| 亚洲国产一区二区三区青草影视| 天堂一区二区三区精品| 国产在线精品一区二区三区不卡| 亚洲一区在线观看视频| 亚洲日本一区二区一本一道| 日韩人妻无码一区二区三区久久| 国模一区二区三区| 无码午夜人妻一区二区三区不卡视频| 无码视频免费一区二三区| 国产精品一区二区久久国产| 亚洲国产欧美国产综合一区 | 人妻久久久一区二区三区| 四虎成人精品一区二区免费网站| 秋霞午夜一区二区| 国产aⅴ精品一区二区三区久久| 无码国产精品一区二区免费vr| 色综合视频一区二区三区| 国内自拍视频一区二区三区| 日产一区日产2区| 日本在线观看一区二区三区| 亚洲天堂一区在线| 中文字幕人妻无码一区二区三区 | 国产波霸爆乳一区二区| 免费精品一区二区三区在线观看| 亚洲一区影音先锋色资源|