首页 > 其他分享 >vue-购物车案例、前后端交互、vue生命周期、组件

vue-购物车案例、前后端交互、vue生命周期、组件

时间:2023-02-16 22:59:03浏览次数:45  
标签:生命周期 name price number 购物车 item vue checkGroup data

1.购物车案例

1.1 基本版购物车

js的变量只要发生变化,html页面中使用该变量的地方,就会重新渲染
<body>
    <div id="app">
        <div class="container-fluid">
            <div class="row">
                <div class="col-md-6 col-md-offset-3">
                    <h1 class="text-center">购物车案例</h1>
                    <table class="table-striped table-hover table">
                        <thead>
                            <tr>
                                <th>商品编号</th>
                                <th>商品名字</th>
                                <th>商品价格</th>
                                <th>商品数量</th>
                                <th>选择</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr v-for="item in goodlist">
                                <td>{{item.id}}</td>
                                <td>{{item.name}}</td>
                                <td>{{item.price}}</td>
                                <td>{{item.number}}</td>
                                <td><input type="checkbox" name="" id="" v-model="checkGroup" :value="item"></td>
                            </tr>
                        </tbody>
                    </table>
                    <p>{{checkGroup}}</p>  <!--v-model关联checkGroup所以选中值就会改变,该参数是为了看起来方便,可以取消-->
                    <p>总价格:{{getTotal()}}</p>  <!--插值语法也可以插函数,要加括号-->
                </div>
            </div>
        </div>
    </div>
</body>
<script>
    var vm = new Vue({
        el:'#app',
        data:{
            goodlist:[
                {id: '1', name: '钢笔', price: 20.1, number: 2},
                {id: '2', name: '饼干', price: 4, number: 1},
                {id: '3', name: '辣条', price: 5, number: 5},
            ],
            checkGroup:[]
        },
        methods:{
            getTotal(){
                var total=0
                for (item of this.checkGroup){
                    total+=item.price*item.number
                }
                return total
            }
        }
    })
</script>

1.2 带全选全不选

基本逻辑:全选意味着列表checkGroup和goodlist完全一样,并且checkbox类型的布尔值选中之后,用v-model和它绑定的布尔值就会变成true,取消选择就会变成false,所以我们只需要根据全选框是否打钩,来决定checkGroup的值。
<body>
<div id="app">
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-6 col-md-offset-3">
                <h1 class="text-center">购物车案例</h1>
                <table class="table-striped table-hover table">
                    <thead>
                    <tr>
                        <th>商品编号</th>
                        <th>商品名字</th>
                        <th>商品价格</th>
                        <th>商品数量</th>
                        <th>全选/全不选 <input type="checkbox" v-model="checkAll" @change="getAll"></th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr v-for="item in goodlist">
                        <td>{{item.id}}</td>
                        <td>{{item.name}}</td>
                        <td>{{item.price}}</td>
                        <td>{{item.number}}</td>
                        <td><input type="checkbox" name="" id="" v-model="checkGroup" :value="item"></td>
                    </tr>
                    </tbody>
                </table>
                <p>{{checkGroup}}</p>  <!--v-model关联checkGroup所以选中值就会改变-->
                <p>总价格:{{getTotal()}}</p>  <!--插值语法也可以插函数,要加括号-->
            </div>
        </div>
    </div>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            goodlist: [
                {id: '1', name: '钢笔', price: 20.1, number: 2},
                {id: '2', name: '饼干', price: 4, number: 1},
                {id: '3', name: '辣条', price: 5, number: 5},
            ],
            checkGroup: [],
            checkAll: false
        },
        methods: {
            getTotal() {
                var total = 0
                for (item of this.checkGroup) {
                    total += item.price * item.number
                }
                return total
            },
            getAll() {
                // console.log(this.checkAll)  // 绑定布尔值的多选框,选中该布尔值就是true,否则就是false
                if (this.checkAll === true) {
                    this.checkGroup = this.goodlist
                } else {
                    this.checkGroup = []
                }
            }
        }
    })
</script>

1.3 带加减的购物车

