昨日回顾

#1  style,class
-字符串
-数组
-对象
-横杠转驼峰体
# 2 v-if=条件 v-else-if=条件 v-else
# 3 v-for='(i,k)in 数字,数组,字符串,对象'
-基于索引的循环 (i=0;i<10;i++)
-in 循环出来的是索引
-of 基于迭代的,循环出来就是值
-数组.each(item=>{})
-ajax forEach 循环
# 4 key值得解释:v-for上的标签上,尽量写 :key=唯一值
# 5 数组和对象的检测与更新:
Vue.set(要改得值,0,改成的值)
# 6 input: v-model
# 7 input的事件:blur,change,input
# 8 过滤案例
-1 数组的filter方法
数组=数组.filter(function(item){return true})
-2 字符串.indexOf(子字符串) 返回子字符串在当前字符串的位置 如果 >=0 说明在里面
-3 es6 对象写法
{'name':'lqz'}--->{name:'lqz'}
var a='lqz'
var f=function(itemt){}
{a,f(){}}
-4 箭头函数
数组.filter(item=>true)
有一个参数的,多个参数,有返回值并且只有一行
箭头函数没有自己的this
# 9 事件修饰符
.stop
.self
.prevent
.once
# 10 按键修饰符
@keyup.esc='函数'
@keyup.enter='函数'
@keyup.13='函数' (Keycode值,这种写法在Vue3中被弃用)
# 11 表单控制
-radio :字符串类型 多个radio使用v-model绑定,选中某个会把 value 赋值给这个变量
-chekbox
-单选:布尔类型
-多选:数组中

表单数据双向绑定(重要)

# input:checkbox(单选,多选),radio(单选)

checkbox单选 --- 布尔值

给checkbox的v-model该如何绑定?

这样如果选中checkbox,变量isRemeber的值就会变成true

checkbox多选 --- 数组

所有checkbox都使用一个数组:

如:

每次选中checkbox,都会把value值放入数组:

radio单选 --- 字符串

如何对radio单选框进行双向数据绑定?

这里的意思是如果你选了,就会将标签value所对应的值赋值给gender,此时gender:'男'

value需要每个都不一样。

通常会这样表示不同的选项:

给后端发送数据

写一个按钮:

所有的数据都是双向绑定的,并且所有的数据都在Vue对象的data属性中,直接获取即可,相当方便。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
<h1>表单控制</h1>
<p>用户名:<input type="text" v-model="name"></p>
<p>密码:<input type="text" v-model="password"></p>
<p><input type="checkbox" v-model="isRemember"> 记住密码</p>
<p>
<input type="radio" v-model="gender" value="1"> 男
<input type="radio" v-model="gender" value="2"> 女
<input type="radio" v-model="gender" value="0"> 未知
</p>
<p>
爱好:
<input type="checkbox" value="篮球" v-model="hobby"> 篮球
<input type="checkbox" value="足球" v-model="hobby"> 足球
<input type="checkbox" value="乒乓球" v-model="hobby"> 乒乓球
<input type="checkbox" value="橄榄球" v-model="hobby"> 橄榄球
</p>
{{hobby}} </div>
</body> <script> new Vue({
el: '#app',
data: {
name: '',
password: '',
isRemember: false, // checkbox单选,使用布尔类型
gender: '', // radio单选,使用字符串
hobby: [], // checkbox 多选使用数组
},
})
</script>
</html>

购物车案例

使用v-model将checkbox与数组进行双向绑定,每次点击或者取消checkbox都会导致数组的变化:

需要注意的是,checkbox的value属性应该放一个商品对象item,这样后续获取数据方便。

编写getPrice函数:

 methods: {
getPrice() {
// 通过checkGroup里面的对象,计算出总价格
var total = 0
for (item of this.checkGroup) {
total += item.price * item.number
}
return total
}
}

页面上使用插值语法:{{ getPrice() }},即可实现需求。

每次点击checkbox,checkGroup数组都会发生变化,都会运行getPrice函数,函数的返回值会通过插值语法{{ getPrice() }}即时的渲染到页面上。

  • js的变量只要发生变化,html页面中使用该变量的地方,就会重新渲染。(通过虚拟dom)

也就是因为checkGroup发生了变化,所以引用到这个变量的 getPrice()也会发生变化。虚拟dom会和真实dom进行比较,发现页面有变化的地方,针对这些地方进行更新。使得最终页面只有部分发生变化,而不是整体重新渲染。

全选按钮

这个全选按钮和之前的checkbox不能绑定同一个数组,而是使用新的数组。

给全选按钮添加@change事件,点击全选按钮之后,让数组添加所有数据,因为数组的数据是跟页面绑定的,所以只需修改数组即可,前端页面也会发生变化:

