计算属性
1.计算属性是基于它们的依赖变量进行缓存的
2.计算属性只有在它的相关依赖变量发生改变时才会重新求值,否则不会变(函数只要页面变化,就会重新运算)
3.计算属性就像Python中的property,可以把方法/函数伪装成属性
4.计算属性函数,必须有返回值
作用:延缓计算:跟它相关联的变量发生变化,它才会重新运算
方法烦属性用,可以被for循环,if判断
基本使用
效果:实现输入input中后名字首字母大写
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src='./js/vue.js'></script>
</head>
<body>
<div id='app'>
<p> 用户名:<input type="text" v-model="username">---->{{ username.substring(0, 1).toUpperCase() + username.substring(1) }}</p>
<p>用户名1:<input type="text" v-model="username1">---->{{ First_Upper() }}</p>
<p>通过计算属性实现--->当属性用</p>
<p>用户名2:<input type="text" v-model="username2">---->{{ getName}}</p>
</div>
</body>
<script>
var vue = new Vue({
el: '#app',
data: {
username: '',
username1: '',
username2: '',
},
methods: {
First_Upper() {
console.log('函数执行了')
return this.username1.substring(0, 1).toUpperCase() + this.username1.substring(1)
}
},
computed:{
getName(){
console.log('计算属性执行了')
return this.username2.substring(0, 1).toUpperCase() + this.username2.substring(1)
}
}
})
</script>
</html>
重写过滤案列
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model="search" @input="handleInput">
<hr>
<ul>
<li v-for="item in newdataList">{{item}}</li>
</ul>
</div>
</body>
<script>
let vm = new Vue({
el: '#app',
data: {
search: '',
dataList: ['a', 'at', 'atom', 'attoo', 'be', 'beyond', 'cs', 'csrf'],
newdataList: ['a', 'at', 'atom', 'attoo', 'be', 'beyond', 'cs', 'csrf'],
},
methods: {
handleInput() {
this.newdataList = this.dataList.filter(item => item.indexOf(this.search) >= 0)
}
}
})
</script>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model="search" >
<hr>
<ul>
<li v-for="item in newdataList">{{item}}</li>
</ul>
</div>
</body>
<script>
let vm = new Vue({
el: '#app',
data: {
search: '',
dataList: ['a', 'at', 'atom', 'attoo', 'be', 'beyond', 'cs', 'csrf'],
},
computed:{
newdataList(){
return this.dataList.filter(item => item.indexOf(this.search) >= 0)
}
}
})
</script>
</html>
监听(侦听)属性
属性如果发生变化,就会执行某个函数(当watch的变亮发生变化,就会触发函数的执行)
<!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>
<input type="text" v-model="username"> -->{{username}}
</div>
</body>
<script>
var vm = new Vue({
el:'#app',
data:{
username:''
},
watch:{
username(newValue,oldValue){
console.log('新值',newValue)
console.log('旧值',oldValue)
console.log('我发生了变化')
}
}
})
</script>
</html>
Vue生命周期
1.new Vue()---->创建出来--->页面关闭--->被销毁掉---->整个整个过程经历了一个周期---->vue帮咱们提供了一些钩子函数[写了就会执行,不写就不执行],到某个阶段,就会触发某个函数的执行
官网图片+理解
Vue生命周期
| 钩子函数 | 描述 |
|---|---|
| beforeCreate | 创建Vue实例之前调用 |
| created | 创建Vue实例成功后调用(可以在此处发送异步请求后端数据) |
| beforeMount | 渲染DOM之前调用 |
| mounted | 渲染DOM之后调用 |
| beforeUpdate | 重新渲染之前调用(数据更新等操作时,控制DOM重新渲染) |
| updated | 重新渲染完成之后调用 |
| beforeDestroy | 销毁之前调用 |
| destroyed | 销毁之后调用 |
<!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>
<input type="text" v-model="username">-->{{username}}
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
username: ''
},
beforeCreate() {
console.log('beforeCreate执行了')
},
created() {
console.log('created执行了')
},
beforeMount() {
console.log('beforeMount执行了')
},
mounted() {
console.log('mounted执行了')
},
beforeUpdate() {
console.log('beforeUpdate执行了')
},
updated() {
console.log('updated执行了')
},
beforeDestroy() {
console.log('beforeDestroy执行了')
},
destroyed() {
console.log('destroyed执行了')
},
})
</script>
</html>
为了演示beforeDestroy,destroyed的执行借助组件
补充:组件
vue实例有生命周期,每个组件也有这8个生命周期
<script>
//组件有自己的html,cxx,js,事件等等
//``模版字符串,是es6的语法
//在组件中,data必须是一个函数,返回对象
//1.定义一个全局组件
Vue.component('child',{
template:``,
data(){
return {}
},
methods:{
},
})
</script>
效果:点击按钮,就显示组件
<!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>
<button @click="handleShow" >显示组件,隐藏组件</button>
<hr>
<child v-if="show"></child>
<hr>
</div>
</body>
<script>
Vue.component('child',{
template:` <div>
<button @click="back">后退</button>
{{name}}
<button @click="forword">前进</button>
</div>`,
data(){
return {
name:'首页'
}
},
methods:{
back(){
alert('后退了')
} ,
forword(){
alert('前进了')
}
},
})
var vm = new Vue({
el: '#app',
data: {
username: '',
show:false
},
methods: {
handleShow(){
this.show = !this.show
}
},
})
</script>
</html>
利用组件演示Vue生命周期
1.created:用的最多,变量初始化完成了(data中得数据),在这里,我们发送ajax请求
2.beforeDestroy:组件销毁之前会执行,主要做资源清理工作
组件创建,就执行一个定时任务[每隔1s,打印一个helloworld]
组件销毁,定时任务要销毁,如果定时任务不销毁,会一直执行
<!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>
<input type="text" v-model="username">-->{{username}}
<h1>使用组件</h1>
<button @click="handleShow">显示组件,隐藏组件</button>
<hr>
<child v-if="show"></child>
<hr>
</div>
</body>
<script>
//组件有自己的html,cxx,js,事件等等
//``模版字符串,是es6的语法
//在组件中,data必须是一个函数,返回对象
//1.定义一个全局组件
Vue.component('child', {
template: `
<div>
<button @click="back">后退</button>
{{ name }}
<button @click="forword">前进</button>
</div>`,
data() {
return {
name: '首页',
t :null,
}
},
methods: {
back() {
alert('后退了')
},
forword() {
alert('前进了')
}
},
beforeCreate() {
console.log('beforeCreate执行了')
console.log(this) //VueComponent
console.log('当前el状态:', this.$el)
console.log('当前data状态:', this.$data)
console.log('当前name状态:', this.name)
},
created() {
console.log('created执行了')
console.log(this)
console.log('当前el状态:', this.$el)
console.log('当前data状态:', this.$data)
console.log('当前name状态:', this.name)
//启动一个定时器
this.t = setInterval(() =>{
console.log('helloword')
},1000)
},
beforeMount() {
console.log('beforeMount执行了')
console.log(this)
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)
},
})
var vm = new Vue({
el: '#app',
data: {
username: '',
show: false
},
methods: {
handleShow() {
this.show = !this.show
}
},
})
</script>
</html>
组件介绍和使用
1.组件:就是扩展 HTML 元素,封装可重用的代码,目的是复用
例如:有一个轮播图,可以在很多页面中使用,一个轮播有js,css,html
组件把js,css,html放到一起,有逻辑,有样式,有html
2.组件的分类:
全局组件:可以放在根中,可以在所有组件中使用
局部组件:只能在当前组件中使用
定义全局组件
1.定义一个全局组件:Vue.component(类似于自定义的标签名,{}),在{}里面写template、data、methods等
2.在全局任意位置使用
<!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>
<hr>
<child></child>
<hr>
<h1>第二次出现</h1>
<child></child>
</div>
</body>
<script>
//1 定义一个全局组件,vue2中,组件必须在一个标签中
Vue.component('child',{
template:`
<div>
<button @click="back">后退</button>
{{name}}
<button @click="forword">前进</button>
</div>
`,
data(){
return {
name:'首页',
}
},
methods:{
back(){
alert('后退了')
},
forword(){
alert('前进了')
}
},
})
var vm = new Vue({
el:'#app',
})
</script>
</html>
定义局部组件
1.局部组件是定义在某个组件内,可以定义多个,只能在它父组件中使用,不能在别的地方使用
2.components写在父组件内,里面写template、data、methods等
<!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>
<child></child>
</div>
</body>
<script>
var child = {
template:` <div>
<h2>我是局部组件</h2>
<img :src="url" alt="" height="300px">
</div>`,
data(){
return {
url:'./img/3.jpg'
}
},
methods:{},
}
//根组件
var vm = new Vue({
el:'#app',
data:{},
//局部组件是定义在某个组件内,可以定义多个,只能在它父组件中使用,不能在别的地方使用
components:{
child,
}
})
</script>
</html>
全局组件和局部组件
<!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>
<hr>
<child></child>
<hr>
<hr>
<part_components></part_components>
<hr>
</div>
</body>
<script>
//全局组件
Vue.component('child', {
template: `
<div>
<h1>全局组件</h1>
<button @click="back">后退</button>
{{ name }}
<button @click="forword">前进</button>
</div>`,
data() {
return {
name: '首页'
}
},
methods: {
back() {
alert('后退了')
},
forword() {
alert('前进了')
}
},
})
//局部组件
var part_components = {
template: ` <div>
<h1>局部组件</h1>
<img :src="img" alt="" height="400px">
</div>`,
data() {
return {
img:'./img/4.jpg'
}
},
methods: {}
}
var vue = new Vue({
el: '#app',
data: {},
methods: {},
//局部组件
components: {part_components,},
})
</script>
</html>
总结
1.全局组件是使用Vue.component定义的,可以在全局任意组件中使用
2.局部组件是定义在某个组件内的:components,只能用在当前组件中
3.组件可以嵌套定义和使用
4.扩展:elementui,提供给咱们很多全局组件
组件间通信
1.父组件把数据传递给子组件
1.需要自定义属性
1.在子组件中自定义属性,使用属性指令绑定父组件的变量
<part_components :myshow="true" :url="url"></part_components>
父组件里的data:url:'./img/5.jpg'
2.在子组件中,使用props接受 ['属性名','属性名2']
"""
限制属性类型:props: {myshow: Boolean, url: String}
"""
3.在子组件中,使用属性名即可
2.子组件把数据传递给父组件
1.需要自定义事件
1.父组件中自定义事件
<part_components @myevent="handelEvent"></part_components>
2.子组件中只要执行 this.$emit('myevent'),就会触发自定义事件对应的函数
父组件methods:
methods:{
handelEvent(username){
console.log('父组件自定义事件的event执行了')
console.log(username)
this.username = username
}
组件间通信之父传子
<!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>
<part_components :myshow="true" :url="url"></part_components>
</div>
</body>
<script>
var part_components={
template: `
<div>
<h1>局部组件</h1>
<img :src="url" alt="" width="300px">
<button @click="handleCheck" >点我看myshow类型</button>
</div>`,
data(){
return {
}
},
methods: {
handleCheck(){
console.log(this.myshow)
console.log(typeof this.myshow) //boolean
}
},
props:['url','myshow']
}
var vue = new Vue({
el:'#app',
data:{
url:'./img/5.jpg'
},
methods:{},
components:{
part_components,
}
})
</script>
</html>
组件间通信之子传父
<!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>
接收到的子组件输入的内容是:{{username}}
<hr>
<part_components @myevent="handelEvent"></part_components>
<hr>
</div>
</body>
<script>
var part_components={
template: `
<div>
<h1>局部组件</h1>
<img :src="url" alt="" height="400px">
<br>
<input type="text" v-model="username">
<button @click="handleSend">传递到父组件去</button>
</div>`,
data(){
return {
url:'./img/6.jpeg',
username:''
}
},
methods: {
handleSend(){
//传递给父组件
console.log(this)
this.$emit('myevent',this.username)
}
}
}
var vue = new Vue({
el:'#app',
data:{
username:'',
},
methods:{
handelEvent(username){
console.log('父组件自定义事件的event执行了')
console.log(username)
this.username = username
}
},
components:{
part_components,
}
})
</script>
</html>
补充
1.以后前后端分离
1.前端是前端(小程序);后端是后端,完全没联系
2.后端只写接口,没有template和static
3.media 要有
ref属性
1.ref属性,vue提供的,写在标签上
1.可以写在普通标签:在vue中使用 this.$refs.名字:拿到dom对象,可以原生操作
eg:
this.$refs.myinput.value = 'nana'
this.$refs.myimg.src='./img/1.jpg'
2.可以写在组件上:在vue中使用 this.$refs.名字:拿到[组件]对象,组件属性,方法直接使用即可
写在普通标签上
<!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>ref属性放在普通标签上</h1>
<input type="text" v-model="username" ref = 'myinput'>--->{{username}}
<br>
<img src="./img/3.jpg" alt="" ref="myimg" height="300px">
<button @click="handleClick">点我执行函数</button>
</div>
</body>
<script>
var vm = new Vue({
el:'#app',
data:{
username:'',
},
methods:{
handleClick(){
console.log(this) //Vue
console.log(this.$refs) //{myinput: input, myimg: img}
//通过key,取到标签,拿到原生dom,通过dom操作,控制标签
this.$refs.myinput.value = 'nana'
this.$refs.myimg.src='./img/1.jpg'
}
},
})
</script>
</html>
写在组件上
<!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>ref属性放在组件上</h1>
<hr>
<part_components ref="myref"></part_components>
<hr>
<button @click="handleClick">点我执行函数</button>
{{username}}
</div>
</body>
<script>
var part_components={
template:` <div>
<button @click="handleBack">后退</button>
{{ title }}
<button>前进</button>
</div>`,
data(){
return {title:'首页'}
},
methods: {
handleBack(){
alert('后退了')
}
},
}
var vm = new Vue({
el:'#app',
data:{
username:'',
},
methods:{
handleClick(){
console.log(this) //Vue
console.log(this.$refs) //{myref: VueComponent}
//放在组件上:在父组件中,能拿到子组件的兑现个,对象中的属性和方法直接用即可
console.log(this.$refs.title)
this.$refs.myref.title = 'nana'
this.username = this.$refs.myref.title
this.$refs.myref.handleBack()
}
},
components:{
part_components,
}
})
</script>
</html>
作业
1.购物车使用计算属性,过滤案例使用计算属性
2.写一个books接口,带按价格排序,前端页面创建完成,向后端发送请求,获取图书属性,表格显示在前端
前端使用监听属性实现点击价格正序和倒序排列
3.定义组件,组件创建成功,向后端发送请求,后端返回一张图片地址,显示在组件上
1 网络图片
2 media下的图片
4 在上面的子组件就中写一个按钮,点击按钮,把子组件的图片地址,传递到父组件中打印出来(alert)
购物车使用计算属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src='https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js'></script>
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"
integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd"
crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css"
integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
<script src='./js/vue.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>
<div class="bs-example" data-example-id="hoverable-table">
<table class="table table-hover">
<thead>
<tr>
<th>商品id</th>
<th>商品名称</th>
<th>商品价格</th>
<th>商品数量</th>
<th>全选/不全选
<input type="checkbox" v-model="check_all" @change="handelcheckall"></th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="goods in good_list">
<th scope="row">{{goods.id}}</th>
<td>{{goods.name}}</td>
<td>{{goods.price}}</td>
<td>
<button class='btn' @click="handeljian(goods)">-</button>
{{goods.number}}
<button class='btn' @click="goods.number++">+</button>
</td>
<td>
<input type="checkbox" v-model="checkGroup" :value="goods" @change="handelcheckone">
</td>
<td>
<input type="button" class='btn btn-danger' value='删除' @click="del_goods(goods)">
</td>
</tr>
</tbody>
</table>
<h3>
合计:{{get_price}}
</h3>
<hr>
选中物品:{{checkGroup}}-->全选:{{check_all}}
</div>
</div>
</div>
</div>
</div>
</body>
<script>
var vue = new Vue({
el: '#app',
data: {
good_list: [
{id: 1, name: '钢笔', price: 12, number: 2},
{id: 2, name: '脸盆', price: 20, number: 20},
{id: 3, name: '毛笔', price: 6, number: 9},
{id: 4, name: '圆珠笔', price: 8, number: 5},
{id: 5, name: '铅笔', price: 1, number: 3},],
checkGroup: [],
check_all: false
},
methods: {
handelcheckall() {
// 全选中:对钩都打上,js中得含义是:checkGroup变量满值
if (this.check_all) {
this.checkGroup = this.good_list
} else {
this.checkGroup = []
}
},
handelcheckone() {
// 判断 checkGroup的长度,是否等于good_list长度
if (this.checkGroup.length != this.good_list.length) {
this.check_all = false
} else {
this.check_all = true
}
},
handeljian(goods){
if (goods.number >1){
goods.number -=1
}else {
alert('不能在减了')
}
},
del_goods(goods){
this.good_list.pop((goods.id)-1)
}
},
computed:{
//总价格 -->循环列表-->价格*数量
get_price(){
sum = 0
for (goods of this.checkGroup) {
sum += goods.price * goods.number
}
return sum
}
}
})
</script>
</html>
写一个books接口
需求:带按价格排序,前端页面创建完成,向后端发送请求,获取图书属性,表格显示在前端,前端使用监听属性:实现点击价格正序和倒序排列
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src='https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js'></script>
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"
integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd"
crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css"
integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
<script src='./js/vue.js'></script>
<script src="https://unpkg.com/axios/dist/axios.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>
<button class="btn btn-success" @click="showBook">展示书籍</button>
<button class="btn btn-success" @click = 'changClick'>{{zheng ? '倒叙' : '正序'}}</button>
<table class="table table-hover table-striped" v-show="is_show">
<thead>
<tr>
<th>id</th>
<th>图书名字</th>
<th>图书价格</th>
</tr>
</thead>
<tbody>
<tr v-for="book in book_list">
<th scope="row">{{book.id}}</th>
<td>{{book.name}}</td>
<td>{{book.price}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
is_show: false,
book_list: [],
zheng: true,
},
methods: {
showBook() {
this.is_show = true
axios.get('http://127.0.0.1:8000/books/').then(res => {
console.log(res.data)
this.book_list = res.data
})
},
changClick(){
this.zheng =!this.zheng
}
},
watch: {
zheng:function() {
if (this.zheng) {
//倒叙
axios.get('http://127.0.0.1:8000/books/?ordering=-price').then(res => {
console.log(res.data)
this.book_list = res.data
})
} else {
//正序
axios.get('http://127.0.0.1:8000/books/?ordering=price').then(res => {
console.log(res.data)
this.book_list = res.data
})
}
}
}
})
</script>
</html>
from django.shortcuts import render
# Create your views here.
from .models import Book
from .serializer import BookSerializer
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin
from rest_framework.response import Response
from rest_framework.filters import OrderingFilter
class BookView(GenericViewSet,ListModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerializer
filter_backends=[OrderingFilter]
ordering_fields = ['price']
def get(self,request):
obj = self.list(request)
return Response(obj.data,headers={'Access-Control-Allow-Origin':'*'})
定义组件,组件创建成功,向后端发送请求,后端返回一张图片地址,显示在组件上(网络图片;media下的图片)
<!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>
<button @click="get_img">父组件接收图片:</button>
<img :src="img" alt="" height="300px">
<hr>
<child :my_img="img" ></child>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
img: '',
is_show:true
},
methods: {
get_img() {
axios.get('http://127.0.0.1:8000/get_img/').then(res => {
console.log(res.data, typeof res.data)
this.img = res.data.url
})
},
},
components: {child:{
template: `
<div>
<h1>组件</h1>
<img :src="my_img" alt="" height="300px">
</div>`,
props: ["my_img"],
}}
})
</script>
</html>
from django.http import JsonResponse
def get_img(request):
url='https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2F5da5a7c4-e8ef-4975-8581-81e42fdba317%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1688648650&t=cfe8b5c2fa170e2a7d4815454cd7956a'
obj = JsonResponse({'url':url})
obj.headers['Access-Control-Allow-Origin'] ='*'
return obj
media
<!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>
<button @click="get_img">父组件接收图片:</button>
<img :src="img" alt="" height="300px">
<hr>
<child :my_img="img" ></child>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
img: '',
is_show:true
},
methods: {
get_img() {
this.img='http://127.0.0.1:8000/media/img/1.jpg'
},
},
components: {child:{
template: `
<div>
<h1>组件</h1>
<img :src="my_img" alt="" height="300px">
</div>`,
props: ["my_img"],
}}
})
</script>
</html>
from django.contrib import admin
from django.urls import path,re_path
from app01.views import BookView,get_img
from django.views.static import serve
from django.conf import settings
urlpatterns = [
path('admin/', admin.site.urls),
path('books/', BookView.as_view({'get':'get'})),
path('get_img/', get_img),
re_path(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),
]