前端之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.如果一个局部组件被放进去了全局组件,他就是被全局组件管理,而不是产生自己的组件管理,就会失效
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!