Vue implements exercise templates, single choice, multiple choice, input field

Vue realizes the practice question template, and the effect picture is attached at the end of the film

提示:本文为vue3 + ts实现,请根据自己项目自行修改,主要代码为html+css,可以参考本文逻辑,当然也可照搬(完整代码!)。


foreword

The template supports manual switching of the previous question, the next question (the question cannot be switched if the question is not completed), submission (all questions cannot be submitted if the question is not completed), and supports single-choice, multiple-choice, and output box type questions.


1. HTML code block

The code is as follows (example):

<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>

Two, TS code block

The code is as follows (example):

<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>

The data requested by the url network used here.


3. CSS code blocks

The code is as follows (example):

<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>

4. Realize the effect

1. Single choice

insert image description here

2. Input box

insert image description here

3. Multiple choice + submission (key: topic id, value: selected id/filled value)

insert image description here

Summarize

如果本文对你有帮助,点个赞再走吧!!!

Guess you like

Origin blog.csdn.net/qq_44860866/article/details/127576520