前端之vue day04 简单购物车、前后端交互(重要)、Vue生命周期、组件

一、简单购物车

1.勾选显示总价购物车

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>购物车</title>
    <script src="./js/vue.js"></script>

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"
          integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
    <style>
        .trCenter {
            text-align: right;
        }

    </style>
</head>
<body>
<div id="MyDiv">

    <div class="container-fluid">
        <div class="row ">

            <div class="col-md-6 col-md-offset-3 text-center">
                <h1>我的购物车</h1><span><button class="btn btn-primary" @click="showCar">展开我的购物车</button></span>
                <hr>

                <div v-show="show">
                    <table class="table table-bordered">
                        <thead>
                        <tr class="trCenter">
                            <th>#</th>
                            <th>商品名</th>
                            <th>价格</th>
                            <th>数量</th>
                            <th>选择</th>
                            <th v-if="showEachPrice">单项总价</th>
                        </tr>
                        </thead>
                        <tbody>
                        <tr class="text-center" v-for="item of goodsList">
                            <th scope="row">{{item.id}}</th>
                            <td>{{item.name}}</td>
                            <td>{{item.price}}</td>
                            <td>{{item.num}}</td>
                            <td><input type="checkbox" v-model="carList" :value="item"></td>
                        </tr>
                        </tbody>
                    </table>
                    <hr>

                    <h2>我的购物车商品总价为:{{allPrice()}}</h2>
                </div>


            </div>

        </div>
    </div>


</div>


<script>
    var vm = new Vue({
        el: '#MyDiv',
        data: {
            name: 'jack',
            goodsList: [{id: 1, name: '一加11', price: 3999, num: 2, stock: 15},
                {id: 2, name: '一加ACE 2', price: 2799, num: 3, stock: 20},
                {id: 3, name: '红米K60', price: 2999, num: 1, stock: 19},
                {id: 4, name: '真我GT NEO5', price: 2699, num: 4, stock: 9}
            ],
            carList: [],
            show: false
        },
        methods: {
            showCar() {
                this.show = !this.show
            },
            allPrice() {
                var total = 0
                this.carList.forEach((item) => {
                    total += item.price * item.num
                })
                return total

            }

        }


    })


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

2.带全选、带调整数量、带删除的购物车

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>购物车</title>
    <script src="./js/vue.js"></script>

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"
          integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">

    <style>
        .picture{
            height:150px;
            width: 150px;
        }
    </style>
</head>
<body>
<div id="MyDiv">

    <div class="container-fluid">
        <div class="row ">

            <div class="col-md-6 col-md-offset-3 text-center">
                <h1>我的购物车</h1><span><button class="btn btn-primary" @click="showCar">展开我的购物车</button></span>
                <hr>

                <div v-show="show">
                    <table class="table table-bordered">
                        <thead>
                        <tr class="trCenter">
                            <th>#</th>
                            <th>商品名</th>
                            <th>图片</th>
                            <th>价格</th>
                            <th>数量</th>
                            <th>选择
                                全选<input type="checkbox" v-model="choiceAll" @change="choiceAllFunc"></th>


                        </tr>
                        </thead>
                        <tbody>
                        <tr class="text-center" v-for="item of goodsList">
                            <th scope="row">{{item.id}}</th>
                            <td>{{item.name}}</td>
                            <td><img v-bind:src="item.picture" alt="" class="picture"></td>
                            <td>{{item.price}}</td>
                            <td>
                                <button class="btn btn-danger" @click="reduceNumFunc(item)">-</button>
                                {{item.num}}
                                <button class="btn btn-primary" @click="addNumFunc(item)">+</button>
                            </td>
                            <td><input type="checkbox" v-model.lazy="carList" :value="item" @change="handelCheck"></td>

                        </tr>
                        </tbody>
                    </table>
                    <hr>

                    <h2>我的购物车商品总价为:{{allPrice()}}</h2>
                    <br>
                    <button class="btn btn-block btn-success">结算(假)</button>
                </div>


            </div>

        </div>
    </div>