再给每个商品的选择按钮添加一个点击事件,用于判断是否需要将全选按钮勾选上:

<!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="app">
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h1>购物车案例</h1> <table class="table table-bordered">
<thead>
<tr>
<th>商品编号</th>
<th>商品名字</th>
<th>商品价格</th>
<th>商品数量</th>
<th>全选/全不选 <input type="checkbox" v-model="checkAll" @change="handleCheckAll"></th>
</tr>
</thead>
<tbody>
<tr v-for="item in goodList">
<th scope="row">{{item.id}}</th>
<td>{{item.name}}</td>
<td>{{item.price}}</td>
<td>{{item.number}}</td>
<td><input type="checkbox" v-model="checkGroup" :value="item" @change="handelCheckOne"></td>
</tr>
</tbody>
</table>
<hr>
<p>选中商品:{{checkGroup}}---{{checkAll}}</p>
<p>总价格:{{getPrice()}}</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: {
getPrice() {
// 通过checkGroup里面的对象,计算出总价格
var total = 0
for (item of this.checkGroup) {
total += item.price * item.number
}
return total
},
handleCheckAll() {
if (this.checkAll) {
this.checkGroup = this.goodList
} else {
this.checkGroup = []
}
},
handelCheckOne() {
// console.log('一个被点了')
if (this.checkGroup.length==this.goodList.length){
this.checkAll=true
}else {
this.checkAll=false
}
}
} })
</script>
</html>

点击事件对应的函数:

商品添加删除

商品加减功能,给按钮绑定点击事件:

@click="item.number++":点击事件后面可以写简单的逻辑代码。

商品的添加不能超过库存:

页面加载好时,就已经获取到商品的库存值,如果添加的商品超过库存,那么就禁止商品添加。

减少商品的时候,会出现负数的问题:

需要添加函数限制一下。将item传入点击事件:

