事无巨细地解释一个vue前端网页

参考:

AI全栈开发之 HTML+CSS 零基础入门教程_哔哩哔哩_bilibili

十分钟入门vue_哔哩哔哩_bilibili


目标

我们最初只有这么个基础的代码

html 复制代码
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>hello</title>
    </head>
    <body>
    </body>
</html>

然后企图设计一个网页:

从外向内,逐步细化

1.背景颜色

在body里面添加

html 复制代码
<body>
    <style>
        /*这个body指代一个整体背景*/
        body {
            background:linear-gradient(
                to right,
                rgb(113,65,168),
                rgba(44,114,251,1)
            );
        }
    </style>
</body>

出现了背景

2.白色框框

先得创建一个盒子<div>,起名todo-app。

然后CSS里面用一个点开头,这个表示"类名选择器",如果你问我什么是类...那要不翻个书?

css 复制代码
<div class="todo-app"></div>
.todo-app{
    width: 96%;
    height: 500px;
    background-color: #ffff;
    border-radius: 5px;/*圆角*/
    margin-top: 40px;/*上面的顶*/
    margin-left: 2%;/*96对称*/
}

然后做美化优化,用到圆角border-radius;上面留白、左边留白,也就是margin的用法。

3.白板标题

前面三个属性:大小、宽度、居中

第四个属性:不能用margin-top让黑字往下放,因为遇到"Mar针塌陷"的问题,所以在盒子本身上面改用padding-top。简单来说,一个在外面加,一个在里面加。然后加完之后还会遇到这个盒子整体高度变成了500+30,所以又要引入一个新的代码约束:box-sizing: border-box;。

css 复制代码
<div class="todo-app">
    <div class="title">TodoApp</div>
</div>
.todo-app{
    width: 96%;
    height: 500px;
    padding-top: 30px;
    box-sizing: border-box;
    background-color: #ffff;
    border-radius: 5px;/*圆角*/
    margin-top: 40px;/*上面的顶*/
    margin-left: 2%;/*96对称*/
}
/*大标题的字*/
.title{
    /*大小、宽度、居中*/
    font-size: 30px;
    font-weight: 700;
    text-align: center;/
}

4.输入框(1)

现在先把输入框给写出来

css 复制代码
<div class="todo-app">
    <div class="title">TodoApp</div>
        <div class="todo-from">
            <input type="text"/>
            <div class="todo-button">add todo</div>
    </div>
</div>
/*输入框*/
.todo-from{
    display: flex;
}

5.输入框(左)

要更新原先的input这行代码,给一个占位符placeholder。

css 复制代码
<input class="todo-input" type="text" placeholder="请输入文本" />
.todo-input{
    /*这是左侧的白框,所以是左上左下圆角,右上右下方形*/
    padding-left: 15px;
    border: 1px solid #dfe1e5;/*外框*/
    outline: none;
    width: 60%;
    height: 50px;
    border-radius: 20px 0 0 20px;
}

6.输入框(右)

cursor: pointer;指代的是鼠标放到点击栏上,鼠标变成指针。user-select: none;指代的是上面的add todo文字不能被选中。

css 复制代码
<div class="todo-app">
    <div class="title">TodoApp</div>
    <div class="todo-from">
        input class="todo-input" type="text" placeholder="请输入文本" />
        <div class="todo-button">add todo</div>
    </div>
</div>
/*输入框*/
.todo-from{
    display: flex;
    margin-top:20px;
    margin-left:30px;
}
.todo-input{
    /*这是左侧的白框,所以是左上左下圆角,右上右下方形*/
    padding-left: 15px;
    border: 1px solid #dfe1e5;/*外框*/
    outline: none;
    width: 60%;
    height: 50px;
    border-radius: 20px 0 0 20px;
}
.todo-button{
    /*这是左侧的白框,所以是左上左下圆角,右上右下方形*/
    width: 100px;
    height: 52px;/*50+1+1*/
    border-radius: 0 20px 20px 0;
    text-align: center;
    background:linear-gradient(to right, rgb(113,65,168), rgba(44,114,251,1));
    color:#ffff;
    line-height: 50px;/*行高*/
    cursor: pointer;
    user-select: none;
}

7.选项

align-items: center;框里所有元素垂直居中。

justify-content: space-between;框里元素自动评分空间,也就是左右对半开。

在这里用到一个技巧:选项框和字符是需要看成一个整体的,所以外面套了一层<div>盒子。

同时,后者的div变成span,才能实现横着排。

css 复制代码
<div class="item">
    <div>
        <input type="checkbox" />
        <span class="name">吃饭</span>
    </div>

    <div class="del">del</div>