</div>


<script>
    var vm = new Vue({
        el: '#MyDiv',
        data: {
            name: 'jack',
            goodsList: [{id: 1, name: '一加11',picture:'//img12.360buyimg.com/n7/jfs/t1/153199/3/31674/61965/63eca8f6Ffbda3a22/96dc9c79d8cf8483.jpg' ,price: 4399, num: 2, stock: 15},
                {id: 2, name: '一加ACE 2',picture:'//img14.360buyimg.com/n7/jfs/t1/15148/20/20372/63596/63edea97F2de4ae52/3a9f817f3a078e27.jpg' , price: 3099, num: 3, stock: 20},
                {id: 3, name: '红米K60',picture:'//img14.360buyimg.com/n7/jfs/t1/88439/27/36908/68738/63e99e6dF2240c8f6/b91edda95733dd2d.jpg.avif' ,price: 2999, num: 1, stock: 19},
                {id: 4, name: '真我GT NEO5', picture:'//img12.360buyimg.com/n7/jfs/t1/204446/38/23406/86674/628f2f9bEe15228f7/72de573a56b64881.jpg.avif' ,price: 2699, num: 4, stock: 9}
            ],
            detailGoodsList: [{id: 1, name: '一加11', price: 4399, num: 2, stock: 15},
                {id: 2, name: '一加ACE 2', price: 3099, num: 3, stock: 20},
                {id: 3, name: '红米K60', price: 2999, num: 1, stock: 19},
                {id: 4, name: '真我GT NEO5', price: 2699, num: 4, stock: 9}
            ],
            carList: [],
            show: false,
            choiceAll: false
        },
        methods: {
            showCar() {
                this.show = !this.show
            },
            allPrice() {
                var total = 0
                this.carList.forEach((item) => {
                    total += item.price * item.num
                })
                return total

            },
            choiceAllFunc() {
                var _this = this
                if (_this.choiceAll) {
                    _this.carList = _this.goodsList
                } else {
                    _this.carList = []
                }
            },
            handelCheck() {
                if (this.carList.length === this.goodsList.length) {
                    this.choiceAll = true
                }
            },
            reduceNumFunc(item) {

                if (item.num < 1) {
                    var res = confirm(
                        '商品数量不能小于0,按下确认将删除该商品'
                    )
                    if (res){
                        this.goodsList.splice(item.id-1,1)
                    }
                } else {
                    item.num--
                }
            },
            addNumFunc(item) {
                if(item.num > item.stock){
                    alert('超出商品库存')
                }
                else {
                    item.num++
                }
            }

        }


    })

    a= ''
    console.log(a.length)


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

二、回忆一下可变、不可变

python一切皆对象,没有值和引用,对象都是引用,是作者加的可变和不可变来区分
其实python变量都是指向一个内存地址,这个地址又指向真正的值
# python
	-不可变类型:数字,字符串,元组
    -可变类型:列表,字典,集合
    -python中没有值类型和引用类型的叫法----【因为python一切皆对象,对象都是地址都是引用】
    -可变类型当参数传到函数中,在函数中修改会影响原来的
    -不可变类型当参数传到函数中,在函数中修改不会影响原来的
    
# python 函数参数传递是值传递还是引用传递? 这个问题不应该有


# js 传入了item 对象,在函数中修改,影响了原来的
	-js 的对象是引用类型

三、v-model进阶

使用格式:

v-model.lazy="carList"  #实际也是修饰符

lazy

​ input框失去焦点时页面再局部小刷新

number(可以用于手机号输入)

​ 数字开头,只保留数字,后面的字母不保留;字母开头,都保留

trim

​ 去除首位的空格

四、与后端交互(重点)

​ 前端页面朝后端发送ajax请求是交互后端的常用方式,因为ajax异步发送web请求,拿回响应数据,作为后端只需要提供接口即可。

jQuery发送ajax