<!-- 部分html -->
<td>
<button @click="handleDown(item)">-</button>
{{item.number}}
<button @click="item.number++">+</button>
</td> <!-- 部分js -->
handleDown(item) {
if (item.number > 1) {
item.number-- } else {
alert('太少了,受不了了')
}

注意:减少商品,不能减少到0,最少减少到1。再添加一个删除按钮,对购物车的商品进行删除。(如果是真正的购物车,需要发送一个ajax请求去数据库将购物车的数据删除)

库存校验

添加库存数据:

代码:


# 部分html
<td>
<button class=" btn-default" @click="addGood(good)"></button>
<button>{{ good.count }}</button>
<button class="btn-default" @click="delGood(good)"></button>
</td> # 部分js
addGood(good) {
if (good.count < good.store) {
good.count++
}
},
delGood(good) {
if (good.count > 1) {
good.count--
}
},

可变类型不可变类型

python函数参数是值传递还是引用传递?

python中没有值传递和引用传递的概念。取而代之的是可变类型和不可变类型。

把一个变量传入函数内,在函数内将变量进行修改。

  • 如果传入的是不可变类型,外部的变量不会一同被修改。
  • 如果传入的是可变类型,外部的变量会被一同修改。

js中的对象在函数内部修改,外部的变量也会被影响。

代码:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
<link rel="stylesheet" href="./js/bootstrap.css">
</head>
<body>
<div id="app">
<div class="container-fluid">
<div class="row top">
<div class="col-md-6 col-md-offset-3">
<h2 class="text-center">购物车</h2>
<table class="table table-bordered">
<thead>
<tr>
<th>编号</th>
<th>商品</th>
<th>价格</th>
<th>数量</th>
<th>全选
<input v-model="checkAll" type="checkbox" @change="handleCheckAll">
</th>
</tr>
</thead>
<tbody>
<tr v-for="good in shopCar">
<td>{{good.id}}</td>
<td>{{good.name}}</td>
<td>{{good.price}}</td>
<td>
<button class=" btn-default" @click="addGood(good)"></button>
{{ good.count }}
<button class="btn-default" @click="delGood(good)"></button>
</td>
<td :id="good.id">
<input class="btn btn-default" type="checkbox" v-model="goodList" :value="good"
@change="handleCheckOne">
<!-- 不能使用点击事件,因为点击事件快于v-model的双向数据绑定 -->
</td>
</tr>
</tbody>
</table>
<h4>总价格:{{ getPrice() }}</h4> </div>
</div>
</div> </div>
<script>
var vm = new Vue({
el: '#app',
data: {
shopCar: [
{id: 1, name: '曹操戏张飞', price: 10, count: 1, store: 5},
{id: 2, name: '仿真玩偶', price: 100, count: 1, store: 5},
{id: 3, name: '印度飞饼', price: 1000, count: 1, store: 5},
{id: 4, name: '仿真玩偶plus', price: 10000, count: 1, store: 5},
],
goodList: [],
checkAll: false,
},
methods: {
getPrice() {
var total = 0
for (item of this.goodList) {
total += item.price * item.count
}
return total
},
handleCheckAll() {
if (this.checkAll) {
this.goodList = this.shopCar
} else {
this.goodList = []
}
},
handleCheckOne() {
this.checkAll = this.goodList.length === this.shopCar.length;
},
addGood(good){
if (good.count<good.store){
good.count++
}
},
delGood(good) {
if (good.count > 1) {
good.count--
}
},
}
})
</script>
</body>
</html>

v-model进阶(了解)

lazy:等待input框的数据绑定失去焦点之后再变化
number:数字开头,只保留数字,后面的字母不保留;字母开头,都保留
trim:去除首位的空格

v-mode.lazy

示例:

由于数据做了双向绑定,每次只要输入数据,页面都会发生变化(其实页面是在更新的),这样是非常消耗资源的。

而我们通常只想要用户输入的数据,所以这个时候就可以使用v-model.lazy:

此时当input输入框失去焦点的时候,页面才会发生变化:

v-model.number

当数字开头时,会对输入的数字进行双向绑定,增删数字会即时的渲染在页面上;如果后续输入字母,不会对字母渲染:

当字母开头时,就相当于就是普通的input框数据和页面双向绑定了:

v-model.trim

当input输入框带空格时,v-model.trim可以删除首尾的空格,同时对输入数据进行双向绑定:

代码:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
<h1>v-model进阶</h1>
<input type="text" v-model.lazy="name1"> ---->{{name1}}
<br>
<input type="text" v-model.number="name2"> ---->{{name2}}
<br>
<input type="text" v-model.trim="name3"> ---->{{name3}} </div>
</body> <script> new Vue({
el: '#app',
data: {
name1: '',
name2: '',
name3: '',
}, })
</script>
</html>

vue生命周期

Vue对象的四个过程

# var vm=new Vue实例() 这行代码做了什么事?
-1 实例创建,data数据存放到实例中
-2 挂载模板:el --挂载到--> div
- 挂载结束后,数据与变量实现双向绑定
-3 改页面,改变量,都会相互影响 (update)
- 修改页面或修改变量都不会重新执行上面1、2步
- 浏览器再转圈
-4 销毁实例(页面关闭)

八个钩子函数

上述Vue生命周期的4个过程对应如下8个方法。也叫8个钩子函数。

# 4个过程,对应八个函数,依次执行(到某个过程就会执行某个函数
# 每个过程对应两个钩子函数
-1 实例创建
beforeCreate 创建Vue实例之前调用,data,el都没有
created 创建Vue实例成功后调用(可以在此处发送异步请求后端数据),data有了,el没有的 -2 挂载模板
beforeMount 渲染DOM之前调用 ,data有了,el没有
mounted 渲染DOM之后调用 -3 修改页面、修改变量
beforeUpdate 重新渲染之前调用(数据更新等操作时,控制DOM重新渲染)
updated 重新渲染完成之后调用 -4 销毁实例
beforeDestroy 销毁之前调用
destroyed 销毁之后调用
  • 什么叫做钩子函数?(hook)

    Hook 技术又叫做钩子函数,在系统没有调用该函数之前,钩子程序就先捕获该消息,钩子函数先得到控制权,这时钩子函数既可以加工处理(改变)该函数的执行行为,还可以强制结束消息的传递。简单来说,就是把系统的程序拉出来变成我们自己执行代码片段。

  • 钩子函数是AOP的体现(面向切面编程):

    将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。

    python中装饰器可以实现aop。

简单的说,就是你在程序中写了钩子函数,钩子函数就执行,不写就不执行。

# 5 钩子函数(hook)
AOP的体现:面向切面编程 --> 装饰器实现aop # 6 vm实例:看不到它销毁 组件vc
销毁vm实例需要关闭页面 --> 无法看见销毁vm的打印
组件vc --> 是一个对象 --> 可以看到完整的生命周期

研究Vue的生命周期

钩子函数是写到配置项里的,和el是同级的,并且他的名字是固定的,比如:

一个八个,这些钩子函数会依次去执行。

页面一刷新,钩子函数就开始执行:

此时已经挂载完成了,也就是执行到Vue生命周期的第二个过程。

当我们进行了变量的修改,此时页面会更新,也就会执行钩子函数:

如果再次修改,这两个钩子函数还会执行。

当页面被销毁,我们就看不到控制台的输出了,但是页面销毁会执行剩余的两个钩子函数。

全局组件

全局组件如何定义?

使用Vue.component('组件名',{配置项})

Vue.component的第二个参数就相当于Vue()el配置项。

注意:data的写法有些不同,在这个data函数的返回值的对象里写组件相关的数据。

为什么组件的数据使用data()函数存放?

组件可以使用多次,每个组件用自己的数据,每个组件都是用的函数返回的数据(每次都返回一个新的对象)。如果不是函数,是对象,相当于每次调用组件都使用的是同一份数据(同一个对象)。

将8个钩子函数放入全局组件:

template怎么写?

template里写html代码,组件内data内的数据,可以使用插值语法渲染在组件内。

如何将组件放在我们原来的html页面?

相当于自定义了一个标签<child></child>,会把template的内容渲染到child标签的位置。

组件template内的名字和组件外的名字是可以重复的,不会互相影响。

实现组件的显示和消失(在根组件写代码):

组件有自己的样式、自己的事件。

根组件和子组件:

组件如何更新?

在组件的methods部分写事件相关函数。

数据更新时,会执行组件的更新相关的两个钩子函数。

但使用根组件让子组件销毁,会执行子组件的销毁相关钩子函数:

在组件created方法向后端发送ajax

为什么要在created?

# 8 学习生命周期重点掌握的
-1 组件向后端发送请求,获取数据,应该放在 created 写,此时data已经有数据了
-2 destroyed做一些资源清理性的工作

子组件有自己的数据,数据是从后端加载过来的,子组件是什么时候向后端发送请求获取数据的?是在生命周期的哪个位置?

应该在created函数执行时。data数据已经获取了,挂载还没有进行,所以el还不存在。

this是当前子组件:

查看前端:

  • beforeCreate时,data和el都没有.
  • created时,data有了,但是由于还未挂载所以el没有

  • beforeMount:此时data有了,el还未挂载
  • mounted: 终于el挂载到template

注意:前端向后端发送ajax请求放在created函数里,不要放在beforeCreate此时前端数据不存在。ajax请求在mounted也可以,如果前端加载很慢的话,前端可能会先显示一个默认值,然后再显示从后端接受到的数据。数据变化之后,页面会刷新。

destroyed资源清理

destroyed做一些资源清理性的工作:

如果在组件的created中执行了一些任务,那么当组件销毁了,可能这些任务还没销毁,这种情况就不太合适。所以就需要使用destroyedbeforeDestory做一些资源清理的工作。

组件销毁时,销毁定时器:

代码:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
<h1>vue声明周期</h1>
<button @click="handleShow">点我组件显示和消失</button>
<hr>
<child v-if="show"></child>
<hr>
</div>
</body>
<script> // 定义一个全局组件
Vue.component('child', {
template: `
<div>
<button>后退</button>
{{ title }}
<button @click="handleClick">前进</button>
</div>`,
data() {
return {
title: '好看的首页',
t:''
}
},
methods: {
handleClick() {
// alert('前进')
this.title = 'lqz' }
},
beforeCreate() {
console.log('beforeCreate')
console.log(this.$data)
console.log(this.$el)
},
created() {
console.log('created')
console.log(this.$data)
console.log(this.$el)
// 开启定时器,每隔3s,打印hello
this.t=setInterval(()=>{
console.log('hello')
},3000)
},
beforeMount() {
console.log('beforeMount')
console.log(this.$data)
console.log(this.$el)
},
mounted() {
console.log('mounted')
console.log(this.$data)
console.log(this.$el)
},
beforeUpdate() {
console.log('beforeUpdate')
},
updated() {
console.log('updated')
},
beforeDestroy() {
console.log('当前状态:beforeDestroy')
},
destroyed() {
console.log('当前状态:destroyed')
// 销毁定时器
clearInterval(this.t)
this.t=null },
}) var vm = new Vue({
el: '#app',
data: {
show: true
},
methods: {
handleShow() {
this.show = !this.show
}
} })
</script>
</html>

定时任务和延时任务的使用场景

# 小案例:组件创建,开启定时器,不停的打印hello,在destroyed中对定时器进行销毁

	-补充:js 定时任务和延时任务
# 延时任务
setTimeout(()=>{
console.log('3s后执行我')
},3000)
# 定时任务
setInterval(()=>{
console.log('hello')
},3000) # 什么场景下用定时任务?
1 实时跟后端交互 基于http+定时任务 (有缺陷)
- 一直通过定时任务发送请求,十分消耗资源
- 因为上述方案有缺陷所以产生了:websocket协议 ---> 服务端主动推送消息:手机app的消息推送
2 秒杀场景:先提交秒杀请求,每隔3s,查询是否秒到

setTimeout延时任务:3s之后执行

setInterval定时任务:每隔3s执行一次

在线聊天室案例

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

什么场景下用定时任务?

扫二维码登录微信时。比如初次扫码的时候,会有一个请求是pending状态:

浏览器在等待你确认登录时,会一直向服务端发送请求:

使用手机扫二维码之后,手机会向微信的服务器发送登录相关的请求,但是浏览器不知道你发送了这个请求,所以浏览器需要一刻不停的向后端发送请求(轮询),以验证当前用户是否扫码。如果发现用户扫了码,浏览器这个定时任务的请求,就会把用户头像数据带回来,显示在页面上。

也就是说,数据不是服务器主动发送给客户端的,而是客户端一直发送定时任务,主动去拿的。(类似于拿快递,服务器是寄存点)(这都是因为http协议的特性:无状态、无连接)

比如: A ---> B A向B发送消息

实际上是: A --发送信息--> 服务器

B --查询信息--> 服务器

示例:

页面一直发送定时任务,查询是否有新增的消息。如果有新增的消息,将消息带回来,进行页面更新。

秒杀案例

什么场景下使用延时任务?

先提交秒杀请求,每隔3s,查询是否秒到。

首先,在组件中开启一个定时器(存放在data()):

全局组件:

组件销毁了之后,定时器还是在运行,这显然不合适,所以需要在组件的destroyed() 钩子函数中将定时器销毁:

与后端交互

使用jquery的ajax与后端交互

需求:点击按钮,数据加载,页面更新。

Vue:

点击事件函数:

使用jquery封装的ajax方法。

创建flask服务端:

只要有请求访问根路径,就会返回数据。

跨域问题

# 跨越问题
-浏览器的原因,只要向不是地址栏中的 [域:地址和端口]发送请求,拿的数据,浏览器就给拦截了 # 处理跨域问题
-后端代码处理----》只需要在响应头中加入允许即可

前端点击按钮,会向后端发送请求,获取数据,但是发送了跨域请求报错:

解决跨域问题需要修改后端代码,需要在响应头里加一句话:

示例:

前端渲染数据:

注意从后端获取到的数据是json字符串,需要通过JSON.parse转换成对象。

fetch和axios发送请求

jquery不仅封装了ajax,还有很多的dom操作,而axio只能发请求。

axio使用promsie风格,promsie风格是es6的新语法。

promsie风格是为了解决如下嵌套发送请求的情况,优化代码:

fetch

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

fetch是js原生的,所以可以直接使用:

第一个then会返回一个数据,传给第二个then

查看前端:

渲染数据:

axios

#  axios是在Vue上的第三方的模块
# Axios 是一个基于 promise 的 HTTP 库,还是基于XMLHttpRequest封装的

官网:起步 | Axios 中文文档 | Axios 中文网 (axios-http.cn)

使用cdn引入axios:

只要引入了,就可以在Vue组件里使用!

示例:

查看前端:

后端返回的数据在res.data中。

修改数据:

代码:


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
</head>
<body>
<div id="app"> <h1>jquery的ajax与后端交互</h1>
<!-- <button @click="handleLoad1">点击加载数据</button>-->
<!-- <br>-->
<!-- <p>名字是:{{name}}</p>-->
<!-- <p>年龄是:{{age}}</p>-->
<!-- <hr>--> <h1>js原生的fetch与后端交互</h1>
<!-- <button @click="handleLoad2">点击加载数据</button>-->
<!-- <br>-->
<!-- <p>名字是:{{name}}</p>-->
<!-- <p>年龄是:{{age}}</p>-->
<!-- <hr>--> <h1>axios与后端交互</h1>
<button @click="handleLoad3">点击加载数据</button>
<br>
<p>名字是:{{name}}</p>
<p>年龄是:{{age}}</p>
<hr>
</div> </body> <script> var vm = new Vue({
el: '#app',
data: {
name: '',
age: 0
},
methods: {
handleLoad1() {
$.ajax({
url: "http://127.0.0.1:5000/",
type: 'get',
success: data => {
console.log(typeof data)
data = JSON.parse(data) // data 是字符串类型,需要转成对象类型
console.log(typeof data)
this.name = data.name
this.age = data.age }
})
},
handleLoad2() { // 用的很少
fetch('http://127.0.0.1:5000/').then(res => res.json()).then(res => {
console.log(res)
console.log(typeof res)
this.name = res.name
this.age = res.age
}) }, handleLoad3() { // 用的很少
axios.get('http://127.0.0.1:5000/').then(res => {
console.log(res.data) // 后端真正的数据在res.data中
this.name = res.data.name
this.age = res.data.age
}) },
} })
</script>
</html>

显示电影案例

需求:后端加载电影相关数据,前端显示。

数据获取:

把数据放置在本地文件。

后端代码:

在前端created方法内,向后端获取数据:

循环展示电影:json.cn

如果后端返回的数据格式嵌套的层级比较多,前端需要一层一层的点出来:

前端还需要判断一下状态码是否为100,然后再将后端获取到的数据进行赋值。

有的公司觉得后端使用json格式返回不安全,比如接口返回出了患者的身份证号。需要对数据进行加密。后端在中间件中解密获取数据,再加密返回给前端。但是这种加密十分影响接口的效率,通常只对重要的接口使用。

示例:

进行了数据的加密:

代码:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="app"> <h1>电影小案例</h1>
<ul>
<li v-for="film in filmList">
<h2>电影名:{{film.name}}</h2>
<img :src="film.poster" alt="" height="400px" width="300px">
</li>
</ul> </div> </body> <script> var vm = new Vue({
el: '#app',
data: {
filmList: []
},
created() {
axios.get('http://127.0.0.1:5000/films').then(res => {
this.filmList = res.data.data.films
})
} })
</script>
</html>

Vue组件

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

示例:

组件化之后可复用代码:

组件的分类:全局组件和局部组件。

全局组件在任意组件中都可以使用。

在组件中也可以使用全局组件:

局部组件只能在当前组件中使用。

定义局部组件:

使用components定义局部组件。

局部组件只能在Vue对象监控的代码内使用:

可以将组件的代码放在变量里:

这样在html上使用标签<foo>就可以加载局部组件。

工程化开发之后一个组件就是一个xx.Vue文件。

<!DOCTYPE html>
<html lang="en">
<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> <child></child> <foo></foo>
<!-- <lqz></lqz>--> </div>
</body>
<script>
// 全局组件-----》在任意组件中都可以使用
// 跟之前学的没有区别
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
}
}
}, } })
Vue.component('child3', {
template: `
<div>
<button>后退</button>
</div>`, }) var foo={
template: `
<div>
<h1>局部组件---{{ age }}</h1>
</div>`,
data() {
return {
age: 19
}
}
}
var vm = new Vue({
el: '.app',
data: {
show: false
},
methods: {
handleShow() {
this.show = !this.show
}
},
components: {
foo } })
</script>
</html>

