Vue3实现简单的水果购物车

hello world

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app"><!--Vue的容器-->
        <h1>{{msg}}</h1>
    </div>
    <script src="https://unpkg.com/vue@next"></script><!--用js的方式引入Vue-->
    <script>
        //Vue.createApp({})创建vue3的实例 vue2是new Vue({})
        Vue.createApp({
            data(){
                return {
                    msg:"hello world"
                }
            }
        }).mount("#app")//mount挂载dom节点

    </script>
</body>
</html>

1.如何操作文本:v-text

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <!--指令:vue提供的一些特殊的属性v-开头-->
        <h1 v-text="msg"></h1><!--跟<h1>{{msg}}</h1>效果一样-->
        <!--v-text这个指令让h1标签绑定msg这个变量的文本-->
    </div>
    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            //选项api(option api)
            data(){
                return {
                    msg:"hello world"
                }
            }
        }).mount("#app")

    </script>
</body>
</html>

2.如何操作属性:v-bind


将鼠标悬浮在hello world上就显示hello vue3的小框

现在要让title显示Vue里面的数据

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <!--v-bind是绑定属性的意思,:后面是属性-->
        <h1 v-bind:title="tit" v-text="msg"></h1><!--将tit这个变量通过v-bind绑定到h1标签的title属性上-->
    </div>
    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            data(){
                return {
                    msg:"hello world",
                    tit:"hello vue"
                }
            }
        }).mount("#app")

    </script>
</body>
</html>

3.如何绑定事件:v-on

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <h1 
        v-bind:title="tit" 
        v-text="msg"
        v-on:click="showData"
        ><!--v-on绑定事件,showData是个函数-->
    </h1>
    </div>
    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            data(){
                return {
                    msg:"hello world",
                    tit:"hello vue"
                }
            },
            methods:{//click事件的函数
                showData(){
                    alert("hello vue3");
                }
            }
        }).mount("#app")

    </script>
</body>
</html>

实现计数器功能

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <button @click="decrease">-</button><!--v-on:click简写成@click-->
        <span>{{number}}</span>
        <button @click="increase">+</button>
    </div>
    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            data(){
                return {
                    number:0
                }
            },
            methods:{
                decrease(){
                    if(this.number > 0){
                        this.number--;
                    }
                },
                increase(){
                    this.number++;
                }
            }
        }).mount("#app")
    </script>
</body>
</html>

图片切换功能

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        img{
            height: 300px;
        }
    </style>
</head>
<body>
    <div id="app">
        <img :src="src" alt=""><!--v-bind:src简写成:src-->
        <button @click="changePic(0)">1</button>
        <button @click="changePic(1)">2</button>
        <button @click="changePic(2)">3</button>
    </div>
    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            data(){
                return {
                    src:"images/1.jpg",
                    list:[
                        "images/1.jpg",
                        "images/2.jpg",
                        "images/3.jpg"
                    ]
                }
            },
            methods:{
                changePic(i){
                    this.src = this.list[i];
                }
            }
        }).mount("#app")
    </script>
</body>
</html>

渲染列表

优化下上述的图片切换

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        img{
            height: 300px;
        }
    </style>
</head>
<body>
    <div id="app">
        <img :src="src" alt=""><!--v-bind:src简写成:src-->
        <button 
        v-for="item,index in list"
        @click="changePic(index)">
            {{index+1}}
    </button>
    <!--item是元素 index是索引
    item in list表示数组中的元素,即list中的3张图片路径,item会使每个数组的元素都拥有一个按钮,即页面会出现3个按钮
    而index负责给按钮命名{{index+1}},123,以及给点击对应的按钮设置参数changePic(index)
    -->
    </div>
    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            data(){
                return {
                    src:"images/1.jpg",
                    list:[
                        "images/1.jpg",
                        "images/2.jpg",
                        "images/3.jpg"
                    ]
                }
            },
            methods:{
                changePic(i){
                    this.src = this.list[i];
                }
            }
        }).mount("#app")
    </script>
</body>
</html>

好处在于如果给数组添加图片路径,button那里会自动添加按钮,不用额外去写button

表单提交时阻止默认行为

一般的提交表单会刷新页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <!--绑定表单提交的事件是@submit-->
        <form @submit="post">
            <input type="text">
            <button>提交表单</button>
        </form>
    </div>
    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            methods:{
                post(){
                    console.log("hello")
                }
            }
        }).mount("#app")
    </script>
</body>
</html>