​ 先说一下会碰到跨域问题,何为跨域?就是前后端跑在不同的域上,域就是IP+端口组成,所以一般网址也叫域名,浏览器对不同域名交互的数据会予以拦截。

1.导一下JQ
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
2.举例发送一个get请求
<div id="app">
    <p>姓名:{{infoObj.name}}</p>
    <p>年龄:{{infoObj.age}}</p>
    <p>性别:{{infoObj.gender}}</p>
    <button @click="loadInfo">加载数据</button>
</div>
<script>
    new Vue({
        el: '#app',
        data: {
            infoObj: {}
        },
        methods: {
            loadInfo() {
                $.ajax({
                    url: 'http://127.0.0.1:5000/',
                    type: 'get',
                    success:(data)=>{
                        console.log(data)
                        this.infoObj = data
                    }
                })
            },
        },
    })
</script>
————————————————————————————————————————————————————————
3.搭配后端,后端用flask写,暂时没学flask,看一下即可
import flask

app = flask.Flask(__name__)

@app.route('/')
def get():
    response = flask.make_response(flask.jsonify(
        {'name': 'leethon', 'age': 19, 'gender': 'male'}))
    # 允许其他域名跨域访问资源
    response.headers['Access-Control-Allow-Origin'] = '*'
    return response

if __name__ == '__main__':
    app.run()

解决跨域(浅)

​ 向请求头中添加键值对即可:Access-Control-Allow-Origin=*

import flask

app = flask.Flask(__name__)

@app.route('/')
def get():
    response = flask.make_response(flask.jsonify(
        {'name': 'leethon', 'age': 19, 'gender': 'male'}))
    # 允许其他域名跨域访问资源
    response.headers['Access-Control-Allow-Origin'] = '*'
    return response

if __name__ == '__main__':
    app.run()

fetch(JS内置的)(了解)

​ 是JS提供的接口,用于访问和操作HTTP管道的一些具体部分,比如请求和响应

​ 目前算是便捷的发送ajax的接口,支持最新的异步写法【promise】

用法:
// Vue对象内部的方法,其他部分参考上一节代码
methods: {
    loadInfo() {
        // 需要自己将字符串json反序列化
        fetch('http://127.0.0.1:5000/').then(response => response.json()).then(data=>{
            console.log(data)
            this.infoObj = data
        })
    },
}

axios发送ajax请求(主流)

是vue的第三方模块,基于xmlhttprequest封装的,比较轻量化

1.导入js文件,cdn或者文件形式
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.3.2/axios.min.js"></script>
用法:

​ 实例,点啥就是发啥请求,比如axios.get就是get请求,axios.post就是post请求

​ 对象里面封着的data才是真正的数据,如果后端返回的不是直接的数据而是又套了一层,比如说把数据封在了result里面,则还要继续点~

axios.get('域名').then(res=>)
————————————————————————————————

/*axios发送get请求*/
axios.get('http://127.0.0.1:5000/').then(resObj=>{
    console.log(resObj)
    this.infoObj = resObj.data
})
/*axios可以发送五种请求方式的请求*/
// axios.post()
// axios.delete()
// axios.put()
// axios.patch()

五、Vue生命周期

1.描述

​ 只要准备new出一个vue实例,就开始进入生命周期,在生命周期执行过程种,共计有八个钩子函数参与,比如说实例前,实例后,挂载执行前,执行后,数据更新执行前,执行后....

​ 钩子函数写了就会执行,不写就不会执行,其实这样使用钩子,就是面向切面编程的思想提现(AOP)

​ OOP:面向对象编程

beforeCreate	  创建Vue实例之前调用
created	          创建Vue实例成功后调用(可以在此处发送异步请求后端数据)
beforeMount	      渲染DOM之前调用
mounted	          渲染DOM之后调用
beforeUpdate	  重新渲染之前调用(数据更新等操作时,控制DOM重新渲染)
updated	          重新渲染完成之后调用
beforeDestroy	  销毁之前调用      # 如果写在vue实例上,后面这俩看不到
destroyed	      销毁之后调用