补充

'''可变类型和不可变类型'''
# python
-不可变类型:数字,字符串,元组
-可变类型:列表,字典,集合
-python中没有值类型和引用类型的叫法----【因为python一切皆对象,对象都是地址都是引用】
-可变类型当参数传到函数中,在函数中修改会影响原来的
-不可变类型当参数传到函数中,在函数中修改不会影响原来的 # python 函数参数传递是值传递还是引用传递? 这个问题不应该有 # js 传入了item 对象,在函数中修改,影响了原来的
-js 的对象是引用类型 '''json格式安全性问题'''
# 之前前后端交互,使用xml格式
# 后来json 格式出现,前后端交互,主流都是json格式
-可能觉得不安全
-前后端加密解密方式 # 目前有些比json更安全,高效,节约空间的编码格式,后期可能前后端交互使用某种

练习

# 购物车带删除,有库存校验 ok
# 小电影案例---》后端用django,解决跨域问题
# 整理一下vue生命周期 ok
---------------------------------
# 对象当参数传递,在函数中修改对象,会不会影响原来的 会 ok
# 深浅拷贝 ok
# 搜索什么是跨域

深浅拷贝

(43条消息) javascript 数组以及对象的深拷贝(复制数组或复制对象)的方法_FungLeo的博客-CSDN博客

(43条消息) JavaScript深拷贝看这篇就行了!(实现完美的ES6+版本)_码飞_CC的博客-CSDN博客_js深拷贝

跨域问题

[跨域问题及CORS解决跨域问题方法 - 腾讯云开发者社区-腾讯云 (tencent.com)]

购物车

有问题:选择1,2,4删除3,价格会错乱。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
<link rel="stylesheet" href="./js/bootstrap.css">
<script src="js/layui/layui.js"></script>
</head>
<body>
<div id="app">
<div class="container-fluid">
<div class="row top">
<div class="col-md-6 col-md-offset-3">
<h2 class="text-center">购物车</h2>
<table class="table table-bordered">
<thead>
<tr>
<th>商品</th>
<th>价格</th>
<th>数量</th>
<th>全选
<input v-model="checkAll" type="checkbox" @change="handleCheckAll">
</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(good,index) in shopCar">
<td>{{good.name}}</td>
<td>{{good.price}}</td>
<td>
<button class=" btn-default" @click="addGood(good)"></button>
<button>{{ good.count }}</button>
<button class="btn-default" @click="delGood(good)"></button>
</td>
<td :id="good.id">
<input class="btn btn-default" type="checkbox" v-model="goodList" :value="good"
@change="handleCheckOne">
<!-- 不能使用点击事件,因为点击事件快于v-model的双向数据绑定 -->
</td>
<td>
<button class="btn btn-danger" @click="delShopCar(good,index)">删除</button>
</td>
</tr>
</tbody>
</table>
<h4>总价格:{{ getPrice() }}</h4>
<h4>购物车:{{ goodList }}</h4> </div>
</div>
</div> </div>
<script>
var vm = new Vue({
el: '#app',
data: {
shopCar: [
{id: 1, name: '曹操戏张飞', price: 10, count: 1, store: 5},
{id: 2, name: '仿真玩偶', price: 100, count: 1, store: 5},
{id: 3, name: '印度飞饼', price: 1000, count: 1, store: 5},
{id: 4, name: '仿真玩偶plus', price: 10000, count: 1, store: 5},
],
goodList: [],
checkAll: false,
}, methods: {
getPrice() {
var total = 0
for (item of this.goodList) {
total += item.price * item.count
}
return total
},
handleCheckAll() {
if (this.checkAll) {
this.goodList = this.shopCar.slice(0) // 深浅拷贝 slice(0)返回一个新列表并且在内存中新产生了一份数据 不再引用原来内存中的数据
} else {
this.goodList = []
}
},
handleCheckOne() {
this.checkAll = this.goodList.length === this.shopCar.length;
},
addGood(good) {
if (good.count < good.store) {
good.count++
} else {
layer.msg('超过库存上限')
}
},
delGood(good) {
if (good.count > 1) {
good.count--
} else {
layer.msg('商品数最小为1')
}
},
delShopCar(item, index) { // {id: 1, name: '曹操戏张飞', price: 10, count: 1, store: 5}, if (this.goodList.length === 0) {
this.shopCar.splice(index, 1)
} else {
this.goodList.forEach((good, ix) => {
if (good.id === item.id) {
this.goodList.splice(ix, 1)
}
})
this.shopCar.splice(index, 1) }
},
}, })
</script>
</body>
</html>

