一.Vue概述
Vue:渐进式JavaScript框架
官网:https://cn.vuejs.org/
二. Vue基本使用
2.1 传统开发模式对比
这是原生js
<div id="msg"></div>
<script type="text/javascript">
var msg = 'Hello World';
var div = document.getElementById('msg');
div.innerHTML = msg;
</script>
这是JQuery
<div id="msg"></div>
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript">
var msg = 'Hello World';
$('#msg').html(msg);
</script>
2.2 Vue.js之HelloVue基本步骤
<div id="app">
<h1>{{msg}}</h1>
<!-- 插值表达式支持基本的计算操作 -->
<h2>{{1+3}}</h2>
<h2>{{msg +"----"+user}}</h2>
</div>
<script src="./js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
msg: 'Hello Vue',
user: '我是小龙人多多指教'
}
});
</script>
2.3 Vue.js之HelloVue细节分析
1.实例参数分析
- el: 元素的挂载位置(值可以是CSS选择器或者DOM元素)
- data:模型数据(值是一个对象)
2.插值表达式用法: {{ }}
- 将数据填充到HTML标签中
- 插值表达式支持基本的计算操作
3.Vue代码运行原理分析
三. Vue模板语法
3.1 模板语法概述
1.如何理解前端渲染?
就是把数据填充到HTML标签中
2. 前端渲染方式
- 原生js拼接字符串
- 使用前端模板引擎
- 使用vue特有的模板语法
3. 原生js拼接字符串
基本上就是将数据以字符串的方式拼接到HTML标 签中,前端代码风格大体上如下列代码所示。
var d = data.weather;
var info = document.getElementById('info');
info.innerHTML = '';
for (var i = 0; i < d.length; i++) {
var date = d[i].date;
var day = d[i].info.day;
var night = d[i].info.night;
var tag = '';
tag += '<span>日期:' + date + '</sapn><ul>';
tag += '<li> 白 天 天 气 :' + day[1] + '</li>'
tag += '<li> 白 天 温 度 :' + day[2] + '</li>'
tag += '<li> 白 天 风 向 :' + day[3] + '</li>'
tag += '<li> 白 天 风 速 :' + day[4] + '</li>'
tag += '</ul>';
var div = document.createElement('div');
div.innerHTML = tag;
info.appendChild(div);
};
缺点:不同开发人员的代码风格差别很大,随着业 务的复杂,后期的维护变得逐渐困难起来。
4. 使用前端模板引擎
下方代码是基于模板引擎art-template的一段代 码,与拼接字符串相比,代码明显规范了很多, 它拥有自己的一套模板语法规则。
<script id="abc" type="text/html">
{{if isAdmin}}
<h1>{{title}}</h1>
<ul>
{{each list as value i}}
<li>索引 {{i + 1}} :{{value}}</li>
{{/each}}
</ul>
{{/if}}
</script>
优点:大家都遵循同样的规则写代码,代码可读性 明显提高了,方便后期的维护。
缺点:没有专门提供事件机制。
5.模板语法概览
- 差值表达式
- 指令
- 事件绑定
- 属性绑定
- 样式绑定
- 分支循环结构
3.2 指令
1.什么是指令?
- 什么是自定义属性
- 指令的本质就是自定义属性
- 指令的格式:以v-开始(比如:v-cloak)
2.v-cloak指令用法
- 插值表达式存在的问题:“闪动”,页面刷新时页面中元素会显示 {{ }};
- 如何解决该问题:使用v-cloak指令
- 解决该问题的原理:先隐藏,在内存中替换好值之后再显示最终的值
3.数据绑定指令
-
v-text 填充纯文本
① 相比插值表达式更加简洁
-
v-html 填充HTML片段
① 存在安全问题
② 本网站内部数据可以使用,来自第三方的数据不可以用
-
v-pre 填充原始信息
① 显示原始信息,跳过编译过程(分析编译过程)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HelloVue</title>
<style>
[v-cloak] {
display: none;
}
</style>
</head>
<body>
<div id="app">
<div v-cloak>{{msg}}</div>
<div v-text="msg"></div>
<div v-html="msgplus"></div>
<div v-pre>{{msg}}</div>
</div>
<script src="./js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
msg: 'Hello Vue',
msgplus: '<h1>Hello Vue</h1>',
}
});
</script>
</body>
</html>
运行结果:
4.数据响应式
-
如何理解响应式
① html5中的响应式(屏幕尺寸的变化导致样式的变化)
② 数据的响应式(数据的变化导致页面内容的变化)
-
什么是数据绑定
① 数据绑定:将数据填充到标签中
-
v-once 只编译一次
① 显示内容之后不再具有响应式功能
用法:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>HelloVue</title> <style> [v-cloak] { display: none; } </style> </head> <body> <div id="app"> <div v-cloak>{{msg}}</div> <div v-once>{{user}}</div> </div> <script src="./js/vue.js"></script> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { msg: 'Hello Vue', user: '我是小龙人多多指教' } }); </script> </body> </html>
3.3 双向数据绑定指令
1. 什么是双向数据绑定?
2. 双向数据绑定分析
v-model指令用法:
<input type='text' v-model='uname'/>
3. MVVM设计思想
① M(model)
② V(view)
③ VM(View-Model)
3.4 事件绑定
1. Vue如何处理事件?
-
v-on指令用法
<button v-on:click="num++">点击</button>
-
v-on简写形式
<button @click="num++">点击</button>
2. 事件函数的调用方式
-
直接绑定函数名称
<button v-on:click="addnum">点击</button>
-
调用函数
<button v-on:click="addnum()">点击</button>
3. 事件函数参数传递
-
普通参数和事件对象
<button v-on:click='say("hi",$event)'>Say hi</button>
<div id="app"> <button v-on:click="addnum1">点击</button> <button v-on:click="addnum2(111,999,$event)">点击1</button> </div> <script src="./js/vue.js"></script> <script type="text/javascript"> // 事件绑定-参数传递 // 1. 如果事件直接绑定函数名称,那么默认会传递事件对象作为事件函数的第一个参数。 // 2. 如果事件绑定函数调用,那么事件对象必须作为最后一个参数显示传递,并且事件对象的名称必须是$event var vm = new Vue({ el: "#app", methods: { addnum1: function(event) { // 这里的 this 是 Vue 的实例对象 console.log(event.target.innerHTML); }, addnum2: function(p1, p2, event) { console.log(p1, p2); console.log(event.target.innerHTML); } } }) </script>
4.事件修饰符
- .stop 阻止冒泡
<a v-on:click.stop="handle">跳转</a>
-
.prevent 阻止默认行为
<a v-on:click.prevent="handle">跳转</a>
<div id="app"> <h1>{{num}}</h1> <div v-on:click="addnum0"> <button v-on:click.stop="addnum1">点击</button> </div> <div> <a href="https://www.baidu.com" v-on:click.prevent="addnum2">百度</a> </div> </div> <script src="./js/vue.js"></script> <script type="text/javascript"> var vm = new Vue({ el: "#app", data: { num: 0, }, methods: { addnum0: function() { // 这里的 this 是 Vue 的实例对象 this.num++; }, addnum1: function() { // 冒泡事件 // 传统阻止冒泡事件 // event.stopPropagation(); }, addnum2: function() { // 阻止默认行为 // event.preventDefault(); } } }) </script>
5.按键修饰符
- .enter 回车键
<input v-on:keyup.enter='submit'>
-
.delete (捕获“删除”和“退格”键)
<input v-on:keyup.delete='handle'>
<div id="app"> <form> <div> <input type="text" v-model='uname' v-on:keyup.delete='clearContent'> </div> <div> <input type="text" v-model='password' v-on:keyup.enter='handleSubmit'> </div> <div> <input type="button" value="提交" v-on:click='handleSubmit'> </div> </form> </div> <script src="./js/vue.js"></script> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { uname: '', password: '', }, methods: { clearContent: function() { this.uname = ''; }, handleSubmit: function() { console.log(this.uname, this.password); } } }) </script>
6.自定义按键修饰符
- 全局 config.keyCodes 对象
Vue.config.keyCodes.f1 = 112
<div id="app">
<input type="text" v-on:keyup.aaa='handle' v-model='info'>
</div>
<script src="./js/vue.js"></script>
<script type="text/javascript">
Vue.config.keyCodes.aaa = 65;
var vm = new Vue({
el: '#app',
data: {
info: '',
},
methods: {
handle: function(event) {
console.log(event.keyCode);
},
}
})
</script>
3.5 属性绑定
1. Vue如何动态处理属性?
-
v-bind指令用法
<a v-bind:href='url'>跳转</a>
-
缩写形式
<a :href='url'>跳转</a>
2. v-model的低层实现原理分析
<input v-bind:value="msg" v-on:input="msg=$event.target.value">
<div id="app">
<h1>{{msg}}</h1>
<input type="text" v-bind:value='msg' v-on:input='handle'>
</div>
<script src="./js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
msg: 'Hello',
},
methods: {
handle: function(event) {
// 使用输入域中的最新数据覆盖原来的数据
this.msg = event.target.value;
}
}
})
</script>
3.6 样式绑定
1. class样式处理
-
对象语法
<div v-bind:class="{ active: isActive }"></div>
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>样式处理</title> <style> .active { width: 100px; height: 100px; border: 2px solid skyblue; } .bgc { background-color: pink; } </style> </head> <body> <div id="app"> <div v-bind:class="{active:isactive,bgc:isbgc}"></div> <button v-on:click='change'>切换</button> </div> <script src="./js/vue.js"></script> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { isactive: true, isbgc: true }, methods: { change: function() { this.isactive = !this.isactive; this.isbgc = !this.isbgc; } } }) </script> </body> </html>
-
数组语法
<div v-bind:class="[activeClass, errorClass]"></div>
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>样式处理</title> <style> .active { width: 100px; height: 100px; border: 2px solid skyblue; } .bgc { background-color: pink; } </style> </head> <body> <div id="app"> <div v-bind:class="[activeClass,bgcClass]">段仙子最帅!</div> <button v-on:click='change'>切换</button> </div> <script src="./js/vue.js"></script> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { activeClass: 'active', bgcClass: 'bgc', }, methods: { change: function() { this.activeClass = ''; this.bgcClass = ''; } } }) </script> </body> </html>
-
对象数组结合用法
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>样式处理</title> <style> .active { width: 100px; height: 100px; border: 2px solid skyblue; } .bgc { background-color: pink; } .fsize { font-size: 20px; } </style> </head> <body> <div id="app"> <div v-bind:class="[activeClass,bgcClass]">段仙子最帅!</div> <div v-bind:class="[activeClass,bgcClass,{fsize:isFsize}]">段仙子最帅!</div> <div v-bind:class="[activeClass,bgcClass,{fsize:isFsize}]"></div> <div v-bind:class="arrClass"></div> <div v-bind:class="objClass"></div> <div class="fsize" v-bind:class="objClass"></div> <button v-on:click='change'>切换</button> </div> <script src="./js/vue.js"></script> <script type="text/javascript"> // 样式绑定相关语法细节: // 1. 对象绑定和数组绑定可以结合使用。 // 2. class 绑定的值可以简化操作。 // 3. 默认的 class 会保留。 var vm = new Vue({ el: '#app', data: { activeClass: 'active', bgcClass: 'bgc', isFsize: true, arrClass: ['active', 'bgc'], objClass: { active: true, bgc: true } }, methods: { change: function() { this.isFsize = !this.isFsize; } } }) </script> </body> </html>
2. style样式处理
-
对象语法
<div v-bind:style="{ color: activeColor, fontSize: fontSize }"></div>
-
数组语法
<div v-bind:style="[baseStyles, overridingStyles]"></div>
-
结合用法:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div id="app"> <div v-bind:style='{border: borderStyle, width: widthStyle, height: heightStyle}'></div> <div v-bind:style='objStyles'></div> <div v-bind:style='[objStyles, overrideStyles]'></div> <button v-on:click='handle'>切换</button> </div> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript"> // 样式绑定之内联样式Style: var vm = new Vue({ el: '#app', data: { borderStyle: '1px solid blue', widthStyle: '100px', heightStyle: '200px', objStyles: { border: '1px solid green', width: '200px', height: '100px' }, overrideStyles: { border: '5px solid orange', backgroundColor: 'blue' } }, methods: { handle: function() { this.heightStyle = '100px'; this.objStyles.width = '100px'; } } }); </script> </body> </html>
3.7 分支循环结构
1.分支结构
- v-if
- v-else
- v-else-if
- v-show
2.v-if与v-show的区别
-
v-if控制元素是否渲染到页面
-
v-show控制元素是否显示(已经渲染到了页面)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>循环分支结构</title> </head> <body> <div id="app"> <div v-if="score>=90">优秀</div> <div v-else-if="score<90 && score>=80">良好</div> <div v-else-if="score<80 && score>=70">中等</div> <div v-else-if="score<70 && score>=60">差</div> <div v-else-if="score<60">不及格</div> <!-- v-show原理:控制元素是否显示 display:none --> <div v-show="flage">段晓龙超级帅!</div> <button v-on:click="handle">点击</button> <!-- 如果频繁的让一个元素显示或隐藏,这时候用 v-show 如果元素渲染到页面不经常变化,这时候用 v-if 元素的增加和减少开销较元素的样式渲染开销较大。 --> </div> <script src="./js/vue.js"></script> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { score: 99, flage: false, }, methods: { handle: function() { this.flage = !this.flage } } }) </script> </body> </html>
3. 循环结构
-
v-for遍历数组
<li v-for='item in list'>{{item}}</li>
<li v-for='(item,index) in list'>{{item}} + '---' +{{index}}</li>
-
key的作用:帮助Vue区分不同的元素,从而提高性能
<li :key='item.id' v-for='(item,index) in list'>{{item}} + '---' {{index}}</li>
-
案例
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>循环结构</title> </head> <body> <div id="app"> <ul> <li v-for='item in fruits'>{{item}}</li> <li v-for='(item,index) in fruits'>{{item + '----' +index}}</li> <li v-for='item in myFruits'> <span>{{item.ename}}</span> <span>{{item.cname}}</span> </li> <li :key='item.id' v-for='item in myFruits'> <span>{{item.ename}}</span> <span>{{item.cname}}</span> </li> </ul> </div> <script src="./js/vue.js"></script> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { fruits: ['apple', 'orange', 'banana'], myFruits: [{ id: 1, ename: 'apple', cname: '苹果' }, { id: 2, ename: 'orange', cname: '桔子' }, { id: 3, ename: 'banana', cname: '香蕉' }] } }) </script> </body> </html>
4. 循环结构
-
v-for遍历对象
<div v-for='(value, key, index) in object'></div>
-
v-if和v-for结合使用
<div v-if='value==12' v-for='(value, key, index) in object'></div>
-
案例:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>条件判断与循环</title> </head> <body> <div id="app"> <div v-for='(value,key,index) in obj'>{{value + '----'+ key + '----'+index}}</div> <div v-if='value==18' v-for='(value,key,index) in obj'>{{value + '----'+ key + '----'+index}}</div> </div> <script src="./js/vue.js"></script> <script type="text/javascript"> // 原生 js var obj = { uname: 'duanxx', age: 12, gender: 'male' }; for (var key in obj) { console.log(key, obj[key]); }; // vue.js var vm = new Vue({ el: '#app', data: { obj: { uname: 'xiaolr', age: 18, gender: 'male' } } }) </script> </body> </html>
3.8 Tab栏切换
案例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
.tab ul {
overflow: hidden;
padding: 0;
margin: 0;
}
.tab ul li {
box-sizing: border-box;
padding: 0;
float: left;
width: 100px;
height: 45px;
line-height: 45px;
list-style: none;
text-align: center;
border-top: 1px solid blue;
border-right: 1px solid blue;
cursor: pointer
}
.tab ul li:first-child {
border-left: 1px solid blue;
}
.tab ul li.active {
background-color: orange;
}
.tab div {
width: 500px;
height: 300px;
display: none;
text-align: center;
font-size: 30px;
line-height: 300px;
border: 1px solid blue;
border-top: 0px;
}
.tab div.current {
display: block;
}
</style>
</head>
<body>
<div id="app">
<div class="tab">
<ul>
<li v-on:click='change(index)' :class='currentIndex==index?"active":""' :key='item.id' v-for='(item,index) in list'>{{item.title}}</li>
</ul>
<div :class='currentIndex==index?"current":""' :key='item.id' v-for='(item, index) in list'>
<img :src="item.path">
</div>
</div>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
/*
*/
var vm = new Vue({
el: '#app',
data: {
currentIndex: 0, // 选项卡当前的索引
list: [{
id: 1,
title: 'apple',
path: 'img/apple.png'
}, {
id: 2,
title: 'orange',
path: 'img/orange.png'
}, {
id: 3,
title: 'lemon',
path: 'img/lemon.png'
}]
},
methods: {
change: function(index) {
// 在这里实现选项卡切换操作:本质就是操作类名
// 如何操作类名?就是通过currentIndex
this.currentIndex = index;
}
}
});
</script>
</body>
</html>