Vue
一. Vue基础
Vue是一个渐进式JavaScript国产框架。是由尤雨溪创建的。2014年2月Vue正式发布。
官网:https://cn.vuejs.org/
渐进式
声明式渲染—组件系统—客户端路由----集中式状态管理----项目构建
1. 基本使用
<body>
<div id="test">
{{msg}}
</div>
<script type="text/javascript">
var vm = new Vue({
el:'#test',
data:{
msg:'hello world'
}
})
</script>
</body>
参数:
- el: 元素的挂载位置(值可以是CSS选择器或DOM元素)
- data:模型数据(值是一个对象)
差值表达式用法
- 将数据填充到HTML标签中
- 插值表达式支持基本的计算操作
2. 模板语法
前端渲染:指把数据填充到HTML标签中,前端渲染方式:
- 原生js拼接字符串:把数据以字符串的方式拼接到HTML标签中,但不够规范
- 使用 前端模板引擎:引用一套新模板语法规则,比拼接字符串更规范,但缺少事件机制
- 使用Vue特有的模板语法
- 差值表达式
- 指令
- 事件绑定
- 属性绑定
- 样式绑定
- 分支循环结构
3. 指令
指令的本质就是自定义属性,格式以v-开始(如:v-cloak)
-
v-cloak指令
- 差值表达式存在‘闪动’问题,而v-cloak可以解决该问题。
- 解决原理:先通过样式隐藏内容,然后在内存中进行替换,替换好值之后再显示最终的值
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>v-cloak指令</title> <script src="../vue.js"></script> <style> /* 提供样式 */ [v-cloak]{ display: none; } </style> </head> <body> <div id="test"> <!-- 在插值表达式所在标签中添加v-cloak --> <div v-cloak> {{msg}} </div> </div> <script> var vm = new Vue({ el:'#test', data:{ msg:'hello world' } }) </script> </body> </html>
-
数据绑定指令
数据绑定: 指将数据填充到标签中
-
v-text:填充纯文本
没有‘闪动’问题,且比差值表达式更简洁。推荐使用
<div id="test"> <div v-text='msg'></div> </div> <script> var vm = new Vue({ el: '#test', data: { msg: 'hello world' } }) </script>
-
v-html:填充HTML片段
存在安全隐患,在网站上动态渲染HTML是非常危险的,容易导致XSS攻击
使用原则:本站内部数据可以使用,来自第三方的数据不可以用
<div id="test"> <div v-html='msg'></div> </div> <script> var vm = new Vue({ el: '#test', data: { msg: '<h1>hello world</h1>' } }) </script>
-
v-pre:填充原始信息
显示原始信息,跳过编译过程
<div id="test"> <div v-pre> {{msg}} </div> </div> <script> var vm = new Vue({ el: '#test', data: { msg: '<h1>hello world</h1>' } }) </script>
-
-
数据响应式
在html5中的响应式:屏幕尺寸的变化导致样式的变化
数据响应式:数据的变化导致页面内容的变化
-
v-once指令:只编译一次,显示内容之后不再具有响应式功能
<div id="test"> <div v-text='msg'></div> <div v-once> {{msg}} </div> </div> <script> var vm = new Vue({ el: '#test', data: { msg: 'hello world' } }) </script>
如果显示的信息后续不需要修改,可以使用v-once,这样能提高性能
-
-
双向数据绑定
当用户更改页面内容时,数据会变化。当更改数据时,显示页面内容也变化
-
v-model指令:用于双向绑定数据
<div id="test"> <div v-text='msg'></div> <div> <input type="text" v-model='msg'> </div> </div> <script> var vm = new Vue({ el: '#test', data: { msg: 'hello world' } }) </script>
-
MVVM设计思想
- M(model) V(view) VM(View-Model)
- 把不同的业务代码放到不同的模块当中,然后再通过特定的逻辑组织到一起
- 从视图到模型用的是事件监听,从模型到视图用的是事件绑定
-
v-model原理
<div id="cont"> <div v-text='msg'></div> <input type="text" v-bind:value='msg' v-on:input='handel'> <input type="text" v-bind:value='msg' v-on:input='msg=$event.target.value'> <input type="text" v-model='msg'> </div> <script> let vm = new Vue({ el: '#cont', data: { msg: 'hello' }, methods: { handel: function (event) { this.msg = event.target.value; } } }) </script>
-
4. 事件绑定
-
v-on指令:可以绑定标准事件
<div id="test"> <div v-text='num'></div> <div> <button v-on:click='num++'>点击加1</button> <button @click='num--'>点击减1</button> <button @click='add'>点击加1</button> <button @click='add()'>点击加1</button> </div> </div> <script> var vm = new Vue({ el: '#test', data: { num:0 }, methods:{ add:function(){ // 这里的this指vm this.num++ } } }) </script>
v-on两种语法:
<button v-on:click=''></button>
<button @click=''></button>
-
事件函数:
提供了methods来添加事件函数,值为一个对象,可以储存多个事件
- 事件函数的调用
- 直接绑定函数名:
<button @click='add'></button>
- 默认携带事件对象
- 调用函数:
<button @click='add()'></button>
- 如果要传递参数只能用此方式
- 直接绑定函数名:
<div id="test"> <div v-text='msg'></div> <div> <button @click="pt('hello','world',$event)">按钮一</button> <button @click='pt2'>按钮二</button> </div> </div> <script> /* 如果事件直接绑定事件名称,会默认传递事件对象作为第一个参数 如果事件绑定函数调用,事件对象必须作为最后一个对象显示传递,且事件对象的名称必须是$event */ var vm = new Vue({ el: '#test', data: { msg: '' }, methods: { pt:function(x,y,event){ this.msg = x + y console.log(event.target.innerHTML) }, pt2:function(event){ console.log(event.target.innerHTML) } } }) </script>
- 事件函数的调用
-
事件修饰符
名称 描述 .stop
阻止冒泡 .prevent
阻止默认行为 .capture
添加事件侦听器时使用 capture 模式 .self
只当事件是从侦听器绑定的元素本身触发时才触发回调 .{keyCode|keyAlias}
只当事件是从特定键触发时才触发回调 .native
监听组件根元素的原生事件 .once
只触发一次回调 .left
(2.2.0)只当点击鼠标左键时触发 .right
(2.2.0)只当点击鼠标右键时触发 .middle
(2.2.0) 只当点击鼠标中键时触发 .passive
(2.3.0) 以 { passive: true }
模式添加侦听器<div id="test"> <div v-text='msg'></div> <div @click='pt2'> <button @click.stop="pt">按钮</button> <a href="www.baidu.com" @click.prevent.stop>百度</a> </div> </div> <script> var vm = new Vue({ el: '#test', data: { msg: '' }, methods: { pt: function (event) {}, pt2: function (event) { this.msg = 'helloworld' } } }) </script>
使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。
用
v-on:click.prevent.self
会阻止所有的点击,而v-on:click.self.prevent
只会阻止对元素自身的点击。 -
按键修饰符
.enter
: 回车键.delete
: 删除键.tab
.esc
.space
.up
.down
.left
.right
<div id="test"> 用户名: <input type="text" v-model='uname' @keyup.delete='clear'> 密码: <input type="text" v-model='pwd' @keyup.enter='handleSubmit'> <button @click='handleSubmit'>提交</button> </div> <script> var vm = new Vue({ el: '#test', data: { uname: '', pwd:'' }, methods: { handleSubmit: function () { console.log(this.uname,this.pwd) }, clear:function(){ this.uname = ''; } } }) </script>
-
自定义按键修饰符
Vue提供了
Config.keyCodes
对象进行自定义按键修饰符Vue.config.keyCodes.自定义名称 = 112
- 这里的112是键盘上按键的唯一标识符, 通过keyCode可以获取到
<div id="test"> <div v-text = 'msg'></div> <input type="text" @keyup='Submit'> </div> <script> var vm = new Vue({ el: '#test', data: { msg:'显示' }, methods: { Submit: function (event) { this.msg = `按键: ${event.key} 按键唯一标识: ${event.keyCode}` } } }) </script>
5. 属性绑定
-
v-bind指令: 动态处理属性
<div id="cont"> <a v-bind:href='url' v-text='msg'></a> <a :href='url' v-text='msg'></a> <button @click='center'>切换</button> </div> <script> let vm = new Vue({ el:'#cont', data:{ url:'www.baidu.com', msg:'百度' }, methods:{ center:function(){ this.url = 'www.tx.com', this.msg = '腾讯' } } }) </script>
- v-bind指令语法:
<a v-bind:href="url"></a>
- 简写
<a :href="url"></a>
6. 样式绑定
-
class样式处理
-
对象语法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="../vue.js"></script> <style> .active{ border: 2px solid aqua; width: 100px; height: 100px; } .back{ background-color: gray; } </style> </head> <body> <div id="cont"> <div v-bind:class="{active: isActive,back: isColor}">样式测试</div> <button @click='down'>切换</button> </div> <script> let vm = new Vue({ el: '#cont', data: { isActive: true, isColor:true }, methods: { down: function () { // 取反 !this.isActive; this.isActive = !this.isActive; this.isColor = !this.isColor; } } }) </script> </body> </html>
通过v-bind给class添加样式,添加多个中间用逗号隔开
-
数组语法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="../vue.js"></script> <style> .active { border: 2px solid aqua; width: 100px; height: 100px; } .back { background-color: gray; } </style> </head> <body> <div id="cont"> <div :class='[activeClass, handleClass]'></div> <button @click='down'>切换</button> </div> <script> let vm = new Vue({ el: '#cont', data: { activeClass: 'active', handleClass: 'back' }, methods: { down: function () { this.activeClass = ''; this.handleClass = ''; } } }) </script> </body> </html>
-
样式绑定相关细节
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="../vue.js"></script> <style> .active { border: 2px solid aqua; width: 100px; height: 100px; } .back { background-color: gray; } .color{ color: red; } .base{ font-size: 28px; } </style> </head> <body> <div id="cont"> <div :class='[activeClass, handleClass, {color: isTest }]'>样式测试</div> <div :class='arrClasses'>样式测试</div> <div :class='objClasses'>样式测试</div> <div class="base" :class='arrClasses'>样式测试</div> <button @click='down'>切换</button> </div> <script> let vm = new Vue({ el: '#cont', data: { activeClass: 'active', handleClass: 'back', isTest: true, arrClasses:['active','back'], objClasses:{ active: true, back: true } }, methods: { down: function () { // 取反 !this.isActive; this.isTest = !this.isTest; this.objClasses.back = false; } } }) </script> </body> </html>
- 对象绑定和数组绑定可以结合使用
- class绑定的值可以简化操作
- 默认的class会保留
-
-
style样式处理
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="../vue.js"></script> </head> <body> <div id="cont"> <div v-bind:style='{border: borderStyle, width: widthSytle, height: heightStyle}'></div> <div v-bind:style='objStyles'></div> <div v-bind:style='[objStyles,overrideStyles]'></div> <button @click='down'>切换</button> </div> <script> let vm = new Vue({ el: '#cont', data: { borderStyle: '1px solid aqua', widthSytle: '100px', heightStyle: '200px', objStyles: { border:'1px solid black', width: '200px', height:'100px' }, overrideStyles:{ background: 'gray' } }, methods: { down: function () { this.heightStyle = '100px'; this.objStyles.width = '100px'; } } }) </script> </body> </html>
7. 分支循环结构
-
分支结构
v-if
、v-else
、v-else-if
、v-show
<div id="main"> <div v-if='score>=90'>优秀</div> <div v-else-if='score < 90 && score >= 80'>良好</div> <div v-else-if='score < 80 && score >= 60'>一般</div> <div v-else>差</div> <div v-show='flag'>测试v-show</div> <button @click='cent'>切换</button> </div> <script> let vm = new Vue({ el:'#main', data:{ score:'50', flag:true }, methods:{ cent:function(){ this.flag = !this.flag } } }) </script>
- v-fi控制元素是否渲染到页面
- v-show控制元素是否显示(已经渲染到页面)
-
循环结构
- v-for遍历数组:
<div id="main"> <div>水果列表</div> <ul> <li v-for='item in fruits'>{{item}}</li> <li v-for='(item,index) in fruits'>{{item + '---' + index}}</li> <li :key='item.id' v-for='item in myFruits'> <span>{{item.ename}}</span> <span>{{item.cname}}</span> </li> </ul> </div> <script> let vm = new Vue({ el: '#main', data: { fruits:['apple','banana','orange'], myFruits:[{ id:1, ename:'apple', cname:'苹果' }, { id: 2, ename: 'orange', cname: '橘子' }, { id: 3, ename: 'banana', cname: '香蕉' } ] } }) </script>
- key的作用是帮Vue区分不同的元素,从而提高性能。在开发时最好加上
-
v-for结合v-if
<div id="main"> <div>水果列表</div> <ul> <li v-if='value == 12' v-for='(value,key,index) in obj'>{{value + '---' + key + '---' + index}}</li> </ul> </div> <script> let vm = new Vue({ el: '#main', data: { obj:{ name:'zhansan', age:12, code:456 } } }) </script>