近幾天來了個緊急項目,想要作一個內部版本的問卷星。至關於能夠編輯問卷並提供問卷展現,數據統計的這麼一個平臺。整個項目耗時不長,本着積澱和積累的原則,將過程當中的思路和收穫進行一下沉澱。因爲公司緣由,代碼還沒有開源。html
不過沉澱了個動態配置表單的嘗試: github,用於後臺快速開發表單等需求,搭配element-ui進行使用,同時可經過後臺進行配置生成表單等。vue
問卷編輯功能大概須要一下幾點:git
根據不一樣題型添加問題github
區分問題的必選性ajax
問題排序,刪除,複製功能vuex
選擇題的選項編輯,排序,刪除功能element-ui
問卷渲染數組
生成問卷二維碼數據結構
or
預覽ui
使用element進行後臺以及問卷表單渲染是再合適不過的了。極大的節省了須要進行表單樣式修改的時間,同時,讓動態渲染表單成爲一件可能且容易的事情。
恰好在項目以前,有過一次動態配置表單的嘗試: github 經過字段自動生成表單及驗證。但此時的數據格式至關於在後臺已經肯定好的,針對可變切頻繁變更的表單結構,肯定數據結構以下:
data: { title: 問卷名稱 desc: 問卷描述 questionList: [ { type: 問題類型, label: 問題描述, required: 必選性, options: [ //選項 { label: 選項內容, value: 選項值 } ... ] } ... ] }
最簡單的 v-if 模式來知足咱們的需求,以前有想過使用is進行渲染,可是不一樣表單配置項相差很大,很難進行通用。所以採用相似如下這種方式,配置詳情可見element官網。
<!-- 填空題 --> <div v-if="question.type === 'input' || question.type === 'textarea'" class="question-content-wrap"> <el-row> <el-col :xs="8" :sm="10"> <el-input v-model="question.value" :autosize="{ minRows: 2, maxRows: 4}" class="question-input" :type="question.type"> </el-input> </el-col> </el-row> </div>
很簡單就能夠將表單根據配置渲染出來啦:
思路理清楚了,就能夠動手實踐啦!
首先,我須要各個問題的基本配置模板,以便於每次直接向questionList中直接添加相應的內容,爲了方便存儲及使用,將其放在store中,當
const state = { baseSet: { radio: { type: 'radio', label: '單選題', required: true, options: [...] }, checkbox: ... input: ... } } //添加問題時,直接push進數組便可 const mutations = [ //添加問題 ADDQUESTIONLIST(state, data) { state.qss.questionList.push(data); } ] //添加問題方法 addQuestion(type) { this.addQuestionList(this. baseSet[type]); },
使用getter獲取到咱們對應的baseSet對象時,此對象爲引用類型,而且,對象的屬性,如options也一樣爲引用類型。咱們若不進行處理,則會出現,建立兩個相同類型的問題時,對其中某一問題選項進行修改,另外一個選項也會進行修改。 所以咱們須要對base對象進行簡單的拷貝(只進行到數組內容便可)
export const clone = function(obj) { var newObj = {}; for (let key in obj) { var target = obj[key]; if (Object.prototype.toString.call(target) === "[object Object]") { newObj[key] = clone(target); } else { if (Object.prototype.toString.call(target) === "[object Array]") { newObj[key] = target.slice(0); } else { newObj[key] = target; } } } return newObj; } addQuestion(type) { this.addQuestionList(clone(this. baseSet[type])); },
這三點基本就是簡單的數組操做啦,此時的問題數據依舊是引用類型,直接對引用數組進行操做便可。簡單的上移,下移排序,使用splice便可實現。其實這三點都是用splice實現的哈。
deleteQuestion(index) { this.data.questionList.splice(index, 1); }, copyQuestion(index) { let list = this.data.questionList; //複製時,一樣須要對引用對象進行深拷貝 list.splice(index, 1, list[index], clone(list[index])); }, moveQuestion(index, direct) { let list = this.data.questionList; if(direct === 'up') { if(index < 1) { this.$toast('已是第一項!'); return; } list.splice(index - 1, 2, list[index], list[index - 1]); } else { if(index >= list.length - 1) { this.$toast('已是最後一項!'); return; } list.splice(index, 2, list[index + 1], list[index]); } }
使用qrcode.js,感謝大佬們爲小輩們造出這麼多好用的輪子,讓咱們站在巨人的肩膀上前行!
咱們都知道,針對Vue2.0後,使用computed獲取getters or state,而針對計算屬性,咱們是沒法進行寫操做的,像這樣
computed: { ...mapState({ qss: state => state.qss, base: state => state.base }) }, //如下代碼是無效的 this.qss = 2;
所以,咱們更沒法將qss屬性直接綁定在v-model上,非常苦惱。同事的通常處理方式是在data中書寫相同的屬性,在路由進入時對其進行初始化,當其修改時再寫回store。這樣寫起來未免有點麻煩且不穩當。那麼,該如何解決呢?
其實很簡單,能夠交給父組件呀。
咱們經常會聽到一個詞,單向數據流,大概意思就是讓數據單一方向流動,咱們只對數據源進行修改,再讓數據從數據源依次流動到子組件進行UI渲染。
其實就像咱們使用ajax獲取數據時,統一交給父組件同樣,咱們將統一獲取到的數據,使用props進行向下分發便可,使用vuex亦是如此。子組件值進行對應值的修改。而針對props,v-model能夠很方便的對其進行修改了。固然這些只是個人一點理解,若是有異議,能夠一塊兒討論哈。