<body>
<div id="app">
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-6 col-md-offset-3">
                <h1 class="text-center">购物车案例</h1>
                <table class="table-striped table-hover table">
                    <thead>
                    <tr>
                        <th>商品编号</th>
                        <th>商品名字</th>
                        <th>商品价格</th>
                        <th>商品数量</th>
                        <th>全选/全不选 <input type="checkbox" v-model="checkAll" @change="getAll"></th>                      
                    </tr>
                    </thead>
                    <tbody>
                    <tr v-for="item in goodlist">
                        <td>{{item.id}}</td>
                        <td>{{item.name}}</td>
                        <td>{{item.price}}</td>
                        <td><button @click="item.number++">+</button>{{item.number}}<button @click="downClick(item)">-</button></td>
                        <td><input type="checkbox" name="" id="" v-model="checkGroup" :value="item"></td>                    
                    </tr>
                    </tbody>
                </table>
                <p>{{checkGroup}}</p>  <!--v-model关联checkGroup所以选中值就会改变-->
                <p>总价格:{{getTotal()}}</p>  <!--插值语法也可以插函数,要加括号-->
            </div>
        </div>
    </div>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            goodlist: [
                {id: '1', name: '钢笔', price: 20.1, number: 2},
                {id: '2', name: '饼干', price: 4, number: 1},
                {id: '3', name: '辣条', price: 5, number: 5},
            ],
            checkGroup: [],
            checkAll: false
        },
        methods: {
            getTotal() {
                var total = 0
                for (item of this.checkGroup) {
                    total += item.price * item.number
                }
                return total
            },
            getAll() {
                // console.log(this.checkAll)  // 绑定布尔值的多选框,选中该布尔值就是true,否则就是false
                if (this.checkAll === true) {
                    this.checkGroup = this.goodlist
                } else {
                    this.checkGroup = []
                }
            },
            downClick(item){
                if (item.number>1){
                    item.number--
                }else{
                    alert('不能在减少啦')
                }
            }
           
        }
    })
</script>

1.4 带删除的购物车

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
    <link rel="stylesheet" href="bootstrap-3.4.1-dist/css/bootstrap.min.css">
    <script src="bootstrap-3.4.1-dist/js/bootstrap.min.js"></script>
</head>
<body>
<div id="app">
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-6 col-md-offset-3">
                <h1 class="text-center">购物车案例</h1>
                <table class="table-striped table-hover table">
                    <thead>
                    <tr>
                        <th>商品编号</th>
                        <th>商品名字</th>
                        <th>商品价格</th>
                        <th>商品数量</th>
                        <th>全选/全不选 <input type="checkbox" v-model="checkAll" @change="getAll"></th>
                        <th>删除尚品</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr v-for="item in goodlist">
                        <td>{{item.id}}</td>
                        <td>{{item.name}}</td>
                        <td>{{item.price}}</td>
                        <td>
                            <button @click="item.number++">+</button>
                            {{item.number}}
                            <button @click="downClick(item)">-</button>
                        </td>
                        <td><input type="checkbox" name="" id="" v-model="checkGroup" :value="item"></td>
                        <td>
                            <button class="btn btn-danger" @click="deleteClick(item)">删除</button>
                        </td>
                    </tr>
                    </tbody>
                </table>
                <p>{{checkGroup}}</p>  <!--v-model关联checkGroup所以选中值就会改变-->
                <p>总价格:{{getTotal()}}</p>  <!--插值语法也可以插函数,要加括号-->
            </div>
        </div>
    </div>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            goodlist: [
                {id: '1', name: '钢笔', price: 20.1, number: 2},
                {id: '2', name: '饼干', price: 4, number: 1},
                {id: '3', name: '辣条', price: 5, number: 5},
            ],
            checkGroup: [],
            checkAll: false
        },
        methods: {
            getTotal() {
                var total = 0
                for (item of this.checkGroup) {
                    total += item.price * item.number
                }
                return total
            },
            getAll() {
                if (this.checkAll === true) {
                    this.checkGroup = this.goodlist
                } else {
                    this.checkGroup = []
                }
            },
            downClick(item) {
                if (item.number > 1) {
                    item.number--
                } else {
                    alert('不能在减少啦')
                }
            },
            deleteClick(item) {
                this.goodlist.splice(this.goodlist.indexOf(item),1)  // 首先在goodlist删掉该商品
                if(this.checkGroup.indexOf(item)>=0){  // 在判断如果该商品在临时列表,在的话就从临时列表删除
                    this.checkGroup.splice(this.checkGroup.indexOf(item),1)
                }
            }
        }
    })
</script>

2.v-model进阶操作