点击提交表单,hello会一闪而逝,因为提交表单后会刷新页面

要阻止提交表单会刷新页面的默认行为

<div id="app">
        <form @submit.prevent="post"><!--submit后面加个事件修饰符prevent-->
            <input type="text">
            <button>提交表单</button>
        </form>
    </div>
    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            methods:{
                post(){
                    console.log("hello")
                }
            }
        }).mount("#app")
    </script>

现在不会刷新了

数据的双向绑定

要使表单里输入什么就提交什么,就要用到数据的双向绑定

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <h1>{{msg}}</h1><!--只要有一个地方的msg发生改变,其他的msg也会发生改变,这就是双向绑定的特点-->
        <form @submit.prevent="post">
            <input type="text" v-model="msg"><!--用v-model绑定msg这个变量-->
            <button>提交表单</button>
        </form>
    </div>
    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            data(){
                return{
                    msg:"hello"
                }
            },
            methods:{
                post(){
                    console.log("hello")
                }
            }
        }).mount("#app")
    </script>
</body>
</html>

往文本框中输入字符,h1标签也会跟着变

把post方法改下就能打印文本框的数据了

    <div id="app">
        <h1>{{msg}}</h1>
        <form @submit.prevent="post">
            <input type="text" v-model="msg">
            <button>提交表单</button>
        </form>
    </div>
    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            data(){
                return{
                    msg:"hello"
                }
            },
            methods:{
                post(){
                    console.log(this.msg)
                }
            }
        }).mount("#app")
    </script>


把数据转换成数值类型,控制台中的信息是蓝色的。上面那种字符串是黑色的

    <div id="app">
        <h1>{{msg}}</h1>
        <form @submit.prevent="post">
            <input type="text" v-model.number="msg"><!--.number使数据转换成数值类型-->
            <button>提交表单</button>
        </form>
    </div>
    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            data(){
                return{
                    msg:""
                }
            },
            methods:{
                post(){
                    console.log(this.msg)
                }
            }
        }).mount("#app")
    </script>


如果想要文本框失去焦点时h1标签才变化,就用.lazy

    <div id="app">
        <h1>{{msg}}</h1>
        <form @submit.prevent="post">
            <input type="text" v-model.lazy="msg">
            <button>提交表单</button>
        </form>
    </div>
    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            data(){
                return{
                    msg:""
                }
            },
            methods:{
                post(){
                    console.log(this.msg)
                }
            }
        }).mount("#app")
    </script>

没有失去焦点时h1不会变化

.trim可以去掉文本前后的空格,防止输入用户名的时候多打了空格而没察觉

    <div id="app">
        <h1>{{msg}}</h1>
        <form @submit.prevent="post">
            <input type="text" v-model.trim="msg">
            <button>提交表单</button>
        </form>
    </div>

h1不受空格影响,点击提交后文本框中的空格就会消失

一个简单的水果购物车功能

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <h1>水果列表</h1>
        <form @submit.prevent="insert"><!--通过insert方法添加数组-->
            <input type="text" v-model="name">
            <input type="text" v-model.number="price">
            <button>添加</button>
        </form>
        <ul>
            <li v-for="item,index in list">
                名称:{{item.name}}
                单价:{{item.price}}
                数量:<!--数量是个计数器-->
                <button @click="decrease(index)">-</button><!--通过index定位到数组的第几个元素-->
                <span>{{item.count}}</span>
                <button @click="increase(index)">+</button>
            </li>
        </ul>
        <h3>总价:{{totalPrice}}</h3>
    </div>
    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            data(){
                return{
                    name:"",
                    price:0,
                    list:[]
                }
            },
            computed:{//计算属性
                totalPrice(){
                    let sum = 0;
                    this.list.forEach(v => {//forEach遍历数组
                        sum += (v.price * v.count);
                    })
                    return sum;
                }
            },
            methods:{
                insert(){//添加数组
                    this.list.push({
                        name:this.name,
                        price:this.price,
                        count:1
                    })
                },
                increase(i){
                    this.list[i].count++
                },
                decrease(i){
                    if(this.list[i].count > 0){
                        this.list[i].count--
                    }else if(this.list[i].count <=0 && confirm("是否删除")){//数量小于等于0就弹出窗口,如果点确定就删了
                        this.list.splice(i,1);//删掉那一项
                    }
                } 
            }
        }).mount("#app")
    </script>
</body>
</html>


posted @ 2022-11-25 19:32  ben10044  阅读(281)  评论(0编辑  收藏  举报