钩子函数 | 描述 |
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> <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"> <script src="./js/vue.js"></script> </head> <body> <div class="container-fluid"> <div class="row"> <div class="col-md-6 col-md-offset-3" style="margin-top: 20px"> <div id="app"> {{name}} </div> </div> </div> </div> </body> <script> var vm = new Vue({ el: '#app', data: { name:'lqz' }, methods: {}, beforeCreate() { console.log('当前状态:beforeCreate') }, created() { console.log('当前状态:created') }, beforeMount() { console.log('当前状态:beforeMount') }, mounted() { console.log('当前状态:mounted') //用的最多,向后端加载数据,创建定时器等 //挂在,三秒后执行一个任务 // setTimeout(()=> { // console.log('lqz is nb') // },3000) this.t = setInterval(function () { console.log('lqz is nb') }, 3000) }, beforeUpdate() { console.log('当前状态:beforeUpdate') }, updated() { console.log('当前状态:updated') }, beforeDestroy() { console.log('当前状态:beforeDestroy') }, destroyed() { console.log('当前状态:destroyed') clearInterval(this.t) this.t = null console.log('destoryed') }, }) </script> </html>
组件
jquery-ajax、fetch和axios
jquery的ajax(不推荐使用)
fetch(不是所有浏览器都支持,谷歌浏览器支持)
axios(基本都是用它)
前后端交互之jquery-ajax
前端
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <script src="./js/vue.js"></script> </head> <body> <div class="container-fluid"> <div class="row"> <div class="col-md-6 col-md-offset-3" style="margin-top: 20px"> <div id="app"> <button @click="handle_load">点我加载数据</button> <hr> 拿回来的数据是:{{name}} </div> </div> </div> </div> </body> <script> var vm = new Vue({ el: '#app', data: { name:'lqz' }, methods: { handle_load(){ $.ajax({ url:'http://127.0.0.1:5000/', type:'get', success:data=> { this.name=data } }) } }, mounted() { //跟后端交互,写在这,而不要使用button console.log('当前状态:mounted') this.handle_load() }, }) </script> </html>
后端
from flask import Flask, make_response
app = Flask(__name__)
@app.route('/')
def index():
res = make_response('hello world')
# 运行所有域向我发请求(解决跨域问题)
res.headers['Access-Control-Allow-Origin']='*'
return res
if __name__ == '__main__':
app.run()
前后端交互之fetch
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"> <script src="./js/vue.js"></script> </head> <body> <div class="container-fluid"> <div class="row"> <div class="col-md-6 col-md-offset-3" style="margin-top: 20px"> <div id="app"> <ul> <li v-for="film in films_list"> <img :src="film.poster" alt="" width="60px" height="80px"> <span>{{film.name}}</span> <hr> </li> </ul> </div> </div> </div> </div> </body> <script> var vm = new Vue({ el: '#app', data: { films_list: [] }, methods: { handle_load() { fetch('http://127.0.0.1:5000/home').then(data => data.json()).then(data => { console.log(data) if (data.status == 0) { this.films_list = data.data.films } else { alert('加载出错') } }) } }, mounted() { //跟后端交互,写在这,而不要使用button console.log('当前状态:mounted') this.handle_load() }, }) </script> </html>
前后端交互之axios
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> <script src="./js/vue.js"></script> </head> <body> <div class="container-fluid"> <div class="row"> <div class="col-md-6 col-md-offset-3" style="margin-top: 20px"> <div id="app"> <ul> <li v-for="film in films_list"> <img :src="film.poster" alt="" width="60px" height="80px"> <span>{{film.name}}</span> <hr> </li> </ul> </div> </div> </div> </div> </body> <script> var vm = new Vue({ el: '#app', data: { films_list: [] }, methods: { handle_load() { axios.get('http://127.0.0.1:5000/home').then(data => { //data.data才是后端响应的数据 console.log(data) if (data.data.status == 0) { this.films_list = data.data.data.films } else { alert('加载出错') } }) } }, mounted() { //跟后端交互,写在这,而不要使用button console.log('当前状态:mounted') this.handle_load() }, }) </script> </html>
计算属性
计算属性的特点:只要返回的结果没有发生变化,那么计算属性就只会被执行一次
计算属性的应用场景:由于计算属性会将返回的结果缓存起来,所以如果返回的数据不经常发生变化
那么使用计算属性的性能就会比使用函数的性能高
把输入的首字母大写
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"> <script src="./js/vue.js"></script> </head> <body> <div class="container-fluid"> <div class="row"> <div class="col-md-6 col-md-offset-3" style="margin-top: 20px"> <!-- 这个就是MVVM中的 View --> <div id="app"> {{name}} <input type="text" v-model="s"> <hr> <!-- s.slice 从第0个位置截到第一个位置转成大写,只是第一个字母。还得把后面的字母加上,从第一个截到最后拼上--> 输入的值是:{{s.slice(0,1).toUpperCase()+s.slice(1)}} <hr> <!-- 写一个函数,跟上面一样,缺点:只要页面有值变化,它会触发update的执行, 不管是函数还是其它还会再执行一次 --> 输入的值是:{{to_upper()}} <hr> 输入的值是(计算属性) :{{str_s}} </div> </div> </div> </div> </body> <script> // 这个就是MVVM中的View Model var vm = new Vue({ el: '#app', // 这个就是MVVM中的Model data: { s:'', name:'' }, // 专门用于定义计算属性的 computed:{ str_s(){ // 计算属性的特点:只要返回的结果没有发生变化,那么计算属性就只会被执行一次 //只有该方法中使用的值发生变化,才会重新计算 console.log('计算属性的方法,我执行了') return this.s.slice(0,1).toUpperCase()+this.s.slice(1) } }, //专门用于存储监听事件回调函数 methods:{ // 函数的特点:每次调用都会执行 to_upper(){ console.log('我执行了') return this.s.slice(0,1).toUpperCase()+this.s.slice(1) } }, }) </script> </html>
重写过滤案例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"> <script src="./js/vue.js"></script> </head> <body> <div class="container-fluid"> <div class="row"> <div class="col-md-6 col-md-offset-3" style="margin-top: 20px"> <div id="app"> <p><input type="text" v-model="mytext" @input="handleChange"></p> <ul> <li v-for="data in newdatalist">{{data}}</li> </ul> </div> </div> </div> </div> </body> <script> var vm = new Vue({ el: '#app', data: { mytext: '', datalist: ['aaa', 'abc', 'abcde', 'abcdef', 'bbb', 'bac'], }, computed: { newdatalist() { var newlist = this.datalist.filter(item => { return item.indexOf(this.mytext) > -1 }) return newlist } }, }) </script> </html>
虚拟dom优化问题
1 v-for循环的时候,经常看到有个自定义属性 key
2 key是一个唯一值,为了虚拟dom替换的时候,效率高
组件化开发介绍
Vue的两大核心:1.数据驱动界面改变,2.组件化
什么是组件?什么是组件化?
在前端开发中组件就是把一个很大的界面拆分为多个小的界面,每一个小的界面就是一个组件
将大界面拆分成小界面就是组件化
组件化的好处:
可以简化Vue实例的代码
可以提高复用性
-例如:有一个轮播,可以在很多页面中使用,一个轮播有js,css,html
-组件把js,css,html放到一起,有逻辑,有样式,有html
Vue中如何创建组件?
创建组件构造器
注册已经创建好的组件
使用注册好的组件
全局组件:整个项目中都能使用的组件
局部组件:只能再局部使用
注册全局组件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="./js/vue.js"></script> </head> <body> <div id="app"> <myhead></myhead> <hr> <myhead></myhead> </div> </body> <script> Vue.component('myhead', { template: ` <div> <button @click="handleClick">我是个按钮:点我看美女</button> <button>我又是一个按钮</button> </div> `, methods: { handleClick(){ alert('美女') } }, }) var vm = new Vue({ el: '#app', data: {}, methods: { } }) </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"> <myhead></myhead> <hr> </div> </body> <script> Vue.component('myhead', { template: ` <div> <button @click="handleClick">我是个按钮:点我看美女</button> <button>我又是一个按钮--{{name}}</button> {{show}} <hr> 看到美女了 <child></child> </div> `, methods: { handleClick() { alert('美女') } }, components:{ child:{ template:` <div> <img src="./img/1.jpg" alt="" v-show="show" height="60px" width="60px"> <button @click="handleRemove">点我图片消失</button> </div> `, data(){ return { show:true } }, methods:{ handleRemove(){ this.show=!this.show } } } }, data(){ return {name:'lqz'} }, }) var vm = new Vue({ el: '#app', data: {}, methods: {} }) </script> </html>
组件间通信
1 父子组件传值 (props down, events up) 2 父传子之属性验证props:{name:Number}Number,String,Boolean,Array,Object,Function,null(不限制类型) 3 事件机制a.使用 $on(eventName) 监听事件b.使用 $emit(eventName) 触发事件 4 Ref<input ref="mytext"/> this.$refs.mytext 5 事件总线var bus = new Vue();* mounted生命周期中进行监听
父传子
在子组件上新增属性 <myhead myname="lqz"></myhead> 在子组件中:定义,myname要跟新增的属性名一致 props:['myname'] 在子组件中就可以使用myname变量了,从父组件传入的 注意加不加:的区别 <myhead :myname="lqz"></myhead>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="./js/vue.js"></script> </head> <body> <div id="app"> <!-- <myhead myname="lqz"></myhead>--> <!-- <hr>--> <!-- <myhead :myname="name"></myhead>--> <hr> <myhead :mybool="false"></myhead> </div> </body> <script> Vue.component('myhead', { template: ` <div> <button>我是按钮</button> 我的名字是: <br> 传入的布尔值是:{{typeof mybool}} </div> `, // props:['myname','mybool'] //类型限制 props: { mybool: Boolean, } }) var vm = new Vue({ el: '#app', data: { name: '迪丽热巴' }, }) </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"> <myhead @myevent="handleParent" @egon="handleEgon"></myhead> </div> </body> <script> Vue.component('myhead', { template: ` <div> <button @click="handleChild">我是按钮</button> </div> `, data(){ return { n:100, m:200 } }, methods:{ handleChild(){ console.log('子组件的按钮被点击了') // this.$emit('myevent') //触发自定义的事件执行(触发myevent的执行) // this.$emit('myevent',this.n,this.m) //触发自定义的事件执行(触发myevent的执行) // this.$emit('egon') } }, mounted(){ this.$emit('egon') } }) var vm = new Vue({ el: '#app', data: { n:0, m:0, }, methods:{ handleParent(n,m){ console.log('自定义的事件执行了') this.n=n this.m=m console.log(n) console.log(m) }, handleEgon(){ console.log('egon被打了') } } }) </script> </html>
通过ref实现父子通信
<!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" placeholder="我是父组件的1" ref="myinput"> <input type="text" placeholder="我是父组件的2" ref="myinput2"> <input type="password" placeholder="我是父组件的3" ref="myinput3"> <button @click="handleParentButton">点我执行一个函数</button> <hr> <myhead ref="mychild"></myhead> </div> </body> <script> Vue.component('myhead', { template: ` <div> <button>我是按钮</button> </div> `, data(){ return { name:'lqz' } }, methods:{ tgc(name){ this.name=name alert(name) } }, }) var vm = new Vue({ el: '#app', data: { }, methods:{ handleParentButton(){ console.log('父组件的button按钮被点击了') // // console.log(this.$refs.myinput3.value) // console.log(this.$refs.myinput3.type) console.log(this.$refs.mychild.tgc('lqz is big')) } } }) //ref属性如果加在普通标签上,通过this.$refs.myinput,取到的就是这个标签 //ref属性如果加在组件上,通过this.$refs.mychild,取到的就是这个组件,拿到组件的值,拿到组件的方法,并且可以执行 </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"> <myhead></myhead> <hr> <child1></child1> </div> </body> <script> // 定义一个事件总线 var bus = new Vue() //new一个vue的实例,就是中央事件总线 Vue.component('myhead', { template: ` <div> <button>我是按钮</button> 来自另一个组件的数据: <span v-text="recv"></span> </div> `, mounted() { //生命周期,当前组件dom创建完后悔执行 console.log('当前组件dom创建完后悔执行') //订阅消息 bus.$on('suibian', (item) => { console.log('收到了', item) this.recv=item }) }, data(){ return { recv:'' } } }) Vue.component('child1', { template: ` <div> <input type="text" v-model="input_1"> <button @click="handleClick">点我</button> </div>`, methods: { handleClick() { bus.$emit('suibian', this.input_1) //发布消息,名字跟订阅消息名一致 } }, data(){ return { input_1:'' } } }) var vm = new Vue({ el: '#app', data: {}, }) //ref属性如果加在普通标签上,通过this.$refs.myinput,取到的就是这个标签 //ref属性如果加在组件上,通过this.$refs.mychild,取到的就是这个组件,拿到组件的值,拿到组件的方法,并且可以执行 </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"> <button @click="who='myhead1'">显示组件1</button> <button @click="who='myhead2'">显示组件2</button> <button @click="who='myhead3'">显示组件3</button> <keep-alive> <component :is="who"></component> </keep-alive> </div> </body> <script> Vue.component('myhead1', { template: ` <div> <button> myhead1的按钮</button> <div> 我是组件1111的样子 </div> </div> `, }) Vue.component('myhead2', { template: ` <div> <button >myhead2的按钮</button> <div> 我是组件222的样子 <input type="text"> </div> </div> `, }) Vue.component('myhead3', { template: ` <div> <button >myhead3的按钮</button> <div> 我是组件333的样子 <button>点我</button> <hr> <span>xxx</span> </div> </div> `, }) var vm = new Vue({ el: '#app', data: { who: 'myhead1' }, }) //ref属性如果加在普通标签上,通过this.$refs.myinput,取到的就是这个标签 //ref属性如果加在组件上,通过this.$refs.mychild,取到的就是这个组件,拿到组件的值,拿到组件的方法,并且可以执行 </script> </html>
Vue-cli创建项目
1 安装node环境:最新是14 - 跟python比较 - node python - npm pip3 - 安装cnpm,淘宝做的npm,以后使用npm的地方,都是用cnpm 2 安装cli脚手架 -cnpm install -g @vue/cli 3 创建项目 vue create my-project # 命令行 # OR vue ui #图形化界面
目录介绍
├─ node_moduls:项目依赖,当前项目的所有第三方包,(上传项目的时候不需要用:把项目给别人,这个文件夹删掉) npm install 就会又把依赖重新装上 pi3 install -r request.txt ├─ public文件夹:(你不用动) ├─ favicon.ico 网站图标 └─ index.html 项目入口页面,单页面开发(整个vue项目就这一个页面,一般不会动它) ├─ src文件夹:代码文件夹(经常动,书写你的所有代码) ├─ assets文件夹 :存储项目中自己的一些静态资源,图片,js,css ├─ components文件夹:存储项目中的自定义组件(组件,小组件,公共组件) ├─ router文件夹:存储VueRouter路由相关文件(装了Router才有,否则没有,页面跳转) ├─ store文件夹:存储Vuex相关文件(vuex才有的,状态管理器) ├─ views文件夹:存储项目中的自定义组件(大组件,页面级组件,路由级别组件) ├─ App.vue:根组件 └─ main.js:整个项目的入口js ├─ .gitignore # git的忽略文件,讲到git才知道 ├─ babel.config.js # 不用动 ├─ package.json #依赖的模块 ├─ package-lock.json #依赖的模块 └─ README.md # 介绍
项目组件介绍(重点)
每一个组件都有三部分 # html内容写在这 // template 用于编写当前组件的结构代码的 <template> <div class="home"> </div> </template> # js内容 // script 用于编写当前组件的业务代码的 <script> export default { name: 'Home', data(){ return { a:'asdfasdfasdfasdfasd' } }, } </script> # style的内容 // style 用于编写当前组件额样式代码的 <style> </style>
把vue项目编译成纯html,css,js
webpack:模块化
打包:npm run build
在项目路径下有个dist文件夹:html,css,js