1.lazy:等到input框输入完成,失去焦点之后再变化。
2.number:数字开头时,只保留数字,后面输入的字母不会显示。如果开头不是数字,那么所有字符都能正常显示。
3.trim:输入框开头有空格时将空格去掉。
<body>
  <div id="app">
    <h1>lazy用法</h1>
    <input type="text" v-model.lazy="myText">{{myText}}
    <h1>number用法</h1>
    <input type="text" v-model.number="myText1">{{myText1}}
    <h1>trim用法</h1>
    <input type="text" v-model.trim="myText2">{{myText2}}
  </div>
</body>
<script>
  var vm = new Vue({
    el:'#app',
    data:{
      'myText':'',
      'myText1':'',
      'myText2':'',
    }
  })
</script>

3.与后端交互

3.1 jquery的ajax

后期jquery和vue一般不同时使用。
前端代码:
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
</head>
<body>
    <div id="app">
        <button @click="handClick">点我获取用户数据</button>
   </div>
</body>
<script>
    var vm = new Vue({
        el:'#app',
        data:{
            userInfo:{}
        },
        methods:{
            handClick(){
                $.ajax({
                    url:'http://127.0.0.1:8000/api/user/sendmsg/',
                    type:'get',
                    success:data=>{
                        console.log(data)
                    }
                })
            }
        }
    })
</script>

1.运行以上代码,在我们在前端向django框架的后端发送get请求,会报以下错误:
from origin 'http://localhost:63342' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

这是由于跨域问题:只要向不是地址栏中的 [域:地址和端口]发送请求,拿的数据,后端给的数据被浏览器就给拦截了。跨域的安全限制,主要是针对浏览器端来说的,服务器端是不存在跨域安全限制的。

2.跨域问题处理:
	后端代码处理:在响应头中加入允许。
"""
在Http四件套中如何添加响应头?
def indexfunc(request):
    obj = HttpResponse('hhh')  先生成一个HttpResponse的对象
    obj['msg'] = 'success'	给对象添加键值对
    return obj
"""
我们将django视图类做如下修改:
views.py:
class Messgae(ViewSetMixin, APIView):
    @action(methods=['GET', ], detail=False)
    def sendmsg(self, request):
        obj = Response({'name': 'max', 'age': 25, 'hobbies': ['soccer', 'run']})
        obj['xx'] = 'success'
        return obj
  
可以看到我们的响应头已经成功传到浏览器:

但是我们要传的键值对不是xx,而是错误提示中的:Access-Control-Allow-Origin。我们将后端代码做如下修改,就可以看到前端成功拿到数据:
class Messgae(ViewSetMixin, APIView):
    @action(methods=['GET', ], detail=False)
    def sendmsg(self, request):
        obj = Response({'name': 'max', 'age': 25, 'hobbies': ['soccer', 'run']})
        obj['Access-Control-Allow-Origin'] = '*'
        return obj
可以在前端将信息显示在页面上:
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
</head>
<body>
    <div id="app">
        <button @click="handClick">点我获取用户数据</button>
        <p>用户姓名:{{userInfo.name}}</p>
        <p>用户年龄:{{userInfo.age}}</p>
        <p>用户爱好:{{userInfo.hobbies}}</p>
   </div>
</body>
<script>
    var vm = new Vue({
        el:'#app',
        data:{
            userInfo:{}
        },
        methods:{
            handClick(){
                $.ajax({
                    url:'http://127.0.0.1:8000/api/user/sendmsg/',
                    type:'get',
                    success:data=>{
                        this.userInfo=data
                    }
                })
            }
        }
    })
</script>

3.2 fetch发送ajax请求

fetch:提供了一个 JavaScript 接口,用于访问和操纵 HTTP 管道的一些具体部分,例如请求和响应
	-新的发送ajax 接口
    -用起来比较方便
    -支持promise写法[最新的异步写法]
    -解决了原生的XMLHttpRequest兼容性的问题
    -不是所有浏览器都支持
    -主流现在是用axios[第三方]发送请求
XMLHttpRequest: 原生js提供的
	-比较老,不同浏览器需要做一些兼容性的处理,写起来比较麻烦
    -jq基于它做了封装

2.前端代码:
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
    <button @click="handClick">点我获取用户数据</button>
        <p>用户姓名:{{userInfo.name}}</p>
        <p>用户年龄:{{userInfo.age}}</p>
        <p>用户爱好:{{userInfo.hobbies}}</p>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            userInfo: {
                name: '',
                age: 0,
                hobbies: ''
            }
        },
        methods: {
            handClick() {
                fetch('http://127.0.0.1:8000/api/user/sendmsg/').then(response => response.json()).then(res => {
                    this.userInfo.name=res.name
                    this.userInfo.age=res.age
                    this.userInfo.hobbies=res.hobbies

                })  // 前端代码需要这样写
            }
        }
    })
