vue-day04
补充1:定时任务和延迟任务,js中如何实现
setTimeout(function(){},3000) # 3s后执行匿名函数 var t=setInterval(function(){},3000) # 每隔3s执行匿名函数 clearInterval(t) # 停止定时任务 t=null 1 定时切换图片 2 倒计时效果 3 定时向后端发请求
与后端交互的三种方式
前后端要打通,从前端发送ajax,核心:使用js发送http请求,接收返回
原生js,可以开启ajax,但是原生js开启,比较麻烦,需要做浏览器兼容
jq,写了个兼容所有浏览器的 $.ajax(),不仅仅有ajax,还封装了很多dom操作,vue中使用它,不合适
axios:第三方的ajax包(咱们用)
fetch: 原生js发送ajax请求,有的浏览器也不兼容
后端
views
from rest_framework.decorators import action from rest_framework.response import Response from rest_framework.views import APIView from rest_framework.viewsets import ViewSet class Index(ViewSet, APIView): @action(methods=['POST'], detail=False) def look(self, request, *args, **kwargs): print('llnb') response = Response({'name': '彭于晏', 'age': 19}) response['Access-Control-Allow-Origin'] = '*' return response
urls
from django.contrib import admin from django.urls import path from rest_framework.routers import SimpleRouter from app01.views import Index router = SimpleRouter() router.register('index', Index, 'index') urlpatterns = [ path('admin/', admin.site.urls), ] urlpatterns += router.urls
方式一:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <title>Title</title> </head> <body> <div id="APP"> <p>name:{{ name }}</p> <p>age:{{ age }}</p> <button @click="handlerAge">点击显示名字和年龄</button> </div> </body> <script> let vm = new Vue({ el: '#APP', data: { name: '', age: '' }, methods: { handlerAge() { var _this = this $.ajax({ url: 'http://127.0.0.1:8000/index/look/', type: 'POST', success: function (data) { console.log(typeof data) _this.name = data.name _this.age = data.age } }) } }, }) </script> </html>
方式二:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <title>Title</title> </head> <body> <div id="APP"> <p>name:{{ name }}</p> <p>age:{{ age }}</p> <button @click="handlerAge">点击显示名字和年龄</button> </div> </body> <script> let vm = new Vue({ el: '#APP', data: { name: '', age: '' }, methods: { handlerAge() { fetch('http://127.0.0.1:8000/index/look/').then(res => res.json()).then(res1 => this.name = res1.name) } }, }) </script> </html>
方式三:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> <title>Title</title> </head> <body> <div id="APP"> <p>name:{{ name }}</p> <p>age:{{ age }}</p> <button @click="handlerAge">点击显示名字和年龄</button> </div> </body> <script> let vm = new Vue({ el: '#APP', data: { name: '', age: '' }, methods: { handlerAge() { let _this = this axios.get('http://127.0.0.1:8000/index/look/').then(function (res) { console.log(res.data) _this.name = res.data.name _this.age = res.data.age }) } }, }) </script> </html>
显示小电影案咧
前端
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> <title>Title</title> </head> <body> <div id="box"> <button @click="handleClick">加载电影数据</button> <p>加载的数据:</p> <ul> <li v-for="item in dataList"> <p>电影:{{item.name}}</p> <p>导演:{{item.director}}</p> <img :src="item.poster" alt=""> </li> </ul> </div> </body> <script> let vm = new Vue({ el: '#box', data: { dataList: [] }, methods: { handleClick() { axios.get("http://127.0.0.1:8000/show/look/").then(res => { console.log(res.data.data.films) // axios 自动包装data属性 res.data this.dataList=res.data.data.films }).catch(err => { console.log(err); }) } } }) </script> </html> </html>
后端
class Show(ViewSet, APIView): @action(methods=['GET'], detail=False) def look(self, request, *args, **kwargs): with open('fliems.json', 'rt', encoding='utf-8') as f: res = json.load(f) response = Response(res) response['Access-Control-Allow-Origin'] = '*' return response
路由
from django.contrib import admin from django.urls import path from rest_framework.routers import SimpleRouter from app01.views import Index, Show router = SimpleRouter() router.register('show', Show, 'show') urlpatterns = [ path('admin/', admin.site.urls), ] urlpatterns += router.urls
计算属性
1 计算属性是基于它们的依赖变量进行缓存的 2 计算属性只有在它的相关依赖变量发生改变时才会重新求值,否则不会变(函数只要页面变化,就会重新运算) 3 计算属性就像Python中的property,可以把方法/函数伪装成属性 4 计算属性,必须有返回值
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>实现输入input中后名字首字母大写</h1> <!-- <input type="text" v-model="username">-–>{{username.substring(0, 1).toUpperCase() + username.substring(1)}}--> <input type="text" v-model="username">--->{{getUpperCase()}} <br> <input type="text" v-model="age">---->{{age}} <h2>通过计算属性实现--->当属性用</h2> <input type="text" v-model="username1">--->{{getName}} </div> </body> <script> var vm = new Vue({ el: '#app', data: { username: '', age: '', username1: '' }, methods: { getUpperCase() { console.log('函数执行我执行了') return this.username.substring(0, 1).toUpperCase() + this.username.substring(1) } }, computed: { getName() { 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"> <title>Title</title> <script src="./js/vue.js"></script> </head> <body> <div id="app"> <h1>实现输入input中后名字首字母大写</h1> <!-- <input type="text" v-model="username">-–>{{username.substring(0, 1).toUpperCase() + username.substring(1)}}--> <input type="text" v-model="username">--->{{getUpperCase()}} <br> <input type="text" v-model="age">---->{{age}} <h2>通过计算属性实现--->当属性用</h2> <input type="text" v-model="username1">--->{{getName}} </div> </body> <script> var vm = new Vue({ el: '#app', data: { username: '', age: '', username1: '' }, methods: { getUpperCase() { console.log('函数执行我执行了') return this.username.substring(0, 1).toUpperCase() + this.username.substring(1) } }, computed: { getName() { 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"> <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>
监听属性:属性如果发生变化,就会执行某个函数
<!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('老值', oldValue) console.log('新值', newValue) console.log('我发生变化了') } } }) </script> </html>
new Vue()---->创建出来---》页面关闭---》被销毁掉----》整个整个过程经历了一个周期----》vue帮咱们提供了一些钩子函数[写了就会执行,不写就不执行],到某个阶段,就会触发某个函数的执行 8 个生命周期钩子函数 beforeCreate 创建Vue实例之前调用 created 创建Vue实例成功后调用 beforeMount 渲染DOM之前调用 mounted 渲染DOM之后调用 beforeUpdate 重新渲染之前调用(数据更新等操作时,控制DOM重新渲染) updated 重新渲染完成之后调用 beforeDestroy 销毁之前调用 destroyed 销毁之后调用
vue实例有生命周期,每个组件也有这8个生命周期
8个声明周期钩子,什么情况会用到
created:用的最多,变量初始化完成了(data中得数据),在这里,我们发送ajax请求
beforeDestroy:组件销毁之前会执行
组件创建,就执行一个定时任务[每隔1s,打印一个helloworld]
组件销毁,定时任务要销毁,如果定时任务不销毁,会一直执行
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> <input type="text" v-model="username"> --->{{username}} <h1>使用组件</h1> <button @click="handleShow">显示组件,隐藏组件</button> <hr> <child v-if="show"></child> <hr> </div> </body> <script> // 组件有自己的html,css,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('当前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) }, }) var vm = new Vue({ el: '#app', data: { username: '', show: false }, methods: { handleShow() { this.show = !this.show } } // 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>
组件介绍
组件就是:扩展 HTML 元素,封装可重用的代码,目的是复用
例如:有一个轮播图,可以在很多页面中使用,一个轮播有js,css,html
组件把js,css,html放到一起,有逻辑,有样式,有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> <h1>第二次出现</h1> <child></child> </div> </body> <script> //1 定义一个全局组件,vue2中,组件必须在一个标签中 Vue.component('child', { template: ` <div> <button @click="back">后退</button> {{ title }} <button>前进</button> </div> `, data() { return { title: '我是首页' } }, methods: { back() { console.log('退了') } } }) / var vm = new Vue({ el: '#app', data: {}, }) </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> <lqz></lqz> </div> </body> <script> // var lqz={ template: ` <div> <h1>我是局部组件</h1> <img :src="url" alt="" height="400px"> </div>`, data() { return { url: 'http://pic.imeitou.com/uploads/allimg/230331/7-230331110I0.jpg' } }, methods: {} } // 根组件 var vm = new Vue({ el: '#app', data: {}, // 局部组件是定义在某个组件内,可以定义多个,只能在它父组件中使用,不能到别的地方使用 components: { lqz } }) </script> </html>
总结
1 全局组件是使用Vue.component定义的,可以在全局任意组件中使用 2 局部组件是定义在某个组件内的:components,只能用在当前组件中 3 组件可以嵌套定义和使用 扩展:elementui,提供给咱们很多全局组件
组件间通信
组件嵌套
父组件被数据传递给子组件 自定义属性 1 在子组件中自定义属性,使用属性指令绑定父组件的变量 2 在子组件中,使用props接受 ['属性名','属性名2'] 3 在子组件中,使用属性名即可 子组件把数据传递给父组件 自定义事件 1 父组件中自定义事件:<lqz @myevent="handelEvent"></lqz> 2 子组件中只要执行 this.$emit('myevent'),就会触发自定义事件对应的函数
<!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> <lqz :url="url" :myshow="true"></lqz> <hr> </div> </body> <script> // 2 var lqz = { template: ` <div> <h1>我是局部组件</h1> <img :src="url" alt="" height="400px"> <button @click="handleCheck">点我看myshow类型</button> </div>`, data() { return {} }, methods: { handleCheck() { console.log(this.myshow) console.log(typeof this.myshow) } }, props: ['url', 'myshow'] } // 根组件 var vm = new Vue({ el: '#app', data: { url: 'http://pic.imeitou.com/uploads/allimg/230331/7-230331110I0.jpg', }, // 局部组件是定义在某个组件内,可以定义多个,只能在它父组件中使用,不能到别的地方使用 components: { lqz, } }) </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> <lqz @myevent="handelEvent"></lqz> <hr> </div> </body> <script> // 2 var lqz = { 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: 'http://pic.imeitou.com/uploads/allimg/230331/7-230331110I0.jpg', username: '' } }, methods: { handleSend() { // 传递给父组件 this.$emit('myevent', this.username) } } } // 根组件 var vm = new Vue({ el: '#app', data: { username: '' }, methods: { handelEvent(username) { console.log('父组件自定义事件的event执行了') console.log(username) this.username = username } }, // 局部组件是定义在某个组件内,可以定义多个,只能在它父组件中使用,不能到别的地方使用 components: { lqz, } }) </script> </html>
补充
以后前后端分离
前端是前端(小程序)
后端是后端,完全没联系
后端只写接口,没有template和static
media 要有
ref属性,vue提供的,写在标签上
可以写在普通标签:在vue中使用 this.$refs.名字 拿到dom对象,可以原生操作
可以写在组件上:在vue中使用 this.$refs.名字 拿到[组件]对象,组件属性,方法直接使用即可
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>
<input type="text" v-model="username" ref="myinput">
<br>
<img src="http://pic.imeitou.com/uploads/allimg/230331/7-230331110I0.jpg" alt="" height="300px" ref="myimg">
<h1>ref放在组件上</h1>
<hr>
<lqz ref="mylqz"></lqz>
<hr>
<button @click="handleClick">点我执行函数</button>
<br>
{{username}}
</div>
</body>
<script>
var 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>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY