0:ES6补充
0.1 块级作用域
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| <script> { var name = 'why'; console.log(name); } console.log(name); var btns = document.getElementsByTagName('button'); for(var i = 0; i<btns.length;i++){ btns[i].addEventListener('click',function(){ console.log('第'+i+'个按钮被点击') }) } for(var i = 0; i<btns.length;i++){ (function(num){ btns[num].addEventListener('click',function(){ console.log('第'+num+'个按钮被点击') }) })(i) } </script>
|
1:Vue初体验
1.1 认识Vuejs
作为时下流行的前端框架,Vuejs是很多中小型企业开发项目的首选框架。
Vue是一个渐进式的框架。
- 渐进式意味着可以将Vue作为应用的一部分嵌入进去,带来更丰富的交互体验。
Vue特点和Web开发中的高级功能
- 解耦视图和数据
- 可复用的组件
- 前端路由
- 状态管理
- 虚拟DOM
学习前提
- 不需要Angular、React、jQuery
- 需要HTML、CSS、JavaScript基础
1.2 Vue.js安装
方式一:直接CDN引入
方式二:下载和引入
方式三:NPM安装
1.3 Hello Vuejs
Vue的响应式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <body>
<div id="app"> <h1> {{name}} </h1> {{message}} </div> <script src="../js/vue.js"></script> <script> const app = new Vue({ el:'#app', data:{ message:'你好啊!', name:'coderwhy' } })
</script> </body>
|
1.4 Vue列表显示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <body> <div id="app"> <ul> <li v-for="item in movies">{{item}}</li> </ul> </div> <script src="../js/vue.js"></script> <script> const app = new Vue({ el:'#app', data:{ message:'你好啊', movies:['海王','大话西游','星际穿越','少年派'] } }) </script> </body>
|
app.movies.push('盗梦空间')//添加数据
案例展示:计数器
当前计数:0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| <body> <script src="../js/vue.js"></script> <div id="app"> <h2> 当前计数:{{counter}} </h2> <button v-on:click="add">+</button> <button @click="min">-</button> </div> <script> const app = new Vue({ el:'#app', data:{ counter:0 }, methods:{ add:function(){ console.log('add被执行'); this.counter++; }, min:function(){ console.log('min被执行'); this.counter--; } } }) </script> </body>
|
1.5 Vue中的MVVM
什么是MVVM?
1.6 创建Vue实例传入的options
目前掌握的选项
el:
- 字符型String|HTMLElement
- 决定Vue管理哪一个DOM
data:
- Object|Funtion()(组件当中必须是一个函数)
- Vue实例对应的数据对象。
methods:
- {[key:string] Function}
- 定义属于Vue的一些方法,可以在其他地方调用,也可以在指令中使用
1.7 Vue的生命周期
生命周期:事物从诞生到消亡的整个过程
1 2 3 4 5 6 7 8 9
| <script> new Vue({ el:'#app', data:obj, methods:{}, created:function(){}, mounted:function(){} }) </script>
|
1.8 Vue的生命周期函数
1 2 3 4 5 6 7 8 9 10
| <script> new Vue({ el:'#app', data:obj, methods:{}, beforeCreate:function(){}, created:function(){}, mounted:function(){} }) </script>
|
生命周期函数:beforeCreate,create,beforeMounte,mounted,beforeUpdate,updated,beforDestroy,destroyed
2:插值的操作
2.1 Mustache语法,插值的操作
Mustache语法:双大括号//mustache胡须
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <div> <h2> {{message}} </h2> <h2> {{firstName+' '+lastName}} </h2> <h2> {{firstName}} {{lastName}} </h2> <h2>{{counter*2}}</h2> </div> <script> new Vue({ el:'#app', data:{ message:'nihao', firstName:'kobe', lastName:'bryant', counter:100 }, }) </script>
|
mustache语法不仅可以直接写变量,还可以写语法。
2.2 插值操作–其他指令使用
- v-once: 不想改变DOM值,使DOM变成非响应式。
1 2 3
| <h2 v-once> {{message}} </h2>
|
- v-html:直接展示html代码,而不是展示其字符串
1 2 3 4 5 6 7 8 9 10 11
| <div> <h2 v-html="url"></h2> </div> <script> new Vue({ el:'#app', data:{ url='<a href="https://www.baidu.com">百度一下</a>' } }) </script>
|
输出结果:百度一下
- v-text:和作用相同,但会覆盖
<h2>
代码块中的字符会被覆盖掉,不灵活。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <body>
<div id="app"> <h2 v-text="message"></h2> <h2>{{message}}</h2> </div> <script src="../js/vue.js"></script> <script> const app = new Vue({ el:'#app', data:{ message:'你好啊!' } }) </script> </body>
|
1 2 3
| <h2 v-pre> {{message}} </h2>
|
输出结果:
- v-cloak:当js延迟加载出来时,不显示dom渲染之前的值。不会在渲染之前出现//cloak斗篷
1 2 3 4 5 6 7 8 9 10 11 12 13
|
<div id="app" v-cloak> {{message}} </div> <script> ... </script>
|
3:动态绑定属性
3.1 v-bind,动态绑定DOM属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <body>
<div id="app"> <img v-bind:src="imgURL" alt=""> <a v-bind:href="aHref"></a> <img :src="imgURL" alt=""> <a :href="aHref"></a> </div> <script src="../js/vue.js"></script> <script> const app = new Vue({ el:'#app', data:{ aHref="https://www.baidu.com", imgURL:'https://i0.hdslb.com/bfs/sycp/creative_img/202002/1e9bfa663a93374c8e10c3933cfc78f8.jpg' } }) </script> </body>
|
- v-bind简写/语法糖:
:
- v-bind对象用法:
1 2 3 4 5 6 7 8 9 10 11 12
| <div> <h2 class="title" :class="{class1:isClass1,class2:isClass2}">{{message}}</h2> </div> <script> new Vue({ data:{ message:"showClassExample" isClass1:true, isClass2:false } }) </script>
|
//title类固定,动态更改class1和class2
{类名:布尔值,类名:布尔值}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <div> <h2 class="title" :class="getClasses()">{{message}}</h2> </div> <script> new Vue({ data:{ message:"showClassExample", isClass1:true, isClass2:false } methods:{ getClasses:function(){ return{class1:this.isClass1,class2:this.isClass2} } } }) </script>
|
注意:v-on中函数省略了(),但v-bind需要添加()
1 2 3 4 5 6 7 8 9 10 11 12
| <div> <h2 class="title" :class="[class1,class2]">{{message}}</h2> </div> <script> new Vue({ data:{ message:"showClassExample", class1:'class1', class2:'class2' } }) </script>
|
3.2 作业,结合v-for和v-bind
作业:使用v-for显示一个电影名称列表,设置监听点击事件,当某个电影被点击,改变此电影名称字体颜色为红色。
答案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .red{color:red} </style> </head> <body> <script src="./js/vue.js"></script> <div id="app"> <ul> <li v-for="(m, index) in movies" @click="clickItem=index" :class="{red:clickItem==index}">{{m}}</li> </ul> </div> <script> const app = new Vue({ el:'#app', data: { movies: ['复仇者联盟', '生化危机', '星际大战', '钢铁侠'], clickItem:99, } }) </script> </body> </html>
|
3.3 v-bind动态绑定样式
1 2 3 4 5 6 7 8 9 10 11 12 13
| <div> <h2 :style="{fontSize:'50px',color:finalColor}"> {{message}} </h2> </div> <script> new Vue({ data:{ message:'abc', finalColor:'red' } }) </script>
|
注意:{fontSize:50px}为错误表达,50px会被解析为一个变量,50px必须加单引号
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <div> <h2 :style="[style1,style2]"> {{message}} </h2> </div> <script> new Vue({ el:'#app', data:{ message:'abc', style1:{fontSize:'100px'}, style2:{color:'red'} } }) </script>
|
4:计算属性
4.1 计算属性的基本用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| <div id="app"> <h2> {{firstName+" "+lastName}} </h2> <h2> {{getFullName()}} </h2> <h2> {{fullName}} </h2> </div> <script> new Vue({ el:'#app', data:{ firstName:'Lebron', lastName:'James' }, computed:{ fullName:function(){ return this.fistName+' '+this.lastName; } }, methods:{ getFullName(){ return this.fistName+' '+this.lastName; } } }) </script>
|
computed:计算属性的使用
4.2 计算属性的复杂使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| <div id="app"> <h2> 总价格:{{totalPrice}} </h2> </div> <script> new Vue({ el:'#app', data:{ books:{ {id:110,name:'Unix编程',price:119}, {id:111,name:'代码大全',price:89}, {id:112,name:'现代操作系统',price:81} } }, computed:{ totalPrice:function(){ for(let i=0;i<this.books.length;i++){ result += this.books[i].price; } /* for(let i in this.books){ result += this.books[i].price; } for(let book of this.books){ result += book.price; } */ return result; } }, }) </script>
|
4.3 计算属性setter和getter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| <div id="app"> <h2> {{fullName}} </h2> </div> <script> new Vue({ el:'#app', data:{ firstName:'Kobe', lastName:'Bryant' }, computed:{ /* fullName:{ set:function(){}, get:function(){ return this.firstName+' '+this.lastName; } } */ fullName:function(){ return this.firstName+' '+this.lastName; } }, }) </script>
|
4.4 计算属性和methods对比
方法每次调用,程序都会重复执行;计算属性第一次计算出来,结果就保存在内存中。下次再调用,程序不会重复执行。
需要多次调用的计算结果,采用计算属性性能会更低。
4.5 跑马灯项目
一句文字实现,点击按钮,文字滚动播放,再点击文字停止滚动。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script src="./js/vue.js"></script> <div id="app"> <button @click="lang">浪起来</button> <button @click="di">低调</button> <h4>{{msg}}</h4> </div> <script> const app = new Vue({ el:'#app', data: { msg:'猥琐发育。别浪~~!', intervalId:null }, methods:{ lang(){ /* setInterval(function(){ let start = this.msg.substring(0,1); let end = this.msg.substring(1); this.msg=end+start; },400) */ if(this.intervalId!=null) return; this.intervalId = setInterval(()=> { let start = this.msg.substring(0,1); let end = this.msg.substring(1); this.msg=end+start; },400)
}, di(){ clearInterval(this.intervalId); this.intervalId=null; } } }) </script> </body> </html>
|
5: 常用指令
5.1 v-for的四种使用方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <div id="app"> <p v-for="item in list"> {{item}} </p> <p v-for="(item,index) in list"> {{item+"-----"+index}} </p> </div> <script> new Vue({ el:'#app', data:{ list:[1,2,3,4,5] }, }) </script>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <div id="app"> <p v-for="item in list"> {{item.id}}--{{item.name}} </p> </div> <script> new Vue({ el:'#app', data:{ list:[ {id: 1, name :'zs1'}, {id: 2, name :'zs2'}, {id: 3, name :'zs3'}, {id: 4, name :'zs4'}, ] }, }) </script>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <div id="app"> <p v-for="(val,key,index) in user"> {{val}}--{{key}}--{{index}} </p> </div> <script> new Vue({ el:'#app', data:{ user:{ id:1, name:'tuoni', gender:'nan' } }, }) </script>
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| <div id="app"> <p v-for="count in 10"> 第{{count}}次循环 </p> </div> <script> new Vue({ el:'#app', data:{}, }) </script>
|
注意:count从1开始计数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| <div id="app"> <div> <label>Id: <input type="text" v-model="id"> </label> <label>Name: <input type="text" v-model="name"> </label> <button @click="add">添加</button> </div> <p v-for="item in list" :key="item.id"> <input type = "checkbox" > {{item.id}}--{{item.name}} </p> </div> <script> new Vue({ el:'#app', data:{ id:'', name:'', list:[ {id:1,name:'lisi'}, {id:2,name:'yinzheng'}, {id:3,name:'zhaogao'}, {id:4,name:'hanfei'}, {id:5,name:'kongzi'}, ] }, methods:{ add(){ this.list.push({id:this.id,name:this.name}); } } }) </script>
|
5.2 v-on指令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <body> <script src="./js/vue.js"></script> <div id="app"> <button v-on:click="show">按钮</button> </div> <script> const app = new Vue({ el:'#app', data:{ counter:0 }, methods:{ show(){ alert('Hello'); } } }) </script> </body>
|
- 事件修饰符
- .stop 阻止冒泡//@click.stop设置再内部DOM。不会触发@click.stop外部DOM的点击事件
- .prevent 阻止默认行为//@click.prevent。比如阻止a标签跳转到href地址
- .capture 添加事件倾听器实现捕获模式//给外层DOM 添加@click.capture,会先处理外部点击事件。
- .self 只当自身被点击才触发事件//给外部DOM添加@click.self,只有点击外部DOM时才能触发它。也可阻止冒泡
- .once 只触发一次事件处理函数。
事件修饰符可以叠加使用 @click.prevent.once先后顺序无区别。
5.3 v-model
可以实现表单元素的model中的数据双向绑定。v-model只能用在表单元素中,input(redio, text, address, email…),select , checkbox, textarea
1
| <input type="text" v-model="msg">
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| <div id="app"> <input type="text" v-model="n1"> <select v-model="opt"> <option value="+">+</option> <option value="-">-</option> <option value="*">*</option> <option value="/">/</option> </select> <input type="text" v-model="n2"> <button @click="calculate">=</button> <input type="text" v-model="result"> </div> <script> const vm = new Vue({ el:'#app', data:{ n1:0, n2:0, result:0, opt:'+' } methods:{ calculate(){ switch(this.opt){ case '+': this.result = parseInt(this.n1) + parseInt(this.n2); break; case '-': this.result = parseInt(this.n1) - parseInt(this.n2); break; case '*': this.result = parseInt(this.n1) * parseInt(this.n2); break; case '/': this.result = parseInt(this.n1) / parseInt(this.n2); break; } } } }) </script>
|
5.4 v-if和v-show的使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| <body> <script src="./js/vue.js"></script> <div id="app"> <button @click="flag=!flag"> 切换 </button> <h3 v-if="flag"> 这是v-if控制的元素 </h3> <h3 v-show="flag"> 这是v-show控制的元素 </h3> </div> <script> const app = new Vue({ el:'#app', data:{ flag:true }, methods:{ } }) </script> </body>
|
6:过滤器
概念:Vue.js中允许自定义过滤器,可以用作一些常见的文本格式化。过滤器可以用在两个地方:mustache插值和v-bind
1 2 3 4 5 6
| <script> Vue.filter('过滤器名称',function(data){}) </script>
|
注意:当全局和私有过滤器,使用相同名称时,优先调用私有过滤器
6.1 定义全局过滤器
全局过滤器,就是所有的vm实例都能用
过滤器的基本使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| <body> <script src="./js/vue.js"></script> <div id="app"> <p> {{ msg | msgFormat('牛逼') | test}} </p> </div> <script> Vue.filter('msgFormat',function(msg, arg){ return msg.replace(/傻子/g,arg) }) Vue.filter('test',function(msg){ return msg+"这是第二个过滤器" }) const app = new Vue({ el:'#app', data:{ msg:'你是真的傻子哦,人是傻子,脑袋笨' }, methods:{
} })
</script> </body>
|
6.2 定义私有过滤器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <body> <script src="./js/vue.js"></script> <div id="app"> <p> {{ msg | msgFormat('牛逼') | test}} </p> </div> <script> const app = new Vue({ el:'#app', data:{ msg:'你是真的傻子哦,人是傻子,脑袋笨' }, methods:{}, filters:{ msgFormat:function(msg, arg){ return msg.replace(/傻子/g,arg) } } })
</script> </body>
|
7:自定义
7.1 自定义按键修饰符
1 2 3
| <label>Name: <input type="text" v-model="name" @keyup.enter="add"> </label>
|
@keyup:绑定键盘
内置修饰符.enter .tab .delete .esc .space .up .down .left .right
其他的键可使用js定义的键盘码。比如**@keyup.113**表示F12 。
1 2 3 4 5 6 7 8
| <label>Name: <input type="text" v-model="name" @keyup.f12="add"> </label>
<script> Vue.config.keyCode.f12 = 113 </script>
|
7.2 自定义指令
- 定义全局指令
比如自定一个指令v-focus
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <script> Vue.directive('focus',{ bind:function(el){ }, inserted:function(el){ el.focus }, updated:function(){}, }) </script>
|
.focus:JS方法,可以将焦点集中到DOM对象上,类似于,鼠标单击一次输入框。
使用钩子函数参数
- el:指令绑定的元素,用来直接操作DOM
- binding:一个对象,包含以下属性:
- name:指令名称——color
- value:指令的绑定值。会计算比如v-color=”1+1”,binding.value=2
- expression:指令绑定值,不会计算, binding.expression=’1+1’
1 2 3 4 5 6 7 8 9 10
| <div v-color="'red'"> </div> <script> Vue.directive('color',{ bind:function(el,binding){ el.style.color = binding.value } }) </script>
|
- 定义私有指令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <script> const app = new Vue({ el:'#app', data:{ msg:'你是真的傻子哦,人是傻子,脑袋笨' }, methods:{}, filters:{}, directives:{ 'color':{ bind:function(el,binding){ el.style.color = binding.value } } } })
</script>
|
简写:
大多数情况下,旨在bind
和update
钩子上做重复动作,可以简写
1 2 3 4 5 6 7
| <script> directives:{ 'color':function(el,binding){ el.style.color = binding.value } } </script>
|
8:vue-resource实现get,post,jsonp请求
vue-resource依赖于vue,需要在vue.js后导入vue-resource.js包。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| <body> <script src="./js/vue.js"></script> <script src="./js/vue-resource.js"></script> <div> <button @click="getInfo"> getInfo </button> <button @click="postInfo"> getInfo </button> <button @click="jsonpInfo"> getInfo </button> </div> <script> const app = new Vue({ el:'#app', data:{ msg:'你是真的傻子哦,人是傻子,脑袋笨' }, methods:{ getInfo(){ this.$http.get('http://vue.studyit.io/api/getlunbo').then(function(result){ console.log(result.body) }), postInfo(){ this.$http.post('http://vue.studyit.io/api/post',{},{emulateJSON:true}).then(result=>{ console.log(result.body) }), jsonpInfo(){ this.$http.jsonp('http://vue.studyit.io/api/jsonp').then(result=>{ console.log(result.body) }) } } } } }) </script> </body>
|