</script>

服务端views.py:
class Messgae(ViewSetMixin, APIView):
    @action(methods=['GET', ], detail=False)
    def sendmsg(self, request):
        obj = Response({'name': 'max', 'age': 25, 'hobbies': ['soccer', 'run']})
        obj['Access-Control-Allow-Origin'] = '*'
        return obj

3.3 axios发送ajax请求

用户在vue上都适用axios发送ajax请求。Axios 是一个基于 promise 的 HTTP 库,还是基于XMLHttpRequest封装的。
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/axios.js"></script>
    <script src="js/vue.js"></script>
  <!--或者使用cdn导入:<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
-->
</head>
<body>
  <div id="app">
    <button @click="handClick">点我获取用户数据</button>
  </div>
</body>
<script>
  axios.get('http://127.0.0.1:8000/api/user/sendmsg/').then(res=>{
    console.log(res)  // res是真正响应体中的内容,后端的真正数据是res.data
  })
</script>

服务端views.py:
class Messgae(ViewSetMixin, APIView):
    @action(methods=['GET', ], detail=False)
    def sendmsg(self, request):
        obj = Response({'name': 'max', 'age': 25, 'hobbies': ['soccer', 'run']})
        obj['Access-Control-Allow-Origin'] = '*'
        return obj

服务端urls.py:
from django.contrib import admin
from django.urls import path,include
from rest_framework.routers import SimpleRouter
from app01 import views
router = SimpleRouter()
router.register('user',views.Messgae,'user')

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/',include(router.urls))
]

点击按钮可以看到前端打印了对象,但是该对象做了一层封装,对象里面的data才是后端的对象。

3.4 实战练习:电影信息排布

该作业主要是为了实战axios接收后端数据,结合for循环将电影信息展示在页面上。
首先在路由:https://m.maizuo.com/v5/?co=mzmovie#/films/nowPlaying拿到电影信息:

然后根据response是电影信息的来筛选请求,将返回的电影信息保存到本地。

服务端views.py代码:
import json
class Film(ViewSetMixin, APIView):
    @action(methods=['GET', ], detail=False)
    def film(self,request):
        with open(r'film.json', 'r', encoding='utf-8') as f:
            res = json.load(f)  <!--load和dump针对文件-->
            obj = Response(res)
            obj['Access-Control-Allow-Origin'] = '*'
        return obj

服务端urls.py:
from django.contrib import admin
from django.urls import path,include
from rest_framework.routers import SimpleRouter
from app01 import views
router = SimpleRouter()
router.register('user',views.Messgae,'user')
router.register('film',views.Film,'film')

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/',include(router.urls))
]

前端代码:
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
    <script src="./js/axios.js"></script>


</head>
<body>
<div class="app">
    <h1>热映电影</h1>
    <button @click="handleClick">点我</button>
    <ul>
        <li v-for="item in dataList">
            <h2>名字:{{item.name}}</h2>
            <h3>导演:{{item.director}}</h3>
            <h3>类型:{{item.category}}</h3>
            <p>简介:{{item.synopsis}}</p>
            <img :src="item.poster" alt="" height="300px" width="200px">  // for循环中src对应对的值是变动的,所以前面要加:

        </li>
    </ul>

</div>
</body>
<script>
    var vm = new Vue({
        el: '.app',
        data: {
            dataList: []
        },
        methods: {
            handleClick() {
                axios.get('http://127.0.0.1:5000/film').then(res => {
                    this.dataList = res.data.data.films
                })  // request.data才是后端发送的真实数据


            }
        }

    })
</script>

4.vue生命周期

# 从vue实例创建开始,到实例被销毁,总共经历了8个生命周期钩子[只要写了就会执行]函数
	-钩子:反序列化验证---》钩子函数
    -学名[专门名字]---》面向切面编程(AOP)
    -OOP:面向对象编程
        
        
# 8个生命周期钩子函数
    beforeCreate	  创建Vue实例之前调用
    created	          创建Vue实例成功后调用(可以在此处发送异步请求后端数据)
    beforeMount	      渲染DOM之前调用
    mounted	          渲染DOM之后调用
    beforeUpdate	  重新渲染之前调用(数据更新等操作时,控制DOM重新渲染)
    updated	          重新渲染完成之后调用
    beforeDestroy	  销毁之前调用
    destroyed	      销毁之后调用