显示电影页面

后端:

# view.py
import json
import os from django.conf import settings
from rest_framework.viewsets import ViewSet
from rest_framework.response import Response
static_path = os.path.join(settings.BASE_DIR, 'static') class MovieView(ViewSet):
def list(self, request, *args, **kwargs):
with open(f'{static_path}/movie.json', 'r', encoding='utf-8') as f:
data = json.load(f)
return Response({'data': data}, headers={'Access-Control-Allow-Origin': '*'}) # urls.py
from django.contrib import admin
from django.urls import path
from rest_framework.routers import SimpleRouter
from app01 import views router = SimpleRouter()
router.register('movie', views.MovieView, 'movie') urlpatterns = [
path('admin/', admin.site.urls),
]
urlpatterns += router.urls

前端:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
<script src="./js/axios.js"></script>
<link rel="stylesheet" href="./js/bootstrap.css">
</head>
<body>
<div id="app">
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="panel panel-default" v-for="item in filmList">
<div class="panel-body">
<a href="">
<h4 class="media-heading">{{item.name}}</h4>
</a>
<div class="media">
<div class="media-left">
<a href="#">
<img style="width: 100px;" class="media-object" :src="item.poster" alt="...">
</a>
</div>
<div class="media-body">
{{ item.synopsis }}
</div>
</div>
</div>
</div> </div>
</div>
</div> </div>
</body> <script>
// // 根组件
let vm = new Vue({
el: '#app',
data: {
data: '',
filmList: []
},
created() {
axios.get('http://127.0.0.1:8000/movie/').then(res => {
this.filmList = res.data.data.data.films
}) },
}) </script>
</html>

