一、Vue简介
Vue:是最近几年出来的一个开源Javascript框架,语法精简,实现精致,但对浏览器的支持受限,最低只能支持IE9。
Vue.js 是一个用于创建 Web 交互界面的库。它让你通过简单而灵活的 API 创建由数据驱动的 UI 组件。
Vue.js是一款轻量级的、以数据驱动构建web界面的前端JS框架,它在架构设计上采用了MVVM(Model-View-ViewModel)模式,其中ViewModel是Vue.js的核心,它是一个Vue的实例,而这个实例又作用域页面上的某个HTML元素。
其核心在于通过数据驱动界面的更新和展示而非JS中通过操作DOM来改变页面的显示。
上图的DOM Listeners和Data Bindings是数据驱动中实现数据双向绑定的关键,实际的 DOM 封装和输出格式都被抽象为了 Directives 和 Filters; 这也是Vue.js事件驱动的原理所在。
对于View而言,ViewModel中的DOM Listeners工具会帮助我们监听页面上DOM元素的变化,一旦有变化,Model中的数据也会发生改变;
对于Model而言,当我们操纵Model中的数据时,Data Bindings工具会帮助我们更改View中的DOM元素。
此外,页面组件化也是Vue.js的核心,它提供了一种抽象,让我们可以用独立可服用的小组件来构建大型应用。
所以,我们搭建的任何一个界面你可以把其抽象成为一个组件树,充分的去复用它。
二、Vue快速入门
(一)Vue 的创建
一个简单的 Vue 实例只需要四步即可
(二)Vue中常用的指令(Directives)
1、v-model
MVVM模式其自身是实现了数据的双向绑定的,在Vue.js中我们可以通过指令v-model来实现数据双向绑定
在Vue中这被称为指令,指令带有前缀v-表示它们是Vue.js提供的特殊属性。它们会在渲染过的DOM上应用特殊的响应式行为。当然,我们就把这指令当做是特殊的HTML特性(attribute)。
2、v-once:
执行一次性地插值,当数据改变时,插值处的内容不会更新
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div id="app"> <h3>v-once:是不会改变的</h3> <p v-once>原始值:{{msg}}</p> <p>后面的:{{msg}}</p> <input type="text" v-model="msg"> </div> <script src="js/vue.js"></script> <script> let vm = new Vue({ el:'#app', data:{ msg:'你好,世界!' } }); </script> </body> </html>
运行结果: v-model 动态传值给msg 变量了。 加上v-once,变量的值不会改变!!!
3、v-if
条件渲染指令,根据表达式的真假来添加或删除元素。可以接收一个表达式. 不满足条件就注释掉了
其语法结构是:v-if="expression",其中expression是一个返回bool值的表达式,其结果可以是true或false,也可以是返回true或false的表达式。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>04-Vue的常用指令-v-if</title> </head> <body> <div id="app"> <p v-if="show">要显示出来!</p> <p v-if="hide">不要显示出来!</p> <!--v-if可以接收一个表达式.不满足条件可以注释。--> <p v-if="height > 1.55">小明身高:{{height}}m</p> <p v-if="height1 > 1.55">小明身高:{{height1}}m</p> </div> <script src="js/vue.js"></script> <script> //通过数据操控界面 let vm = new Vue({ el:'#app', data:{ show:true, hide:false, //v-if可以接收一个表达式. height:1.68, height1:1.50, } }); </script> </body> </html>
运行结果:
我们也可以打开控制台,做出如下输入,进一步体会数据驱动思想: 在上述案例中,Vue.js进行数据绑定也完全支持JavaScript表达式支持,这些表达式会在Vue实例的数据作用域下作为JavaScript被解析。 {{ number + 1 }} {{ ok ? 'YES' : 'NO' }} {{ message.split('').reverse().join('') }} <div v-bind:id="'list-' + id"></div> 有个限制就是,每个绑定都只能包含单个表达式,以下则不会生效: <!-- 这是语句,不是表达式 --> {{ var a = 1 }} <!-- 流控制也不会生效,请使用三元表达式 --> {{ if (ok) { return message } }}
4、v-show
也是条件渲染指令,不同的是有 v-show 的元素会始终渲染并保持在 DOM 中。是根据表达式之真假值,切换元素的 display CSS 属性
和v-if指令不同点在于:v-show是根据表达式之真假值,切换元素的 display CSS 属性,当条件变化时该指令触发过渡效果。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>05-Vue的常用指令-v-show</title> </head> <body> <div id="app"> <p v-show="show">要显示出来!</p> <p v-show="hide">不要显示出来!</p> <!--v-show可以接收一个表达式.不满足条件则不显示。相当于display:none--> <p v-show="height > 1.55">小明身高:{{height}}m</p> <p v-show="height1 > 1.55">小明身高:{{height1}}m</p> </div> <script src="js/vue.js"></script> <script> //通过数据操控界面 let vm = new Vue({ el:'#app', data:{ show:true, hide:false, //v-show可以接收一个表达式. height:1.68, height1:1.50, } }); </script> </body> </html>
运行结果: v-show 不符合相当于 display:none;
5、v-show和v-if的区别
v-if 是真实的条件渲染,因为它会确保条件块在切换当中适当地销毁与重建条件块内的事件监听器和子组件; v-show 则只是简单地基于 CSS 切换。
v-if 有更高的切换消耗而 v-show 有更高的初始渲染消耗。因此,如果需要频繁切换使用 v-show 较好,如果在运行时条件不大可能改变则使用 v-if 较好。
6、v-else指令
可以用v-else指令为v-if或v-show添加一个“else块”。注意:v-else前一兄弟元素必须有 v-if 或 v-else-if。
代码如下:
(1)v-if和v-else结合
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>06vue-v-else命令</title> </head> <body> <div id="app"> <!--v-else:是不能单独使用的。前面必须加上v-if/v-show.并且必须黏在一起,否则会报错。--> <p v-if="height > 1.70">小明身高:{{height}}m</p> <p v-else>小明身高不足1.70m</p> </div> <script src="js/vue.js"></script> <script> //通过数据操控界面 let vm = new Vue({ el:'#app', data:{ //v-else. height:1.88, } }); </script> </body> </html>
(2)v-else-if 和 v-else 结合
<div id="app"> <p v-if="score >= 80">{{ messg1 }}</p> <p v-else-if="score >= 60" >{{ messg2 }}</p> <p v-else>{{ messg3 }}</p> <input type="text" v-model="score"> </div> <script> new Vue({ el:'#app', data:{ score:80, messg1:'良好', messg2:'及格', messg3:'不及格' } }) </script>
7、v-for指令
基于数据渲染一个列表,类似于JS中的遍历。其数据类型可以是 Array | Object | number | string。
该指令之值,必须使用特定的语法(item, index) in items, 为当前遍历元素提供别名。 v-for的优先级别高于v-if之类的其他指令
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Page Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="../node_modules/bootstrap/dist/css/bootstrap.min.css"> <script src="../node_modules/jquery/dist/jquery.js"></script> <script src="../node_modules/bootstrap/dist/js/bootstrap.js"></script> <script src="../node_modules/vue/dist/vue.js"></script> </head> <body> <!-- v-for 练习 --> <div id="app" style="width: 500px;height: 300px;"> <table class="table table-hover"> <thead> <tr> <th>序号</th> <th>姓名</th> <th>年龄</th> <th>性别</th> </tr> </thead> <tbody> <tr v-for="(item, index) in people"> <td>{{ index + 1}}</td> <td>{{ item.name}}</td> <td>{{ item.age}}</td> <td>{{ item.sex}}</td> </tr> </tbody> </table> </div> <script> new Vue({ el: '#app', data: { people: [ {name:'小强', age:18, sex:'男'}, {name:'小花', age:16, sex:'女'}, {name:'小绿', age:16, sex:'男'}, {name:'小美', age:16, sex:'女'} ] } }) </script> </body> </html>
运行结果:
8、v-text v-html
在标签里插入文本或新的标签元素,原来标签里的内容都不会渲染
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div id="app"> <p>{{msg}}hahaha</p> <!-- v-text:标签里的内容都不会渲染 --> <p v-text="msg">呵呵呵呵</p> <hr> <!-- 字符串标签。 标签里的内容都不会渲染--> <div v-html="html"> 哈哈哈哈 <input type="text"> </div> </div> <script src="js/vue.js"></script> <script> let vm = new Vue({ el:'#app', data:{ msg:'今天天气真好!', html:'<input type="date"><input type="color">' } }); </script> </body> </html>
运行结果:
9、v-bind指令
动态地绑定一个或多个特性,或一个组件 prop 到表达式。v-bind指令可以在其名称后面带一个参数,中间用一个冒号隔开。这个参数通常是HTML元素的特性(attribute),比如:
v-bind:src="imageSrc" 可以缩写: :src="imgaeSrc"
:class="{ red: isRed }" 或 :class="[classA, classB]" ...
:style="{ fontSize: size + 'px' }" 或 :style="[styleObjectA, styleObjectB]" ...
绑定一个有属性的对象,比如:v-bind="{ id: someProp, 'other-attr': otherProp }"
语法结构:v-bind:argument="expression"
因为 Mustache 不能在 HTML 属性中使用,应使用 v-bind 指令,Mustache 是一个 logic-less (轻逻辑)模板解析引擎,它的优势在于可以应用在 Javascript、PHP、Python、Perl 等多种编程语言中。
案例实操:让HTML5学院在各大学院中处于选中状态
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>2.class</title> <style> .active{ background-color:orangered; font-size:20px; color:#fff; } </style> </head> <body> <div id="app"> <p v-for="(college,index) in colleges" :class="index === activeIndex ? 'active' : ''"> {{college}} </p> <p style="color:red">今天的天气很好!</p> <p :style="{color:fontColor}">今天的天气很好!</p> </div> <script src="js/vue.js"></script> <script> let vm = new Vue({ el:'#app', data:{ colleges:[ 'ios学院', 'java学院', 'html5学院', 'ui学院', 've学院' ], activeIndex:0, fontColor:'green', } }); </script> </body> </html>
运行结果:
10、v-on指令
动态地绑定一个或多个特性,或一个组件 prop 到表达式;其作用和v-bind类似。注意:如果用在普通元素上时,只能监听 原生 DOM 事件;但是如果用在自定义元素组件上时,也可以监听子组件触发的自定义事件。
常用的修饰符包括:
.stop - 调用 event.stopPropagation();停止冒泡。
.prevent - 调用 event.preventDefault(); 停止监听原生事件。
.capture - 添加事件侦听器时使用 capture 模式。
.self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
.{keyCode | keyAlias} - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
.once - 触发一次。
使用方法
<!-- 方法处理器 --> <button v-on:click="doThis"></button> <!-- 内联语句 --> <button v-on:click="doThat('hello', $event)"></button> <!-- 缩写 --> <button @click="doThis"></button> <!-- 停止冒泡 --> <button @click.stop="doThis"></button> <!-- 阻止默认行为 --> <button @click.prevent="doThis"></button> <!-- 阻止默认行为,没有表达式 --> <form @submit.prevent></form> <!-- 串联修饰符 --> <button @click.stop.prevent="doThis"></button> <!-- 键修饰符,键别名 --> <input @keyup.enter="onEnter"> <!-- 键修饰符,键代码 --> <input @keyup.13="onEnter"> <!-- the click event will be triggered at most once --> <button v-on:click.once="doThis"></button>
例子:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>v-on</title> </head> <body> <div id="app"> <!-- v-vind:简写冒号。绑定:属性、样式、类 --> <p :style="{color:fontColor}">{{msg}}</p> <button v-on:click="msg='娃哈哈'">改变内容</button> <!-- v-on:简写@ --> <button @click="changeContent()">改变内容1</button> <button @click="changeContentColor()">改变字体颜色</button> </div> <script src="js/vue.js"></script> <script> let vm = new Vue({ el:'#app', data:{ msg:'今天的天气很好!', fontColor:'red' }, methods:{ // 实例所以函数实现 // 钩子函数 changeContent(){ // alert(0); this.msg='测试改掉没有!'; }, changeContentColor(){ this.fontColor = 'green'; } } }); </script> </body> </html>
综合练习:增删小例子
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> #app{ margin:50px auto; width:600px; } fieldset{ border:1px solid orangered; margin-bottom: 20px; } fieldset input{ width:200px; height:30px; margin:10px 0; } table{ width:600px; border:2px solid orangered; text-align:center; } thead{ background:orangered; } </style> </head> <body> <div id="app"> <!-- 第一部分 --> <fieldset> <legend>贝贝学生录入系统</legend> <div> <span>姓名:</span> <input type="text" placeholder="请输入姓名" v-model="newStudent.name"> </div> <div> <span>年龄:</span> <input type="text" placeholder="请输入年龄" v-model="newStudent.age"> </div> <div> <span>性别:</span> <select v-model="newStudent.sex"> <option value="男">男</option> <option value="女">女</option> </select> </div> <div> <span>手机号:</span> <input type="text" placeholder="请输入手机号" v-model="newStudent.phone"> </div> <!-- v-on @ --> <button @click="createNewStudent()">创建新用户</button> </fieldset> <!-- 第二部分 --> <table> <thead> <tr> <td>姓名</td> <td>年龄</td> <td>性别</td> <td>手机号</td> <td>操作</td> </tr> </thead> <tbody> <tr v-for="(p,index) in persons"> <td>{{p.name}}</td> <td>{{p.age}}</td> <td>{{p.sex}}</td> <td>{{p.phone}}</td> <td> <button @click="deleteStudentMsg(index)">删除</button> </td> </tr> </tbody> </table> </div> <script src="js/vue.js"></script> <script> let vm = new Vue({ el:'#app', data:{ persons:[ {name:'张三',age:18,sex:'男',phone:'12345'}, {name:'李四',age:20,sex:'男',phone:'12345'}, {name:'王五',age:23,sex:'女',phone:'12345'}, {name:'赵6',age:30,sex:'男',phone:'12345'} ], newStudent:{name:'',age:0,sex:'男',phone:''}, }, methods:{ // 创建一条新记录 createNewStudent(){ // 姓名不能为空 if(this.newStudent.name === ''){ alert('姓名不能为空!'); return; } // 年龄不能小于0 if(this.newStudent.age <= 0){ alert('请输入正确的年龄!'); return; } // 手机号不能为空 if(this.newStudent.phone === ''){ alert('手机号不能为空!'); return; } // 往数据库添加一条新元素 this.persons.unshift(this.newStudent); // 清空数据 this.newStudent = {name:'',age:0,sex:'男',phone:''}; }, // 删除一条学生记录 deleteStudentMsg(index){ this.persons.splice(index,1) } } }); </script> </body> </html>
运行结果