# 重点:
	-1 用的最多的,created  发送ajax请求----》有的人放在mounted中加载
	-2 beforeDestroy
    	-组件一创建,created中启动一个定时器
        -组件被销毁,beforeDestroy销毁定时器
	


# 实现实时聊天效果(在线聊天室)
	-轮询:定时器+ajax   http:http版本区别
    -长轮询:定时器+ajax  http
    -websocket协议:服务端主动推送消息
    https://zhuanlan.zhihu.com/p/371500343

5 vue组件

# 组件化开发的好处:重用代码
# 组件分类
	-全局组件:在任意组件中都可以使用
    -局部组件:只能在当前组件中使用

定义全局组件

Vue.component('child', {
    template: `
      <div>
      <button>后退</button>
      <span style="font-size: 40px">首页--{{ name }}</span>
      <button @click="handleFor">前进</button>
      <lqz1></lqz1>
      </div>`,// 里面写html内容,必须包在一个标签中
    data() {              // data必须是方法,返回对象
        return {
            name: '彭于晏',
            t: null
        }
    },
    methods: {
        handleFor() {
            this.name = 'lqz'
        }
    },
    components: {
        'lqz1': {
            template: `
              <div>
              <h1>局部组件---{{ age }}</h1>
              </div>`,
            data() {
                return {
                    age: 19
                }
            }
        },

    }


})

定义局部组件

var foo={
                template: `
                  <div>
                  <h1>局部组件---{{ age }}</h1>
                  </div>`,
                data() {
                    return {
                        age: 19
                    }
                }
            }



    var vm = new Vue({
   		...
        components: {
            foo

        }


    })

补充

# 1 之前前后端交互,使用xml格式
# 2 后来json 格式出现,前后端交互,主流都是json格式
	-可能觉得不安全
    -前后端加密解密方式
    
# 4 目前有些比json更安全,高效,节约空间的编码格式,后期可能前后端交互使用某种
	

标签:生命周期,name,price,number,购物车,item,vue,checkGroup,data
From: https://www.cnblogs.com/ERROR404Notfound/p/17128594.html

相关文章

  • vue2 - 目录
    vue2-模板语法插值语法,属性单向绑定,属性双向绑定,v-clock,v-text,v-html,v-once,v-prevue2-事件,事件的绑定,事件属性,键盘事件vue2-计算属性,计算属性简写,监听属性,深度监......
  • V-model进阶 Vue与后端交互,Vue生命周期,Vue组件
    目录v-model进阶操作与后端交互jq的ajax与后端交互drf接口vuehtml页面fetch与后端交互代码axios发送ajax请求代码小电影项目接口页面vue生命周期重点:创建组件全局组件局部......
  • 如何优化 Vue.js 应用程序
    单页面应用(SPAs)当处理实时、异步数据时,可以提供丰富的、可交互的用户体验。但它们也可能很重,很臃肿,而且性能很差。在这篇文章中,我们将介绍一些前端优化技巧,以保持我们的Vue......
  • vue2 - 绑定class,绑定style
    1.绑定class样式字符串写法:适用于类名不确定,要动态获取数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。对象写法适用于:要绑定多个样式,个数不确定,名字......
  • vue2 - 计算属性,计算属性简写,监听属性,深度监听,监听属性简写,两个重要的小原则
    1.计算属性<divid="root">性:<inputtype="text"v-model:value="firstName"><br>名:<inputtype="text"v-model:value="lastName"><br>全名:<span>{{full......
  • vue day04
    一、简单购物车1.勾选显示总价购物车<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>购物车</title><scriptsrc="./js/vue.js">......
  • Vue框架:5、购物车案例,v-model进阶操作,与后端交互的方式
    目录前端开发之Vue框架一、购物车案例1、基本购物车2、购物车-优化二、v-model进阶操作三、与后端交互1、jqery对象的ajax2、fetch发送ajax请求3、axios发送ajax请求4、展......
  • Vue框架:4、Vue生命周期,Vue组件
    目录前端开发之Vue框架一、Vue生命周期1、vue生命周期是什么?2、vue生命周期的八个阶段二、Vue组件1、组件是什么2、全局组件2、组件小结前端开发之Vue框架一、Vue生命......
  • vue 购物车案例
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title><scriptsrc="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jqu......
  • Vue_侦听器watch
    方法格式监听器在Vue的watch节点下data:{ username:'Exungsh'}watch:{ username(newVal,oldVal){ console.log(newVal,oldVal) } //如果要侦听的是对象的子......