Vue が練習問題テンプレートを実現し、映画の最後にエフェクト画像が添付されます
提示:本文为vue3 + ts实现,请根据自己项目自行修改,主要代码为html+css,可以参考本文逻辑,当然也可照搬(完整代码!)。
記事ディレクトリ
序文
テンプレートは、前の質問、次の質問(質問が完了していない場合は質問を切り替えることができません)、送信(質問が完了していない場合はすべての質問を送信できません)の手動切り替えをサポートし、単一選択、複数選択をサポートしています。選択肢と出力ボックスタイプの質問。
1. HTMLコードブロック
コードは次のとおりです(例)。
<template>
<div class="Collect">
<!-- 饿了么的走马灯 -->
<el-carousel :autoplay="false" indicator-position="none" arrow="never" ref="carousel" :loop="false" @change="carChange">
<el-carousel-item v-for="item in data.topic" :key="item.id">
<div class="topic">
<h4>{
{
item.title }}</h4>
<div class="topic_valus">
<div v-if="item.type == 'input'">
<input v-model="item.value" class="ip_valus" />
</div>
<div v-else v-for="elem in item.list" :key="elem.id">
<!-- 单选 -->
<div v-if="item.type == 'sign'" :class="item.value == elem.id ? 'active' : ''"
@click="signClick(item, elem.id)">
{
{
elem.value }}
</div>
<!-- 多选 -->
<div v-else-if="item.type == 'both'"
:class="item.value.indexOf(elem.id) > -1 ? 'active' : ''"
@click="bothClick(item, elem.id)">
{
{
elem.value }}
</div>
</div>
</div>
</div>
</el-carousel-item>
<div class="topic_btns">
<el-button type="primary" :disabled="data.current == 0" :icon="ArrowLeft" @click="arrowLeft()">上一题</el-button>
<el-button type="primary" :disabled="data.current == data.topic.length - 1" @click="arrowright()">
下一题<el-icon class="el-icon--right">
<ArrowRight />
</el-icon>
</el-button>
</div>
<div class="submit">
<el-button :disabled="submitDisabled" type="primary" @click="submit()">提交</el-button>
</div>
</el-carousel>
</div>
</template>
2、TSコードブロック
コードは次のとおりです(例)。
<script lang="ts" setup>
import {
ref, reactive, getCurrentInstance, computed } from 'vue';
import {
ArrowLeft,
ArrowRight
} from '@element-plus/icons-vue'
const {
proxy}:any = getCurrentInstance();
const loading = ref(true);
const data = reactive({
topic: [
{
id: 1,
title: '爱好',
type: 'both',
list: [
{
id: 1, value: '打篮球' },
{
id: 2, value: '乒乓球' },
{
id: 3, value: '踢足球' }
],
value: []
},
{
id: 2,
title: '我国的国球是哪个?',
type: 'sign',
list: [
{
id: 1, value: '篮球' },
{
id: 2, value: '乒乓球' },
{
id: 3, value: '足球' }
],
value: 0
},
{
id: 3,
title: '请做一下自我介绍',
type: 'input',
value: ''
},
{
id: 4,
title: '请选择你擅长的技术栈',
type: 'both',
list: [
{
id: 1, value: 'JAVA' },
{
id: 2, value: 'C++' },
{
id: 3, value: 'VUE' },
{
id: 4, value: 'PHP' }
],
value: []
}
], // 所有题
current: 0, // 当前走马灯下标,及哪一道题
})
const carousel = ref<any>()
// 监听走马灯下标
function carChange(index){
data.current = index
}
// 单选
function signClick(item, elem_id) {
item.value = elem_id
}
// 多选
function bothClick(item, elem_id) {
if (item.value.indexOf(elem_id) > -1) {
let index = item.value.indexOf(elem_id)
item.value.splice(index, 1)
} else {
item.value.push(elem_id)
}
}
// 提交,拿到所有值
function submit() {
const arr = data.topic.map(item => {
return {
key: item.id, // 题目id
value: typeof item.value == 'object' ? item.value.join(',') : item.value, // 所选id/所填value
}
})
console.log(arr)
}
// 上一题
function arrowLeft() {
carousel.value.prev()
}
// 下一题
function arrowright() {
// 如果当前题没做,不小允许切换到下一题
const value:any = data.topic[data.current].value // 当前题的值
const status = typeof value == 'object' ? 1 : 0 // 判断是数组类型的value还是字符串类型的value
if(status == 1 && value.length > 0 || value != ''){
carousel.value.next()
}else{
proxy.$global.toast({
title: '请完成当前题!',
type: 'warning'
})
}
}
// 提交按钮禁用判定
const submitDisabled = computed(()=>{
const value:any = data.topic[data.topic.length - 1].value // 最后一题的值,用于判断做没做
const status = typeof value == 'object' ? 1 : 0 // 判断是数组类型的value还是字符串类型的value
// 如果没有做到最后一题或者最后一题没做
if(data.current != data.topic.length - 1 || (status == 1 && value.length == 0) || (status == 0 && value == '')){
return true
}else{
return false
}
})
setTimeout(() => {
loading.value = false;
}, 1500);
</script>
ここで使用される URL ネットワークによって要求されたデータ。
3. CSSコードブロック
コードは次のとおりです(例)。
<style lang="scss" scoped>
.Collect {
margin: 2rem;
padding: 2rem;
border-radius: 7px;
background: #fff;
::v-deep(.el-carousel) {
width: 300px;
border: solid 1px #ccc;
border-radius: 5px;
margin: 0 auto;
.el-carousel__item {
display: flex;
justify-content: center;
align-items: center;
}
}
.topic {
h4 {
font-size: 2rem;
font-weight: bold;
}
.topic_valus {
div {
div {
font-size: 1.5rem;
padding: 1rem 2rem;
border: solid 1px #ccc;
border-radius: 5px;
min-width: 200px;
max-width: fit-content;
cursor: pointer;
margin-bottom: 1rem;
}
}
.ip_valus {
height: 33px;
min-width: 200px;
max-width: fit-content;
border: solid 1px #ccc;
margin-bottom: 1rem;
border-radius: 5px;
}
.active {
background: #ccc;
}
}
}
.topic_btns{
position: absolute;
left: 0;
bottom: 0;
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
}
.submit{
position: absolute;
right: 0;
top: 0;
}
}
</style>