vue实现在一个段落内的填空题
方案一可编辑段落contenteditable 属性规定元素内容是否可编辑。属性说明代码:<p><span>题目1</span><span contenteditable></span></p>``效果:这个属性很好,遗憾的是我做的是段落填空,需要填空与题目在一行,只能另求他法。方案二 使用隐藏的input每个填空设置一个隐藏
·
具体实现
contenteditable 属性规定元素内容是否可编辑。属性说明
效果:
先说一下主要思路:
将填空部分设置为可编辑元素,通过监听input
事件获取填空部分的innerText
。通过text-decoration: underline;
设置底部横线。
填空题初始状态在题目后面需要预留一段空白,因为做的是内联填空,所以可编辑元素不能设置为inline-block
,否则长度超出一行后,填空内容会独占一行,与题目分成两行,体验极差。那么自然也不能设置最小宽度,所以在可编辑元素后面新增一段占位空格,在进行输入时相对应减少占位空格数量。
以下是填空组件fillblank.vue
内容
模板:
<p class="other-input-text">
<span class="label">{{ label }}</span>
<span class="value seat" ref="value" contenteditable @blur="blur" @input="input" @focus="focus"></span>
<span class="seat" @click="clickSeat">{{ seat }}</span>
<span v-if="comma">,</span>
</p>
js代码:
export default {
props: {
// 题目label
label: {
type: String
},
// 填空内容
value: {
type: String
},
// 末尾是否显示逗号
comma: {
type: Boolean
}
},
model: {
prop: 'value',
event: 'changeValue'
},
data() {
return {
inputValue: ''
};
},
computed: {
// 占位空格内容
seat() {
let minLength = 15;
let detaLength = minLength - this.inputValue.length;
if (detaLength > 0) {
return new Array(detaLength).fill(' ').join('');
}
return '';
}
},
watch: {
value(val) {
this.inputValue = val;
},
inputValue(value) {
this.$emit('changeValue', value);
}
},
mounted() {
this.inputValue = this.value || '';
this.$refs.value.innerHTML = this.inputValue;
},
methods: {
// 点击占位空格时聚焦可编辑元素
clickSeat() {
this.$refs.value && this.$refs.value.focus();
},
// 聚焦时定位光标位置
focus(e) {
setTimeout(() => {
this.setFocus(this.inputValue.length);
}, 0);
},
// 失焦时再赋值一遍
blur() {
this.inputValue = this.$refs.value.innerText;
console.log(this.$refs.value.innerText);
},
// 输入时进行赋值
input() {
this.inputValue = this.$refs.value.innerText;
},
// 聚焦后把光标放到最后
setFocus(index) {
let obj = this.$refs.value;
if (document.createRange) {
// 获取选定对象
let selection = getSelection();
let range = document.createRange();
range.setStart(obj.firstChild || obj, index);
range.setEnd(obj.firstChild || obj, index);
selection.removeAllRanges();
selection.addRange(range);
}
}
}
};
样式部分的代码就不贴了,因为做的是内联填空,需要注意以下几点:
1、整个组件中元素的样式都应该是内联的;
2、字母单词需要可以换行;
3、填空部分及占位部分需要添加下划线;
4、可编辑对象的边框可使用outline:none
隐藏。
其他知识点
在实现过程中,为了优化体验,也对光标的位置手动做了定位,每次可编辑元素进行聚焦的时候,都让光标出现在填空内容的末尾。这涉及到selection
对象和range
对象,以下是参考的博文:
更多推荐
已为社区贡献1条内容
所有评论(0)