与后端交互的三种方式
// 后端接口写好了,前后端分离的项目,前端如何与后端进行交互?
前后端要打通----->从前端发送Ajax请求------>核心:使用JavaScript发送HTTP请求,接受返回的数据
-使用原生JS,可以开启Ajax,但是使用原生JS,比较麻烦,需要做浏览器兼容,现在基本不使用
-jQuery,写了个兼容所有的浏览器,$.ajax(),但是它里面不仅仅有Ajax还有一些dom操作,如果在Vue中使用不太合适
-axios:第三方的Ajax包,可以使用
-fetch:原生JS发送Ajax强求,有的浏览器也不兼容
后端
class UserInfo(ViewSetMixin, APIView):
@action(methods=["GET"], detail=False)
def user(self, request):
response = Response({"username": "彭于晏", "age": "19"})
response.headers = {"Access-Control-Allow-Origin": "*"}
return response
使用jQuery的Ajax
<script>
new Vue({
el: "#app1",
data: {
username: "",
age: "",
},
methods: {
handeruserinfo() {
let _this = this
$.ajax({
url: "//127.0.0.1:8000/user/",
method: "get",
success: function (args) {
console.log(typeof args)
console.log(args)
_this.username = args.username
_this.age = args.age
}
})
}
},
})
</script>
使用fetch
handleLoad() {
// 2 使用js原生的fetch(目前也不用)
// fetch('http://127.0.0.1:5000').then(function (response) {
// // console.log(response)
// return response.json();
// }).then(function (res) {
// console.log(res);
// });
// 了解,箭头函数一会讲
fetch('http://127.0.0.1:5000').then(res=>res.json()).then(res=>{
console.log(res)
})
使用axios
// cdn 导入axios:<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
new Vue({
el: "#app1",
data: {
username: "",
age: "",
},
methods: {
handeruserinfo() {
let _this = this
axios.get("http://127.0.0.1:8000/user/").then(function (args) {
console.log(args)
_this.username = args.data.username
_this.age = args.data.age
})
}
},
})
</script>
计算属性
// 计算属性是基于他们所依赖的变量进行缓存的
// 计算属性只有在他们的相关依赖变量发生改变时才会重新求值,否则不会变,(函数是只要页面发生变化,就会重新运算)
// 计算属性就像python中的property一样, 将方法伪装成属性
// 计算属性必须要有返回值
计算属性要写在----->computed中
基础使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="src/JS/Vue.js"></script>
<script src="src/JS/jQuery.js"></script>
<script src="src/bootstrap/js/bootstrap.min.js"></script>
<script src="src/JS/axios.js"></script>
<link rel="stylesheet" href="src/bootstrap/css/bootstrap.min.css">
<script type="module" src="/src/main.js"></script>
<title></title>
</head>
<body>
<div id="app1">
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="text-center">
<h1>计算属性的基本使用</h1>
<p><input type="text" v-model="username">------>{{ cat_username() }}</p>
<!-- 当我使用插值语法进行插值的时候,我在password框中输入值的时候也会触发username这个函数的执行-->
<input type="text" v-model="password">------>{{ password }}
<h2>通过计算属性实现---->当属性使用</h2>
<input type="text" v-model="username1">----------》{{ get_username }}
</div>
</div>
</div>
</div>
</div>
</body>
<script>
new Vue({
el: "#app1",
data: {
username: "",
password: "",
username1: "",
},
methods: {
cat_username() {
console.log("我是username的函数我执行了")
return this.username.substring(0, 1).toUpperCase() + this.username.substring(1)
}
},
computed: {
get_username() {
console.log("我是计算属性,我执行了")
return this.username1.substring(0, 1).toUpperCase() + this.username1.substring(1)
}
}
})
</script>
</html>
重写过滤案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="src/JS/Vue.js"></script>
<script src="src/JS/jQuery.js"></script>
<script src="src/bootstrap/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="src/bootstrap/css/bootstrap.min.css">
<script type="module" src="/src/main.js"></script>
<title></title>
</head>
<body>
<div id="app1">
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="text-center">
<h1>过滤案例</h1>
<input type="text" v-model="myText">
<hr>
<ul>
<li v-for="item in handleInput">{{ item}}</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</body>
<script>
let vm = new Vue({
el: "#app1",
data: {
myText: "",
dataList: ['a', 'at', 'atom', 'be', 'beyond', 'cs', 'csrf', 'e', 'egg', 'agg'],
},
methods: {
},
computed: {
handleInput(){
return this.dataList.filter((item => item.indexOf(this.myText) >= 0))
}
}
})
</script>
</html>
监听(侦听)属性
// 只要属性发生了变化,就会执行某个函数
这个函数要写在watch中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="src/JS/Vue.js"></script>
<script src="src/JS/jQuery.js"></script>
<script src="src/bootstrap/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="src/bootstrap/css/bootstrap.min.css">
<script type="module" src="/src/main.js"></script>
<title></title>
</head>
<body>
<div id="app1">
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="text-center">
<h1>监听</h1>
<input type="text" v-model="username">-------{{ username }}
</div>
</div>
</div>
</div>
</div>
</body>
<script>
new Vue({
el: "#app1",
data: {
username: ""
},
methods: {},
watch: {
username(newValue, oldValue) {
// 修改过后的值
console.log(newValue)
// 修改前的值
console.log(oldValue)
// 只要我的属性发生了变化,就会触发我这个函数的执行
console.log("我执行了")
}
}
})
</script>
</html>
Vue的生命周期
new Vue() ----->创建出来----->页面关闭----->被销毁掉----->整个过程经历了一个周期----->Vue提供了钩子函数[写了就会执行,不写就不执行],到了某个阶段,就会触发某个函数的执行
8个生命周期钩子函数:
beforeCreate 创建Vue实例之前调用
created 创建Vue实例成功后调用
beforeMount 渲染DOM之前调用
mounted 渲染DOM之后调用
beforeUpdate 重新渲染之前调用(数据更新等操作时,控制DOM重新渲染)
updated 重新渲染完成之后调用
beforeDestroy 销毁之前调用
destroyed 销毁之后调用
8个生命周期钩子,什么情况下会用得到?
created:用的最多,变量初始化完成了(data中的数据),在这里,我们可以发送Ajax请求
beforDestroy:组件销毁之前会执行
-组件创建,就会执行一个定时任务,[每隔15秒,打印一个HelloKitty]
-组件销毁,定时任务被销毁,如果定时任务不被销毁就会一直执行
// 每一个钩子函数都是一个独立的函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="src/JS/Vue.js"></script>
<script src="src/JS/jQuery.js"></script>
<script src="src/bootstrap/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="src/bootstrap/css/bootstrap.min.css">
<script type="module" src="/src/main.js"></script>
<title></title>
</head>
<body>
<div id="app1">
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="text-center">
<h1>Vue的生命周期</h1>
// 当我input框的内容发生改变时就会触发updated的钩子函数
<input type="text" v-model="username">---------{{ username }}
</div>
</div>
</div>
</div>
</div>
</body>
<script>
new Vue({
el: "#app1",
data: {
username: ""
},
methods: {},
beforeCreate() {
console.log('beforeCreate')
console.log('当前el状态:', this.$el)
console.log('当前data状态:', this.$data)
console.log('当前name状态:', this.name)
},
created() {
console.log('created')
console.log('当前el状态:', this.$el)
console.log('当前data状态:', this.$data)
console.log('当前name状态:', this.name)
// 启动一个定时器
this.t = setInterval(() => {
console.log('hello world')
}, 1000)
},
beforeMount() {
console.log('beforeMount')
console.log('当前el状态:', this.$el)
console.log('当前data状态:', this.$data)
console.log('当前name状态:', this.name)
},
mounted() {
console.log('mounted')
console.log('当前el状态:', this.$el)
console.log('当前data状态:', this.$data)
console.log('当前name状态:', this.name)
},
beforeUpdate() {
console.log('beforeUpdate')
console.log('当前el状态:', this.$el)
console.log('当前data状态:', this.$data)
console.log('当前name状态:', this.name)
},
updated() {
console.log('updated')
console.log('当前el状态:', this.$el)
console.log('当前data状态:', this.$data)
console.log('当前name状态:', this.name)
},
beforeDestroy() {
console.log('beforeDestroy')
console.log('当前el状态:', this.$el)
console.log('当前data状态:', this.$data)
console.log('当前name状态:', this.name)
// 销毁定时器
clearInterval(this.t)
this.t = null
},
destroyed() {
console.log('destroyed')
console.log('当前el状态:', this.$el)
console.log('当前data状态:', this.$data)
console.log('当前name状态:', this.name)
},
})
</script>
</html>
组件介绍和使用
// 组件就是 :扩展HTML元素,封装可重复使用的代码,目的是复用
例如:
有一个轮播图,可以在很多页面中使用,一个轮播有js,css,html,组件把js,css,html放到一起,有逻辑,有样式,有html
// 组件的分类:
全局组件:可以放在根中,可以在所有组件中使用
局部组件:只能在当前组件中使用
定义一个全局组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="src/JS/Vue.js"></script>
<script src="src/JS/jQuery.js"></script>
<script src="src/bootstrap/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="src/bootstrap/css/bootstrap.min.css">
<script type="module" src="/src/main.js"></script>
<title></title>
</head>
<body>
<div id="app1">
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="text-center">
<h1>组件的使用</h1>
</div>
</div>
</div>
</div>
<child></child>
</div>
</body>
<script>
Vue.component("child", {
template:
`
<div>
<p><img src="img/测试图4.jpg" alt="" height="400px" width="400px"></p>
<button @click="come">前进</button>
{{ title }}
<button @click="go">后退</button>
</div>
`,
data() {
return {
title: "我是首页"
}
},
methods: {
come() {
alert("我前进了")
},
go() {
alert("我后退了")
}
}
})
new Vue({
el: "#app1",
data: {
username: ""
},
methods: {},
});
</script>
</html>
定义局部组件
// 要在Vue实例中的components里面定义组件,就是局部组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="src/JS/Vue.js"></script>
<script src="src/JS/jQuery.js"></script>
<script src="src/bootstrap/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="src/bootstrap/css/bootstrap.min.css">
<script type="module" src="/src/main.js"></script>
<title></title>
</head>
<body>
<div id="app1">
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="text-center">
<h1>组件的使用</h1>
</div>
</div>
</div>
</div>
<child></child>
</div>
</body>
<script>
let child = {
template:
`
<div>
<p><img :src="url" alt="" height="700px" width="700px"></p>
<button @click="come">前进</button>
{{ title }}
<button @click="go">后退</button>
</div>
`,
data() {
return {
title: "我是首页",
url: "img/测试图2.jpg"
}
},
methods: {
come() {
alert("我前进了")
},
go() {
alert("我后退了")
}
}
}
new Vue({
el: "#app1",
data: {
username: ""
},
methods: {},
// 局部组件是定义在某个组件内,可以定义多个,只能在它父组件中使用,不能到别的地方使
components: {
child
}
});
</script>
</html>
// 全局组件是使用Vue.component定义的,可以在全局任意组件中使用
// 局部组件是定义在某个组件内:components,只能用在当前组件中
// 组件可以嵌套定义和使用
// 扩展:elementui,提供给咱们很多全局组件
组件之间的通信
// 组件嵌套
-父组件把数据传递给子组件
-自定义属性
-1、在子组件中自定义属性,使用属性指令绑定父组件的变量、
-2、在子组件中,使用props接收["属性名","属性名2"]
-3、在子组件中,使用属性名即可
-子组件把数据传递给父组件
-自定义事件
-1、父组件中自定义一个事件:<xxx @myevent="handelEvent"></xxx>
-2、子组件只要执行 this.$emit('xxx'),就会触发自定义事件对应的函数
组件间通信父传子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="src/JS/Vue.js"></script>
<script src="src/JS/jQuery.js"></script>
<script src="src/bootstrap/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="src/bootstrap/css/bootstrap.min.css">
<script type="module" src="/src/main.js"></script>
<title></title>
</head>
<body>
<div id="app1">
<h1>组件的使用</h1>
<hr>
<child :url="url"></child>
<hr>
</div>
</body>
<script>
let child = {
template:
`
<div>
<h2>这是局部组件</h2>
<p><img :src="url" alt="" height="700px" width="700px"></p>
<button @click="go">后退</button>
</div>
`,
data() {
return {}
},
methods: {
go() {
alert("我后退了")
}
},
props:["url"]
}
new Vue({
el: "#app1",
data: {
url: "img/测试图2.jpg"
},
methods: {},
components: {
child
}
});
</script>
</html>
总结
我在根组件中的数据如何被我的子组件拿到?
1、先在我子组件的标签中自定义一个属性,然后再在我子组件中使用我这个自定义的属性,再在我子组件中使用props以数组的形式接收
组件间通信值子传父
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="src/JS/Vue.js"></script>
<script src="src/JS/jQuery.js"></script>
<script src="src/bootstrap/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="src/bootstrap/css/bootstrap.min.css">
<script type="module" src="/src/main.js"></script>
<title></title>
</head>
<body>
<div id="app1">
<h1>组件的使用</h1>
接收到的子组件输入的内容是:{{ username}}
<hr>
<child @myclick="xxx"></child>
<hr>
</div>
</body>
<script>
let child = {
template:
`
<div>
<h2>这是局部组件</h2>
<input type="text" v-model="username">
<button @click="handersend">传递到父组件</button>
</div>
`,
data() {
return {
username: ""
}
},
methods: {
handersend() {
console.log("jjjjjjjj")
this.$emit('myclick', this.username)
}
},
}
new Vue({
el: "#app1",
data: {
username: ""
},
methods: {
xxx(username) {
console.log("执行到了父组件")
console.log(username)
this.username = username
}
},
components: {
child
}
});
</script>
</html>
总结
1、需要在我子组件产生的标签中自定义一个事件:<child @myclick="xxx"></child>
2、在我子组件中绑定一个事件,当我子组件触发了事件,就会执行绑定方法里面的:this.$emit('myclick', this.username),一个是我自定义事件的名称,一个是我要传给父组件的数据
3、我在父组件中需要调用我自定义绑定事件的方法,接收一个参数,这个参数就是我子组件传给我父组件的参数:
xxx(username) {
console.log("执行到了父组件")
console.log(username)
this.username = username
}
ref属性
ref属性,vue提供的,写在标签上
可以写在普通标签:在vue中使用 this.$refs.名字 拿到dom对象,可以原生操作
可以写在组件上:在vue中使用 this.$refs.名字 拿到[组件]对象,组件属性,方法直接使用即可
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="src/JS/Vue.js"></script>
<script src="src/JS/jQuery.js"></script>
<script src="src/bootstrap/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="src/bootstrap/css/bootstrap.min.css">
<script type="module" src="/src/main.js"></script>
<title></title>
</head>
<body>
<div id="app">
<h1>ref属性放在普通标签上</h1>
<input type="text" v-model="username" ref="myinput">
// 当我普通标签中有了ref这个特殊属性以后,就有不用再在data中放入我变量的值,也可以渲染出来饿了
<br>
<img src="img/测试图3.jpg" alt="" height="300px" ref="myimg">
<h1>ref放在组件上</h1>
<hr>
<lqz ref="mylqz"></lqz>
<hr>
<button @click="handleClick">点我执行函数</button>
<br>
{{ username }}
</div>
</body>
<script>
let vm = new Vue({
el: '#app',
data: {
username: ''
},
methods: {
handleClick() {
console.log(this.$refs)
// 通过key,取到标签,拿到原生dom,通过dom操作,控制标签
// this.$refs.myinput.value = 'lqz'
// this.$refs.myimg.src='https://img2.woyaogexing.com/2021/09/22/3c686eb61fe34696840c478584b73d36!400x400.jpeg'
// 放在组件上---》现在在父组件中,能拿到子组件对象,对象中的属性和方法直接用即可
console.log(this.$refs.mylqz)
// this.$refs.mylqz.title = 'sb'
// this.username=this.$refs.mylqz.title
this.$refs.mylqz.handleBack()
}
},
components: {
lqz: {
template: `
<div>
<button @click="handleBack">后退</button>
{{ title }}
<button>前进</button>
</div>`,
data() {
return {
title: "首页"
}
},
methods: {
handleBack() {
alert('后退了')
}
}
}
}
})
</script>
</html>
作业
1 上课讲的代码写一遍
-购物车使用计算属性,过滤案例使用计算属性
2 写一个books接口,带按价格排序,前端页面创建完成,向后端发送请求,获取图书属性,表格显示在前端
前端使用监听属性实现点击价格正序和倒序排列
3 定义组件,组件创建成功,向后端发送请求,后端返回一张图片地址,显示在组件上
-1 网络图片
-2 media下的图片
4 在上面的子组件就中写一个按钮,点击按钮,把子组件的图片地址,传递到父组件中打印出来(alert