【Vue】表单数据双向绑定 vue生命周期 fetch和axios发送请求 Vue全局组件的更多相关文章

  1. vue.js的一些事件绑定和表单数据双向绑定

    知识点: v-on:相当于: 例如:v-on:click==@click ,menthods事件绑定 v-on修饰符可以指定键盘事件 v-model进行表单数据的双向绑定 <template&g ...

  2. Vue声明式渲染、条件与循环、事件绑定、双向绑定及生命周期钩子函数

    VUE基础介绍 Vue 是一套用于构建用户界面的渐进式框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用. -声明式渲染 <div> {{ message }} </ ...

  3. VUE 表单元素双向绑定总结

    checkbox最基本用法: <input type="checkbox" v-model="inputdata" checked/> <in ...

  4. 你还不知道Vue的生命周期吗?带你从Vue源码了解Vue2.x的生命周期(初始化阶段)

    作者:小土豆biubiubiu 博客园:https://www.cnblogs.com/HouJiao/ 掘金:https://juejin.im/user/58c61b4361ff4b005d9e8 ...

  5. Vue表单控件绑定

    前面的话 本文将详细介绍Vue表单控件绑定 基础用法 可以用 v-model 指令在表单控件元素上创建双向数据绑定.它会根据控件类型自动选取正确的方法来更新元素.v-model本质上不过是语法糖,它负 ...

  6. vue 表单输入与绑定 v-model

    vue使用 v-model 指令在表单 <input>.<textarea> 及 <select> 元素上创建双向数据绑定.下面我们通过示例先了解下基本用法: &l ...

  7. vue中的数据双向绑定

    学习的过程是漫长的,只有坚持不懈才能到达到自己的目标. 1.vue中数据的双向绑定采用的时候,数据劫持的模式.其实主要是用了Es5中的Object.defineProperty;来劫持每个属性的get ...

  8. day68:Vue:类值操作/style样式操作&v-for&filer/computed/watch&生命周期钩子函数&axios

    目录 1.类值操作 :class 2.style操作样式 :style 3:示例:选项卡 @click+:class 4.v-for示例:循环商品显示 5.过滤器:filter 6.计算属性:comp ...

  9. Angular11 模板表单、响应式表单(自定义验证器)、HTTP、表单元素双向绑定

    1 模板表单 模型通过指令隐式创建 技巧01:需要在模块级别引入 FormsModule ,通常在共享模块中引入再导出,然后在需要用到 FormsModule 的模块中导入共享模块就可以啦 impor ...

  10. Vue环境搭建-项目的创建-启动生命周期-组件的封装及应用

    vue项目环境的搭建 """ node >>> python:node是用c++编写用来运行js代码的 npm(cnpm) >>> p ...

随机推荐

  1. 使用GPT4进行数据分析,竟然被他骗了

    上周,OpenAI开发者大会上OpenAI发布了一系列震撼人心的功能.而最让我感兴趣的,就是GPT4的数据分析功能了.话不多说,赶紧上号体验一下. 在最新登录GPT4的时候,都会有下面这个提示,目前已 ...

  2. 从DPlayer说起,有哪些开源的H5播放器

    引言 ​ H5指的是HTML5,也就是介绍网页播放器(只是列出而已).首先我不是什么大佬,并没有完全体验过以下我会介绍的全部播放器:其次,因为我水平比较低,主要介绍拥有中文文档的播放器,不了解开发的朋 ...

  3. 2022 暑期 DP 极限单兵计划

    前言 LJ 认为我的 DP 是我的一大弱项,便精心为我准备了 毒瘤DP 12 题(然后发现原来给的 T1 是个树套树,就变成 毒瘤DP 11 题 感谢 LJ 教练..... 为了方便复习,代码均格式化 ...

  4. jvm的jshell,学生的工具

    jshell  在我眼里,只能作为学校教学的一个玩具,事实上官方也做了解释,以下是官方的解释: 在学习编程语言时,即时反馈很重要,并且 它的 API.学校引用远离Java的首要原因 教学语言是其他语言 ...

  5. docker制作compose

    第一步,先了解Compose是什么? Compose 项目是 Docker 官方的开源项目,负责实现对 Docker 容器集群的快速编排. Compose有两个重要的概念 1.项目 :由一组关联的应用 ...

  6. Tensorflow2.0实战之GAN

    本文主要带领读者了解生成对抗神经网络(GAN),并使用提供的face数据集训练网络 GAN 入门 自 2014 年 Ian Goodfellow 的<生成对抗网络(Generative Adve ...

  7. 从零开始封装 vue 组件

    对于学习 Vue 的同学来说,封装 vue 组件是实现代码复用的重要一环.在 Vue 官网中非常详细地介绍了 vue 组件的相关知识,我这里简单摘取使用最频繁的几个知识点,带大家快速入门 vue 组件 ...

  8. Springboot快速集成阿里云RocketMq

    前言 随着互联网的兴起,越来越多的用户开始享受科技带来的便利,对于服务的压力也日益增大,随即便有了高并发.高性能.高可用等各种解决方案,这里主要介绍RocketMq的集成方法.(文末附源码地址) 正文 ...

  9. OpenSSL命令总结

    OpenSSL命令总结 疑今者察之古,不知来者视之往. 导航 介绍 对称加密 公钥加密 信息摘要 数字证书 杂项 介绍 密码学标准和互联网协议一样,是一种大家都遵守的约定和标准,比如PKCS#1中规定 ...

  10. 案例分享-Exception.getMessage突然为null

    背景 之前做的小工具一个jsqlparse+git做的小工具帮我节省时间摸鱼昨天突然停止工作,看了下jvm并没有退出,但是看日志确实有不少Error输出,虽说是一个普通的NPE,但是分析了一下却疑点重 ...