</div>
.item{
    display: flex;
    box-sizing: border-box;
    width: 80%;
    height: 50px;
    margin: 8px auto;
    padding: 16px;
    border-radius: 20px;
    box-shadow: rgba(149, 157, 165, 0.2) 0px 8px 20px;

    align-items: center;
    justify-content: space-between;
}

8.删除选项

新知识:一个盒子可以同时拥有多个类名。

目前的代码:

html 复制代码
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>hello</title>
    </head>
    <body>
        <div class="todo-app">
            <div class="title">TodoApp</div>
            <div class="todo-from">
                <input class="todo-input" type="text" placeholder="请输入文本" />
                <div class="todo-button">add todo</div>
            </div>

            <div class="item completed">
                <div>
                    <input type="checkbox" />
                    <span class="name">吃饭</span>
                </div>
                <div class="del">del</div>
            </div>

            <div class="item">
                <div>
                    <input type="checkbox" />
                    <span class="name">学习</span>
                </div>
                <div class="del">del</div>
            </div>

            <div class="item">
                <div>
                    <input type="checkbox" />
                    <span class="name">打瞌睡</span>
                </div>
                <div class="del">del</div>
            </div>

        </div>
        <style>
            /*这个body指代一个整体背景*/
            body {
                background:linear-gradient(
                    to right,
                    rgb(113,65,168),
                    rgba(44,114,251,1)
                );
            }
            /*白色框框*/
            .todo-app{
                width: 96%;
                height: 500px;
                padding-top: 30px;
                box-sizing: border-box;
                background-color: #ffff;
                border-radius: 5px;/*圆角*/
                margin-top: 40px;/*上面的顶*/
                margin-left: 2%;/*96对称*/
            }
            /*大标题的字*/
            .title{
                /*大小、宽度、居中*/
                font-size: 30px;
                font-weight: 700;
                text-align: center;/
            }
            /*输入框*/
            .todo-from{
                display: flex;
                margin-top:20px;
                margin-left:30px;
            }
            .todo-input{
                /*这是左侧的白框,所以是左上左下圆角,右上右下方形*/
                padding-left: 15px;
                border: 1px solid #dfe1e5;/*外框*/
                outline: none;
                width: 60%;
                height: 50px;
                border-radius: 20px 0 0 20px;
                margin-bottom: 20px;
            }
            .todo-button{
                /*这是左侧的白框,所以是左上左下圆角,右上右下方形*/
                width: 100px;
                height: 52px;/*50+1+1*/
                border-radius: 0 20px 20px 0;
                text-align: center;
                background:linear-gradient(to right, rgb(113,65,168), rgba(44,114,251,1));
                color:#ffff;
                line-height: 50px;/*行高*/
                cursor: pointer;
                user-select: none;
            }
            /*选项框*/
            .item{
                display: flex;
                box-sizing: border-box;
                width: 80%;
                height: 50px;
                margin: 8px auto;
                padding: 16px;
                border-radius: 20px;
                box-shadow: rgba(149, 157, 165, 0.2) 0px 8px 20px;

                align-items: center;
                justify-content: space-between;
            }
            .del{
                color: red;
            }
            .completed{
                text-decoration: line-through;
                opacity: 0.4;
            }

        </style>
    </body>
</html>

9.切换框架

这里给我恶心到了。

切换框架发现边角是没办法填的,然后右边多出了下拉,不知道怎么弄,尽力了。

html 复制代码
<script setup>

</script>

<template>
    <div class="full-screen-container">
        <div class="todo-app">
            <div class="title">TodoApp</div>
            <div class="todo-from">
                <input class="todo-input" type="text" placeholder="请输入文本" />
                <div class="todo-button">add todo</div>
            </div>
        
            <div class="item completed">
                <div>
                    <input type="checkbox" />
                    <span class="name">吃饭</span>
                </div>
                <div class="del">del</div>
            </div>

            <div class="item">
                <div>
                    <input type="checkbox" />
                    <span class="name">学习</span>
                </div>
                <div class="del">del</div>
            </div>

            <div class="item">
                <div>
                    <input type="checkbox" />
                    <span class="name">打瞌睡</span>
                </div>
                <div class="del">del</div>
            </div>

        </div>
    </div>
</template>

<style scoped>
    /*这个body指代一个整体背景*/
    .full-screen-container {
        background:linear-gradient(
            to right,
            rgb(113,65,168),
            rgba(44,114,251,1)
        );
        /* 顺便让内容居中 */
        width: 100%;
        height: 100vh;
        display: flex;
        justify-content: center;
        padding-top: 40px;
        /* 2. 消除可能导致的溢出 */
        margin: 0;
        padding: 0;
        overflow: hidden; /* 防止内部元素撑开滚动条s */
    }
    /*白色框框*/
    .todo-app{
        width: 96%;
        height: 500px;
        padding-top: 30px;
        box-sizing: border-box;
        background-color: #ffff;
        border-radius: 5px;/*圆角*/
        margin-top: 40px;/*上面的顶*/
        margin-left: 2%;/*96对称*/
    }
    /*大标题的字*/
    .title{
        /*大小、宽度、居中*/
        font-size: 30px;
        font-weight: 700;
        text-align: center;
    }
    /*输入框*/
    .todo-from{
        display: flex;
        margin-top:20px;
        margin-left:30px;
    }
    .todo-input{
        /*这是左侧的白框,所以是左上左下圆角,右上右下方形*/
        padding-left: 15px;
        border: 1px solid #dfe1e5;/*外框*/
        outline: none;
        width: 60%;
        height: 50px;
        border-radius: 20px 0 0 20px;
        margin-bottom: 20px;
    }
    .todo-button{
        /*这是左侧的白框,所以是左上左下圆角,右上右下方形*/
        width: 100px;
        height: 52px;/*50+1+1*/
        border-radius: 0 20px 20px 0;
        text-align: center;
        background:linear-gradient(to right, rgb(113,65,168), rgba(44,114,251,1));
        color:#ffff;
        line-height: 50px;/*行高*/
        cursor: pointer;
        user-select: none;
    }
    /*选项框*/
    .item{
        display: flex;
        box-sizing: border-box;
        width: 80%;
        height: 50px;
        margin: 8px auto;
        padding: 16px;
        border-radius: 20px;
        box-shadow: rgba(149, 157, 165, 0.2) 0px 8px 20px;

        align-items: center;
        justify-content: space-between;
    }
    .del{
        color: red;
    }
    .completed{
        text-decoration: line-through;
        opacity: 0.4;
    }
</style>

10.点击绑定输入

从现在开始难度陡然上升。先贴出修改的代码。

html 复制代码
<input v-model="val" class="todo-input" type="text" placeholder="请输入文本" />
<div @click="add" class="todo-button">add todo</div>
javascript 复制代码
import { ref } from 'vue'
const val = ref('')
function add(){
    console.log(val.value)
}

这里的逻辑是:

输入的数据会被存入到val变量中,这个是字符串,因此用('')。

@click就是点击触发函数add。

add可以把数据打印在控制台上,就完成了输入与点击的绑定。

11.修改下方选项内容

我们先需要一个列表list。

javascript 复制代码
const list = ref([
    { isComplete: false, text: "吃饭" },
    { isComplete: false, text: "睡觉" },
    { isComplete: false, text: "斗地主"},
])

然后加上一行v-for="item in list",也就变成

html 复制代码
<div v-for="item in list" class="item completed">
     <div>
          <input type="checkbox" />
          <span class="name">吃饭</span>
     </div>
     <div class="del">del</div>
</div>

(在这里我们又把completed的样式加上了item的样式,所以就不用两个类了)

但是我们发现这个文字被写死成了吃饭,那么这个时候就应该用到类的内容了,把吃饭替换成item.text。也就是相当于for循环了,每个都叫item。

<span class="name">{{item.text}}</span>

接着我们知道不论如何这个样式都是completed,但是我们需要的是item或者completed的选择款。所以三目运算符在此发力。

<div v-for="item in list" :class="[item.isComplete ? 'completed' : 'item']">

可见现在不同的情况对应不同的样式

12.单选框切换样式

我怎么通过勾选把isComplete给改变呢?

用到v-model即可。我们之前用v-model关联外界输入值val,现在关联外界输入值item.Completed。里面是有一套数据结构表示的,你点击了就代表这个值等于1。

<input v-model="item.isComplete" type="checkbox" />

13.增删列表

现在的问题就来到了------怎么点击Add Todo就是增,del就是删?

用到@click即可。这两个本身就是意味着:数组增添对象,数组删除对象。

增添对象的函数好写,删除对象的函数要知识储备splice函数

function add(){

//console.log(val.value)

list.value.push({isComplete: false, text: val.value})

}

function del(index){

list.value.splice(index, 1)

}

然后最大的问题,如何知道你要删哪个数据?

我们把index和item放在一起循环

<div v-for="(item,index) in list"

然后@click绑的时候带参数<div @click="del(index)" class="del">del</div>

结束。

Code

html 复制代码
<script setup>
import { ref } from 'vue'

const val = ref('')

const list = ref([
    { isComplete: false, text: "吃饭" },
    { isComplete: false, text: "睡觉" },
    { isComplete: true, text: "斗地主"},
])

function add(){
    //console.log(val.value)
    list.value.push({isComplete: false, text: val.value})
}