在这里插入图片描述

2.常用created钩子使用

写在methods下面
created(){
    this.handleclick()
}

意思就是打开这个页面,就直接加载handleclick函数直接朝后端拿数据展示

六、组件

​ 以后根组件就是vue,可以叠一堆分组件,每个组件都有自己独有的数据和方法等,可以封装可重用的代码,达到快速复用的目的

1.全局组件

​ 写在vue实例的外面,可以用于任意位置,可以套娃到全局组件的里面(一定要套到要套的全局组件的template里面的div里面啊!)

Vue.components('创建组件的名字',{
    template:'模板标签,但是是字符串形式'# 比如说<div></div> 这里面写内容
    data(){  # data必须是方法,返回对象
        return{}
    },
    methods:{}
    
})

___________________________________________
写好后,可以去任何想使用的地方,输入组件名字然后tab补齐
局部组件每次v-if 彻底消除后,数据又重新变为实例时的数据
————————————————————————————————————————————
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
      <script src="./js/vue.js"></script>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"
          integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
</head>
<body>
<div class="myDiv">
    <h1>我是全局</h1>
    <button @click="handClick">点击我,显示和隐藏组件</button>
<!--    <p>{{name}}</p>-->
<!--    <p>{{age}}</p>-->

<child v-if="show"></child>



</div>


</body>


<script>

    Vue.component('child', {
        template:'<div> 我是全局<button>后退</button><span>首页————{{name}}</span>' +
            '<button @click="handChangeName">前进(其实是改变name)</button></div>',
        data(){
            return{
                name:'李小狼'
            }
        },
        methods: {
            handChangeName(){
                this.name='木之本樱'
            }
        }
        }
    )

    var vm=new Vue({
        el:'.myDiv',
        data:{name:'李小狼',age:16,
        show:false
        },
        methods:{
            handClick(){
                this.show=!this.show
            }
        },

    })

</script>
</html>
研究destroyed钩子
Vue.component('child', {

            template: '<div> 我是全局<button>后退</button><span>首页————{{name}}</span>' +
                '<button @click="handChangeName">前进(其实是改变name)</button></div>',
            data() {
                return {
                    name: '李小狼',
                    a: null
                }
            },
            methods: {
                handChangeName() {
                    this.name = '木之本樱'
                }
            },
            created() {
                this.a = setInterval(() => {  #开启定时器
                    console.log(this.name)
                }, 1000)
            },
            destroyed() {
                clearInterval(this.a)  # 销毁定时器
                    this.a = null
                console.log('我清除了实例') 
            }
        }
    )

2.局部组件

​ 写在某个组件中,只能用于该组件下,写完名字后有些许变化,是:,而全局组件是,

components:{
    'lowTab':{template:'<div><h1>我是局部组件————{{city}}</h1></div>',
              data(){
                  return{city:'changsha'}
              }

             }
}

————————————————————————————————————————

也可以把整个局部组件对应的对象赋值给一个变量接收
var foo={template:'<div><h1>我是局部组件————{{city}}</h1></div>',
            data(){
                return{city:'changsha'}
            }

components:{
	foo
}

总结:

组件中的data必须是一个函数,并且return对象出去,防止共用变量名引用数据冲突 

今日注意:

1.写购物车时,总价函数中,循环数组用了for xx in 取不到!得用for xx of !!! in 在JS中是拿数组的索引值
2.依旧是写购物车,<input type="checkbox"  v-model="carList" :value="item">,是:value="item"
3.  a.forEach(
      (item)=>{console.log(item)}
  )
4.js中,Item对象被传入函数,因为js的对象是引用类型,在函数中修改,原来的也被影响了
5.el: '#myDiv' 不用加()
6.5-7年内json依旧是主流
7.如果一个局部组件被放进去了全局组件,他就是被全局组件管理,而不是产生自己的组件管理,就会失效
posted @   yiwufish  阅读(201)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示