vue 填空题组件封装
生活随笔
收集整理的這篇文章主要介紹了
vue 填空题组件封装
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
目錄
1. 效果圖
2. 組件使用
3. 設計思路
1. 效果圖
首先上一張效果圖
需求就是給定題干,自定義答案的位置,然后用戶輸入后,可判斷答案的正確性,進行區別標注。
2. 組件使用
如圖所示,需要傳兩個參數,question和sign
question: '$莫聽$穿林打葉聲,何妨$吟嘯$且徐行。竹杖芒鞋輕勝馬,誰怕?一蓑煙雨$任平生$。', sign: '$'question是完成的題干,把答案用特殊的符號前后框起來,可框選多處。例如文字中橙色背景的答案
sign是自定義特殊的字符,以防止與題干所含的字符沖突
3. 設計思路
整體思路如下,
- step1:設計一個input框,用來監聽用戶的輸入
- step2:處理題干和答案,渲染出題目(文字)和答案(空格)
- step3:空格和底層的input綁定,監聽輸入后將文字渲染到空格中
- 初次之外還有些細節,例如輸入的空格focus的效果之類
4.組件代碼
累了,碼到這里不想細致寫了,直接干脆貼代碼好了
<template><div class="completion"><inputclass="answer-input"v-model="currentVal"ref="inputVal":maxlength="rightVal.join('').split('').length"v-on:input="setText"/><div class="single-text"v-for="(item, index) in blankAllList":key="index">{{ item.type !== 'input' ? item.content : '' }}<div class="blank-box" v-if="item.type === 'input'"><span v-for="itemIpt in item.content":key="itemIpt.index"ref="singleAnswer":class="['answer-text', focusIndex === itemIpt.index - 1 && focusRow === item.order - 1 ? 'span-focus': '']"@click="inputTextChange">{{ blankList[item.order - 1][itemIpt.index - 1] }}</span></div></div><div class="submit-btn" @click="rightCheck">確定</div><div class="answer-right" v-if="showRightBox"><p>正確答案:{{ rightVal.join('、') }}</p></div></div> </template><script> export default {name: "CompletionDemo",props: ['question', 'sign'],data() {return {blankAllList: [], // 完成題干blankList: [], // 輸入答案切割組rightVal: [], // 正確答案currentVal: '', // input實際輸入focusRow: -1,focusIndex: -1,showRightBox: false,}},mounted() {this.handleQuestion();},methods: {// 處理題干及答案handleQuestion() {let list = this.question.split(this.sign);let i = 1;this.blankAllList = [];this.rightVal = [];this.blankList = [];list.filter((item, index) => {if (index % 2 == 0) {item.split('').forEach(subItem => {this.blankAllList.push({type: 'txt', content: subItem})})} else {let param = {order: i,type: 'input',content: []};i++;item.split('').forEach((subItem, subIndex) => param.content.push({index: subIndex + 1}));this.blankAllList.push(param);this.rightVal.push(item)}});this.rightVal.forEach(() => {this.blankList.push([]);});console.log(this.blankAllList, this.rightVal);},// 判斷數組是否相等isArrEqual(obj, list) {return obj.length === list.length && obj.toString() === list.toString();},// 確定按鈕rightCheck() {const rightKey = this.rightVal.join('').split('');if (rightKey.length === this.currentVal.length) {let fult = this.isArrEqual(rightKey, this.currentVal)if (fult) {for (let i = 0; i < rightKey.length; i++) {let color = this.$refs['singleAnswer'][i]color.style.color = 'green'color.style.border = 'solid 2px #67c23a'}} else {for (let j = 0; j < rightKey.length; j++) {if (this.currentVal[j] != rightKey[j]) {let bhcolor = this.$refs['singleAnswer'][j]bhcolor.style.color = 'red'bhcolor.style.border = 'solid 2px #f56c6c'} else {let ycolor = this.$refs['singleAnswer'][j]ycolor.style.color = 'green'ycolor.style.border = 'solid 2px #67c23a'}}}} else {for (let k = 0; k < rightKey.length; k++) {let colors = this.$refs['singleAnswer'][k]colors.style.color = 'red'colors.style.border = 'solid 2px #f56c6c'}}this.showRightBox = true; // 展示正確答案},// 填空題輸入inputTextChange() {this.$refs.inputVal.focus();this.spanFocus();},// 切割輸入內容setText() {this.blankList = [];let rightValIndex = this.rightVal.map(item => item.length);let len = 0;rightValIndex.forEach((item, index) => {len += item;if (index == 0) {this.blankList.push(this.currentVal.slice(0, item).split(''))} else {this.blankList.push(this.currentVal.slice(len - item, len).split(''))}});this.spanFocus();},// 獲取焦點高亮顯示spanFocus() {let h_input_curlength = this.currentVal.length;let rightValIndex = this.rightVal.map(item => item.length);let len = 0;this.focusRow = rightValIndex.findIndex(item => {len += item;return len >= h_input_curlength;});this.focusIndex = this.focusRow > 0 ? h_input_curlength - len + rightValIndex[this.focusRow] : h_input_curlength;},} } </script><style lang="less" scoped> .completion {text-align: left;padding: 20px; }.answer-input {display: flex !important;opacity: 1;height: 0 !important;line-height: 0 !important; }.single-text {display: inline;font-weight: bold;color: #333333;line-height: 30px;font-size: 20px; }.blank-box {display: inline; }.answer-text {margin: 0 2px;padding: 0;display: inline-block;text-align: center;vertical-align: middle;background: #ffffff;border: 2px solid #cccccc;border-radius: 4px;font-size: 16px;color: #B59E84;width: 40px;height: 40px;line-height: 36px; }.answer-text :active {background-color: #f1f1f1; }.span-focus {border-color: #B59E84; }.submit-btn {margin: 20px 0;height: 60px;border-radius: 30px;line-height: 60px;text-align: center;color: #FFFFFF;background: red; }.answer-right {font-weight: bold;color: #333333;line-height: 30px;font-size: 20px; } </style>完整的組件代碼都在這里了,樣式和邏輯有待優化,不足之處請指出,或許等我有大空可能會及時把優化后的代碼繼續更新,今天寫到這里吧~
總結
以上是生活随笔為你收集整理的vue 填空题组件封装的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ABBYY FineReader 12使
- 下一篇: 1999年冬发出第一个论坛帖,弹指二十年