function del(index){
    list.value.splice(index, 1)
}

</script>

<template>
    <div class="full-screen-container">
        <div class="todo-app">
            <div class="title">原神</div>
            <div class="todo-from">
                <input v-model="val" class="todo-input" type="text" 
                    placeholder="你说的对,但是《原神》是由米哈游自主研发的一款全新开放世界冒险游戏。游戏发生在一个被称作「提瓦特」的幻想世界,在这里,被神选中的人将被授予「神之眼」,导引元素之力。你将扮演一位名为「旅行者」的神秘角色,在自由的旅行中邂逅性格各异、能力独特的同伴们,和他们一起击败强敌,找回失散的亲人------同时,逐步发掘「原神」的真相。" />
                <div @click="add" class="todo-button">add todo</div>
            </div>
        
            <div v-for="(item,index) in list" 
            :class="[item.isComplete ? 'completed' : 'item']">
                <div>
                    <input v-model="item.isComplete" type="checkbox" />
                    <span class="name">{{item.text}}</span>
                </div>
                <div @click="del(index)" class="del">del</div>
            </div>

        </div>
    </div>
</template>

<style scoped>
    /*这个body指代一个整体背景*/
    .full-screen-container {
        background:linear-gradient(
            to right,
            rgb(113,65,168),
            rgba(44,114,251,1)
        );
        /* 顺便让内容居中 */
        width: 100%;
        height: 100vh;
        display: flex;
        justify-content: center;
        padding-top: 40px;
        /* 2. 消除可能导致的溢出 */
        margin: 0;
        padding: 0;
        overflow: hidden; /* 防止内部元素撑开滚动条s */
    }
    /*白色框框*/
    .todo-app{
        width: 96%;
        height: 500px;
        padding-top: 30px;
        box-sizing: border-box;
        background-color: #ffff;
        border-radius: 5px;/*圆角*/
        margin-top: 40px;/*上面的顶*/
        margin-left: 2%;/*96对称*/
    }
    /*大标题的字*/
    .title{
        /*大小、宽度、居中*/
        font-size: 30px;
        font-weight: 700;
        text-align: center;
    }
    /*输入框*/
    .todo-from{
        display: flex;
        margin-top:20px;
        margin-left:30px;
    }
    .todo-input{
        /*这是左侧的白框,所以是左上左下圆角,右上右下方形*/
        padding-left: 15px;
        border: 1px solid #dfe1e5;/*外框*/
        outline: none;
        width: 60%;
        height: 50px;
        border-radius: 20px 0 0 20px;
        margin-bottom: 20px;
    }
    .todo-button{
        /*这是左侧的白框,所以是左上左下圆角,右上右下方形*/
        width: 100px;
        height: 52px;/*50+1+1*/
        border-radius: 0 20px 20px 0;
        text-align: center;
        background:linear-gradient(to right, rgb(113,65,168), rgba(44,114,251,1));
        color:#ffff;
        line-height: 50px;/*行高*/
        cursor: pointer;
        user-select: none;
    }
    /*选项框*/
    .item{
        display: flex;
        box-sizing: border-box;
        width: 80%;
        height: 50px;
        margin: 8px auto;
        padding: 16px;
        border-radius: 20px;
        box-shadow: rgba(149, 157, 165, 0.2) 0px 8px 20px;

        align-items: center;
        justify-content: space-between;
    }
    .del{
        color: red;
    }
    .completed{
        text-decoration: line-through;
        opacity: 0.4;

        display: flex;
        box-sizing: border-box;
        width: 80%;
        height: 50px;
        margin: 8px auto;
        padding: 16px;
        border-radius: 20px;
        box-shadow: rgba(149, 157, 165, 0.2) 0px 8px 20px;
        align-items: center;
        justify-content: space-between;
    }
</style>
相关推荐
han_3 小时前
JavaScript设计模式(三):代理模式实现与应用
前端·javascript·设计模式
~欲买桂花同载酒~3 小时前
项目安装- React + TypeScript
前端·react.js·typescript
光辉GuangHui3 小时前
SDD 实践:OpenSpec + Superpowers 整合创建自定义工作流
前端·后端
西梯卧客3 小时前
[4-3] 异步编程与事件循环 · 终极异步解决方案 (Generator & Async/Await)
javascript
ssshooter3 小时前
infer,TS 类型系统的手术刀
前端·面试·typescript
用户3167361303423 小时前
图片懒加载,我总结了三个方式
前端
灰太狼大大王3 小时前
2026 前端基石:HTML5 全景知识体系指南(从入门到架构师思维)
前端
米丘3 小时前
vue-router 5.x 文件式路由
前端·vue.js
始持3 小时前
第十五讲 本地存储
前端·flutter