文章目录
- 教程
- 安装
- 起步
- 模板语法
- 插值
- 指令
- 用户输入
- 过滤器
- 缩写
- 条件语句
- 循环语句
- 计算属性
- 监听属性
- 样式绑定
- 事件处理器
- 表单
- 组件
- 组件 - 自定义事件
- 自定义指令
- 钩子
- 路由( vue-router )
- 过渡 & 动画
- 过渡
- Ajax(axios)
- 安装方法:
- GET 方法
- POST 方法
- 执行多个并发请求
- axios API
- 响应接口
- 实例
- 导航菜单
- 编辑文本
- 订单列表
- 搜索页面
- 切换不同布局
教程
本教程主要介绍了 Vue2.x 版本的使用
第一个实例:
<body> <div id="app"> <p>{{ message }}</p> </div> <script> new Vue({ el: '#app', data: { message: 'Hello Vue.js!' } }) </script> </body>
复制
安装
- 使用 CDN 方法
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
<script src="https://cdn.staticfile.org/vue/2.7.0/vue.min.js"></script>
起步
每个 Vue 应用都需要通过实例化 Vue 来实现。
语法格式如下:
var vm = new Vue({ // 选项 })
复制
接下来让我们通过实例来看下 Vue 构造器中需要哪些内容:
<div id="vue_det"> <h1>site : {{site}}</h1> <h1>url : {{url}}</h1> <h1>{{details()}}</h1> </div> <script type="text/javascript"> var vm = new Vue({ el: '#vue_det', data: { site: "菜鸟教程", url: "www.runoob.com", alexa: "10000" }, methods: { details: function() { return this.site + " - 学的不仅是技术,更是梦想!"; } } }) </script>
复制
在 Vue 构造器中有一个el
参数,它是 DOM 元素中的id
。在上面实例中 id 为 vue_det
,在 div 元素中:<div id = "vue_det"></div>
。
这意味着我们接下来的改动全部在以上指定的 div 内,div 外部不受影响。
接下来我们看看如何定义数据对象。
data 用于定义属性,实例中有三个属性分别为:site、url、alexa。
methods 用于定义的函数,可以通过 return 来返回函数值。
{{ }} 用于输出对象属性和函数返回值。
当一个 Vue 实例被创建时,它向 Vue 的响应式系统中加入了其 data 对象中能找到的所有的属性。当这些属性的值发生改变时,html 视图将也会产生相应的变化。
<div id="vue_det"> <h1>site : {{site}}</h1> <h1>url : {{url}}</h1> <h1>Alexa : {{alexa}}</h1> </div> <script type="text/javascript"> // 我们的数据对象 var data = { site: "菜鸟教程", url: "www.runoob.com", alexa: 10000} var vm = new Vue({ el: '#vue_det', data: data }) // 它们引用相同的对象! document.write(vm.site === data.site) // true document.write("<br>") // 设置属性也会影响到原始数据 vm.site = "Runoob" document.write(data.site + "<br>") // Runoob // ……反之亦然 data.alexa = 1234 document.write(vm.alexa) // 1234 </script>
复制
模板语法
插值
- 文本
数据绑定最常见的形式就是使用{{...}}
(双大括号)的文本插值:
<div id="app"> <p>{{ message }}</p> </div> <script> new Vue({ el: '#app', data: { message: 'Hello Vue.js!' } }) </script>
复制
- HTML
使用v-html
指令用于输出html
代码:
<div id="app"> <div v-html="message"></div> </div> <script> new Vue({ el: '#app', data: { message: '<h1>菜鸟教程</h1>' } }) </script>
复制
- 属性
HTML
属性中的值应使用v-bind
指令。
以下实例判断use
的值,如果为true
使用class1
类的样式,否则不使用该类:
<style> .class1{ background: #444; color: #eee; } </style> <body> <script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script> <div id="app"> <label for="r1">修改颜色</label><input type="checkbox" v-model="use" id="r1"> <br><br> <div v-bind:class="{'class1': use}"> v-bind:class 指令 </div> </div> <script> new Vue({ el: '#app', data:{ use: false } }); </script> </body>
复制
- 表达式
<div id="app"> {{5+5}}<br> {{ ok ? 'YES' : 'NO' }}<br> {{ message.split('').reverse().join('') }} <div v-bind:id="'list-' + id">菜鸟教程</div> </div> <script> new Vue({ el: '#app', data: { ok: true, message: 'RUNOOB', id : 1 } }) </script>
复制
指令
指令是带有 v- 前缀的特殊属性。
指令用于在表达式的值改变时,将某些行为应用到 DOM 上。
如下例子:
<div id="app"> <p v-if="seen">现在你看到我了</p> <template v-if="ok"> <h1>菜鸟教程</h1> <p>学的不仅是技术,更是梦想!</p> <p>哈哈哈,打字辛苦啊!!!</p> </template> </div> <script> new Vue({ el: '#app', data: { seen: true, ok: true } }) </script>
复制
这里, v-if 指令将根据表达式 seen 的值(true 或 false )来决定是否插入 p 元素。
- 参数
参数在指令后以冒号指明。例如,v-bind
指令被用来响应地更新HTML
属性:
<div id="app"> <pre><a v-bind:href="url">菜鸟教程</a></pre> </div> <script> new Vue({ el: '#app', data: { url: 'http://www.runoob.com' } }) </script>
复制
在这里href
是参数,告知v-bind
指令将该元素的href
属性与表达式url
的值绑定。
另一个例子是v-on
指令,它用于监听 DOM 事件:
<a v-on:click="doSomething">
在这里参数是监听的事件名。
- 修饰符
修饰符是以半角句号.
指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。例如,.prevent
修饰符告诉v-on
指令对于触发的事件调用event.preventDefault()
:
<form v-on:submit.prevent="onSubmit"></form>
用户输入
- 在
input
输入框中我们可以使用v-model
指令来实现双向数据绑定:
<div id="app"> <p>{{ message }}</p> <input v-model="message"> </div> <script> new Vue({ el: '#app', data: { message: 'Runoob!' } }) </script>
复制
v-model
指令用来在input
、select
、textarea
、checkbox
、radio
等表单控件元素上创建双向数据绑定,根据表单上的值,自动更新绑定的元素的值。
按钮的事件我们可以使用v-on
监听事件,并对用户的输入进行响应。
以下实例在用户点击按钮后对字符串进行反转操作:
<div id="app"> <p>{{ message }}</p> <button v-on:click="reverseMessage">反转字符串</button> </div> <script> new Vue({ el: '#app', data: { message: 'Runoob!' }, methods: { reverseMessage: function () { this.message = this.message.split('').reverse().join('') } } }) </script>
复制
过滤器
Vue.js 允许你自定义过滤器,被用作一些常见的文本格式化。
由"管道符"指示, 格式如下:
<!-- 在两个大括号中 --> {{ message | capitalize }} <!-- 在 v-bind 指令中 --> <div v-bind:id="rawId | formatId"></div>
复制
以下实例对输入的字符串第一个字母转为大写:
<div id="app"> {{ message | capitalize }} </div> <script> new Vue({ el: '#app', data: { message: 'runoob' }, filters: { capitalize: function (value) { if (!value) return '' value = value.toString() return value.charAt(0).toUpperCase() + value.slice(1) } } }) </script>
复制
缩写
Vue.js 为两个最为常用的指令提供了特别的缩写:
<!-- 完整语法 --> <a v-bind:href="url"></a> <!-- 缩写 --> <a :href="url"></a> <!-- 完整语法 --> <a v-on:click="doSomething"></a> <!-- 缩写 --> <a @click="doSomething"></a>
复制
条件语句
<div id="app"> <div v-if="type === 'A'"> A </div> <div v-else-if="type === 'B'"> B </div> <div v-else-if="type === 'C'"> C </div> <div v-else> Not A/B/C </div> </div> <script> new Vue({ el: '#app', data: { type: 'C' } }) </script>
复制
循环语句
v-for 指令需要以 site in sites 形式的特殊语法, sites 是源数据数组并且 site 是数组元素迭代的别名。
v-for 可以绑定数据到数组来渲染一个列表:
<div id="app"> <ol> <li v-for="site in sites"> {{ site.name }} </li> </ol> </div> <script> new Vue({ el: '#app', data: { sites: [ { name: 'Runoob' }, { name: 'Google' }, { name: 'Taobao' } ] } }) </script>
复制
v-for 迭代对象
v-for 可以通过一个对象的属性来迭代数据:
<div id="app"> <ul> <li v-for="(value, key, index) in object"> {{ index }}. {{ key }} : {{ value }} </li> </ul> </div> <script> new Vue({ el: '#app', data: { object: { name: '菜鸟教程', url: 'http://www.runoob.com', slogan: '学的不仅是技术,更是梦想!' } } }) </script>
复制
计算属性
计算属性关键词: computed。
计算属性在处理一些复杂逻辑时是很有用的。
可以看下以下反转字符串的例子:
<div id="app"> <p>原始字符串: {{ message }}</p> <p>计算后反转字符串: {{ reversedMessage }}</p> </div> <script> var vm = new Vue({ el: '#app', data: { message: 'Runoob!' }, computed: { // 计算属性的 getter reversedMessage: function () { // `this` 指向 vm 实例 return this.message.split('').reverse().join('') } } }) </script>
复制
实例中声明了一个计算属性reversedMessage
。
提供的函数将用作属性vm.reversedMessage
的getter
。
vm.reversedMessage
依赖于vm.message
,在vm.message
发生改变时,vm.reversedMessage
也会更新。
computed vs methods
我们可以使用methods
来替代computed
,效果上两个都是一样的,但是computed
是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值。而使用methods
,在重新渲染的时候,函数总会重新调用执行。
<div id="app"> <p>原始字符串: {{ message }}</p> <p>计算后反转字符串: {{ reversedMessage }}</p> <p>使用方法后反转字符串: {{ reversedMessage2() }}</p> </div> <script> var vm = new Vue({ el: '#app', data: { message: 'Runoob!' }, computed: { // 计算属性的 getter reversedMessage: function () { // `this` 指向 vm 实例 return this.message.split('').reverse().join('') } }, methods: { reversedMessage2: function () { return this.message.split('').reverse().join('') } } }) </script>
复制
可以说使用computed
性能会更好,但是如果你不希望缓存,你可以使用methods
属性。
监听属性
本章节,我们将为大家介绍Vue.js
监听属性watch
,我们可以通过watch
来响应数据的变化。
以下实例通过使用watch
实现计数器:
<div id = "app"> <p style = "font-size:25px;">计数器: {{ counter }}</p> <button @click = "counter++" style = "font-size:25px;">点我</button> </div> <script type = "text/javascript"> var vm = new Vue({ el: '#app', data: { counter: 1 } }); vm.$watch('counter', function(nval, oval) { alert('计数器值的变化 :' + oval + ' 变为 ' + nval + '!'); }); </script>
复制
以下实例进行千米与米之间的换算:
<div id = "computed_props"> 千米 : <input type = "text" v-model = "kilometers"> 米 : <input type = "text" v-model = "meters"> </div> <p id="info"></p> <script type = "text/javascript"> var vm = new Vue({ el: '#computed_props', data: { kilometers : 0, meters:0 }, methods: { }, computed :{ }, watch : { kilometers:function(val) { this.kilometers = val; this.meters = this.kilometers * 1000 }, meters : function (val) { this.kilometers = val/ 1000; this.meters = val; } } }); // $watch 是一个实例方法 vm.$watch('kilometers', function (newValue, oldValue) { // 这个回调将在 vm.kilometers 改变后调用 document.getElementById ("info").innerHTML = "修改前值为: " + oldValue + ",修改后值为: " + newValue; }) </script>
复制
以上代码中我们创建了两个输入框,data
属性中,kilometers
和meters
初始值都为0
。watch
对象创建了data
对象的两个监控方法:kilometers
和meters
。
当我们在输入框输入数据时,watch
会实时监听数据变化并改变自身的值。
把$watch
实例方法删掉后,千米和米的数据依然会改变,只是少了最下面的那行字
样式绑定
class
与style
是HTML
元素的属性,用于设置元素的样式,我们可以用v-bind
来设置样式属性。
class
属性绑定
我们可以为v-bind:class
设置一个对象,从而动态的切换class
:
实例中将isActive
设置为true
显示了一个绿色的div
块,如果设置为false
则不显示:
实例1:
<style> .active { width: 100px; height: 100px; background: green; } </style> </head> <body> <div id="app"> <div v-bind:class="{ 'active': isActive }"></div> </div> <script> new Vue({ el: '#app', data: { isActive: true } }) </script>
复制
以上实例div class
为:
<div class="active"></div>
我们也可以在对象中传入更多属性用来动态切换多个class
。
实例2:
text-danger
类背景颜色覆盖了active
类的背景色:
<style> .active { width: 100px; height: 100px; background: green; } .text-danger { background: red; } </style> </head> <body> <div id="app"> <div class="static" v-bind:class="{ 'active': isActive, 'text-danger': hasError }"> </div> </div> <script> new Vue({ el: '#app', data: { isActive: true, hasError: true } }) </script>
复制
以上实例div class
为:
<div class="static active text-danger"></div>
我们也可以直接绑定数据里的一个对象:
实例3:
text-danger 类背景颜色覆盖了 active 类的背景色:
<div id="app"> <div v-bind:class="classObject"></div> </div> <script> new Vue({ el: '#app', data: { classObject: { active: true, 'text-danger': true } } }) </script>
复制
实例 3 与 实例 2 的渲染结果是一样的。
此外,我们也可以在这里绑定返回对象的计算属性。这是一个常用且强大的模式:
实例4:
new Vue({ el: '#app', data: { isActive: true, error: { value: true, type: 'fatal' } }, computed: { classObject: function () { return { base: true, active: this.isActive && !this.error.value, 'text-danger': this.error.value && this.error.type === 'fatal', } } } })
复制
我们可以把一个数组传给 v-bind:class ,实例如下:
实例 5
<div v-bind:class="[activeClass, errorClass]"></div>
以上实例 div class 为:
<div class="active text-danger"></div>
Vue.js style(内联样式)
我们可以在v-bind:style
直接设置样式:
<div id="app"> <div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }">菜鸟教程</div> </div> <script> new Vue({ el: '#app', data: { activeColor: 'green', fontSize: 30 } }) </script>
复制
以上实例 div style 为:
<div style="color: green; font-size: 30px;">菜鸟教程</div>
也可以直接绑定到一个样式对象,让模板更清晰:
<div id="app"> <div v-bind:style="styleObject">菜鸟教程</div> </div> <script> new Vue({ el: '#app', data: { styleObject: { color: 'green', fontSize: '30px' } } }) </script>
复制
v-bind:style
可以使用数组将多个样式对象应用到一个元素上:
<body> <div id="app"> <div v-bind:style="[baseStyles, overridingStyles]">菜鸟教程</div> </div> <script> new Vue({ el: '#app', data: { baseStyles: { color: 'green', fontSize: '30px' }, overridingStyles: { 'font-weight': 'bold' } } }) </script> </body>
复制
事件处理器
事件监听可以使用v-on
指令:
<div id="app"> <button v-on:click="counter += 1">增加 1</button> <p>这个按钮被点击了 {{ counter }} 次。</p> </div> <script> new Vue({ el: '#app', data: { counter: 0 } }) </script>
复制
通常情况下,我们需要使用一个方法来调用JavaScript
方法。
v-on
可以接收一个定义的方法来调用。
<div id="app"> <!-- `greet` 是在下面定义的方法名 --> <button v-on:click="greet">Greet</button> </div> <script> var app = new Vue({ el: '#app', data: { name: 'Vue.js' }, // 在 `methods` 对象中定义方法 methods: { greet: function (event) { // `this` 在方法里指当前 Vue 实例 alert('Hello ' + this.name + '!') // `event` 是原生 DOM 事件 if (event) { alert(event.target.tagName) } } } }) // 也可以用 JavaScript 直接调用方法 app.greet() // -> 'Hello Vue.js!' </script>
复制
用 JavaScript 直接调用方法
用 v-on 调用方法,点击显示
if(event){alert (event.target.tagName)}
除了直接绑定到一个方法,也可以用内联JavaScript
语句:
<div id="app"> <button v-on:click="say('hi')">Say hi</button> <button v-on:click="say('what')">Say what</button> </div> <script> new Vue({ el: '#app', methods: { say: function (message) { alert(message) } } }) </script>
复制
事件修饰符
Vue.js 为 v-on 提供了事件修饰符来处理 DOM 事件细节,如:event.preventDefault() 或 event.stopPropagation()。
Vue.js 通过由点.
表示的指令后缀来调用修饰符。
按键修饰符
Vue 允许为 v-on 在监听键盘事件时添加按键修饰符:
<!-- 只有在 keyCode 是 13 时调用 vm.submit() --> <input v-on:keyup.13="submit">
复制
表单
你可以用 v-model 指令在表单控件元素上创建双向数据绑定。
v-model 会根据控件类型自动选取正确的方法来更新元素。
实例中演示了 input 和 textarea 元素中使用 v-model 实现双向数据绑定:
<div id="app"> <p>input 元素:</p> <input v-model="message" placeholder="编辑我……"> <p>消息是: {{ message }}</p> <p>textarea 元素:</p> <p style="white-space: pre">{{ message2 }}</p> <textarea v-model="message2" placeholder="多行文本输入……"></textarea> </div> <script> new Vue({ el: '#app', data: { message: 'Runoob', message2: '菜鸟教程\r\nhttp://www.runoob.com' } }) </script>
复制
复选框
复选框如果是一个为逻辑值,如果是多个则绑定到同一个数组:
以下实例中演示了复选框的双向数据绑定:
<div id="app"> <p>单个复选框:</p> <input type="checkbox" id="checkbox" v-model="checked"> <label for="checkbox">{{ checked }}</label> <p>多个复选框:</p> <input type="checkbox" id="runoob" value="Runoob" v-model="checkedNames"> <label for="runoob">Runoob</label> <input type="checkbox" id="google" value="Google" v-model="checkedNames"> <label for="google">Google</label> <input type="checkbox" id="taobao" value="Taobao" v-model="checkedNames"> <label for="taobao">taobao</label> <br> <span>选择的值为: {{ checkedNames }}</span> </div> <script> new Vue({ el: '#app', data: { checked : false, checkedNames: [] } }) </script>
复制
单选按钮
以下实例中演示了单选按钮的双向数据绑定:
<div id="app"> <input type="radio" id="runoob" value="Runoob" v-model="picked"> <label for="runoob">Runoob</label> <br> <input type="radio" id="google" value="Google" v-model="picked"> <label for="google">Google</label> <br> <span>选中值为: {{ picked }}</span> </div> <script> new Vue({ el: '#app', data: { picked : 'Runoob' } }) </script>
复制
select 列表
以下实例中演示了下拉列表的双向数据绑定:
<div id="app"> <select v-model="selected" name="fruit"> <option value="">选择一个网站</option> <option value="www.runoob.com">Runoob</option> <option value="www.google.com">Google</option> </select> <div id="output"> 选择的网站是: {{selected}} </div> </div> <script> new Vue({ el: '#app', data: { selected: '' } }) </script>
复制
组件
组件(Component)是 Vue.js 最强大的功能之一。
组件可以扩展 HTML 元素,封装可重用的代码。
组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:
注册一个全局组件语法格式如下:
Vue.component(tagName, options)
tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件:
<tagName></tagName>
全局组件
所有实例都能用全局组件。
注册一个简单的全局组件 runoob,并使用它:
<div id="app"> <runoob></runoob> </div> <script> // 注册 Vue.component('runoob', { template: '<h1>自定义组件!</h1>' }) // 创建根实例 new Vue({ el: '#app' }) </script>
复制
局部组件
我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:
注册一个简单的局部组件 runoob,并使用它:
<div id="app"> <runoob></runoob> </div> <script> var Child = { template: '<h1>自定义组件!</h1>' } // 创建根实例 new Vue({ el: '#app', components: { // <runoob> 将只在父模板可用 'runoob': Child } }) </script>
复制
Prop
prop 是子组件用来接受父组件传递过来的数据的一个自定义属性。
父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 “prop”:
<div id="app"> <child message="hello!"></child> </div> <script> // 注册 Vue.component('child', { // 声明 props props: ['message'], // 同样也可以在 vm 实例中像 "this.message" 这样使用 template: '<span>{{ message }}</span>' }) // 创建根实例 new Vue({ el: '#app' }) </script>
复制
动态 Prop
类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:
<div id="app"> <div> <input v-model="parentMsg"> <br> <child v-bind:message="parentMsg"></child> </div> </div> <script> // 注册 Vue.component('child', { // 声明 props props: ['message'], // 同样也可以在 vm 实例中像 "this.message" 这样使用 template: '<span>{{ message }}</span>' }) // 创建根实例 new Vue({ el: '#app', data: { parentMsg: '父组件内容' } }) </script>
复制
以下实例中使用 v-bind 指令将 todo 传到每一个重复的组件中:
<div id="app"> <ol> <todo-item v-for="item in sites" v-bind:todo="item"></todo-item> </ol> </div> <script> Vue.component('todo-item', { props: ['todo'], template: '<li>{{ todo.text }}</li>' }) new Vue({ el: '#app', data: { sites: [ { text: 'Runoob' }, { text: 'Google' }, { text: 'Taobao' } ] } }) </script>
复制
注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
Prop 验证
组件可以为 props 指定验证要求。
为了定制 prop 的验证方式,你可以为 props 中的值提供一个带有验证需求的对象,而不是一个字符串数组。
组件 - 自定义事件
父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
- 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。
<div id="app"> <div id="counter-event-example"> <p>{{ total }}</p> <button-counter v-on:increment="incrementTotal"></button-counter> <button-counter v-on:increment="incrementTotal"></button-counter> </div> </div> <script> Vue.component('button-counter', { template: '<button v-on:click="incrementHandler">{{ counter }}</button>', data: function () { return { counter: 0 } }, methods: { incrementHandler: function () { this.counter += 1 this.$emit('increment') } }, }) new Vue({ el: '#counter-event-example', data: { total: 0 }, methods: { incrementTotal: function () { this.total += 1 } } }) </script>
复制
data 必须是一个函数
上面例子中,可以看到 button-counter 组件中的 data 不是一个对象,而是一个函数:
data: function () { return { count: 0 } }
复制
这样的好处就是每个实例可以维护一份被返回对象的独立的拷贝,如果 data 是一个对象则会影响到其他实例:
<div id="components-demo3" class="demo"> <button-counter2></button-counter2> <button-counter2></button-counter2> <button-counter2></button-counter2> </div> <script> var buttonCounter2Data = { count: 0 } Vue.component('button-counter2', { data: function () { // data 选项是一个对象,会影响到其他实例 return buttonCounter2Data }, template: '<button v-on:click="count++">点击了 {{ count }} 次。</button>' }) new Vue({ el: '#components-demo3' }) </script>
复制
自定义组件的 v-model
组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件。
<input v-model="parentData">
等价于:
<input :value="parentData" @input="parentData = $event.target.value" >
复制
以下实例自定义组件 runoob-input,父组件的 num 的初始值是 100,更改子组件的值能实时更新父组件的 num:
<div id="app"> <runoob-input v-model="num"></runoob-input> <p>输入的数字为:{{num}}</p> </div> <script> Vue.component('runoob-input', { template: ` <p> <!-- 包含了名为 input 的事件 --> <input ref="input" :value="value" @input="$emit('input', $event.target.value)" > </p> `, props: ['value'], // 名为 value 的 prop }) new Vue({ el: '#app', data: { num: 100, } }) </script>
复制
由于 v-model 默认传的是 value,不是 checked,所以对于复选框或者单选框的组件时,我们需要使用 model 选项,model 选项可以指定当前的事件类型和传入的 props。
<div id="app"> <base-checkbox v-model="lovingVue"></base-checkbox> <div v-show="lovingVue"> 如果选择框打勾我就会显示。 </div> </div> <script> // 注册 Vue.component('base-checkbox', { model: { prop: 'checked', event: 'change' // onchange 事件 }, props: { checked: Boolean }, template: ` <input type="checkbox" v-bind:checked="checked" v-on:change="$emit('change', $event.target.checked)" > ` }) // 创建根实例 new Vue({ el: '#app', data: { lovingVue: true } }) </script>
复制
自定义指令
除了默认设置的核心指令( v-model 和 v-show ), Vue 也允许注册自定义指令。
下面我们注册一个全局指令 v-focus, 该指令的功能是在页面加载时,元素获得焦点:
<div id="app"> <p>页面载入时,input 元素自动获取焦点:</p> <input v-focus> </div> <script> // 注册一个全局自定义指令 v-focus Vue.directive('focus', { // 当绑定元素插入到 DOM 中。 inserted: function (el) { // 聚焦元素 el.focus() } }) // 创建根实例 new Vue({ el: '#app' }) </script>
复制
我们也可以在实例使用 directives 选项来注册局部指令,这样指令只能在这个实例中使用:
<div id="app"> <p>页面载入时,input 元素自动获取焦点:</p> <input v-focus> </div> <script> // 创建根实例 new Vue({ el: '#app', directives: { // 注册一个局部的自定义指令 v-focus focus: { // 指令的定义 inserted: function (el) { // 聚焦元素 el.focus() } } } }) </script>
复制
钩子
钩子函数
指令定义函数提供了几个钩子函数(可选):
-
bind: 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。
-
inserted: 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。
-
update: 被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新(详细的钩子函数参数见下)。
-
componentUpdated: 被绑定元素所在模板完成一次更新周期时调用。
-
unbind: 只调用一次, 指令与元素解绑时调用。
钩子函数的参数
- el: 指令所绑定的元素,可以用来直接操作 DOM 。
- binding: 一个对象,包含以下属性:
- name: 指令名,不包括 v- 前缀。
- value: 指令的绑定值, 例如: v-my-directive=“1 + 1”, value 的值是 2。
- oldValue: 指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
- expression: 绑定值的表达式或变量名。 例如 v-my-directive=“1 + 1” , expression 的值是 “1 + 1”。
- arg: 传给指令的参数。例如 v-my-directive:foo, arg 的值是 “foo”。
- modifiers: 一个包含修饰符的对象。 例如: v-my-directive.foo.bar, 修饰符对象 modifiers 的值是 { foo: true, bar: true }。
- vnode: Vue 编译生成的虚拟节点。
- oldVnode: 上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
以下实例演示了这些参数的使用:
<div id="app" v-runoob:hello.a.b="message"> </div> <script> Vue.directive('runoob', { bind: function (el, binding, vnode) { var s = JSON.stringify el.innerHTML = 'name: ' + s(binding.name) + '<br>' + 'value: ' + s(binding.value) + '<br>' + 'expression: ' + s(binding.expression) + '<br>' + 'argument: ' + s(binding.arg) + '<br>' + 'modifiers: ' + s(binding.modifiers) + '<br>' + 'vnode keys: ' + Object.keys(vnode).join(', ') } }) new Vue({ el: '#app', data: { message: '菜鸟教程!' } }) </script>
复制
有时候我们不需要其他钩子函数,我们可以简写函数,如下格式:
Vue.directive('runoob', function (el, binding) { // 设置指令的背景颜色 el.style.backgroundColor = binding.value.color })
复制
指令函数可接受所有合法的 JavaScript 表达式,以下实例传入了 JavaScript 对象:
<div id="app"> <div v-runoob="{ color: 'green', text: '菜鸟教程!' }"></div> </div> <script> Vue.directive('runoob', function (el, binding) { // 简写方式设置文本及背景颜色 el.innerHTML = binding.value.text el.style.backgroundColor = binding.value.color }) new Vue({ el: '#app' }) </script>
复制
路由( vue-router )
Vue.js 路由允许我们通过不同的 URL 访问不同的内容。
通过 Vue.js 可以实现多视图的单页Web应用(single page web application,SPA)。
安装
1、直接下载 / CDN
https://unpkg.com/vue-router/dist/vue-router.js
2、NPM
推荐使用淘宝镜像:cnpm install vue-router
简单实例
Vue.js + vue-router 可以很简单的实现单页应用。
<router-link>
是一个组件,该组件用于设置一个导航链接,切换不同 HTML 内容。 to 属性为目标地址, 即要显示的内容。
以下实例中我们将 vue-router 加进来,然后配置组件和路由映射,再告诉 vue-router 在哪里渲染它们。代码如下所示:
<div id="app"> <h1>Hello App!</h1> <p> <!-- 使用 router-link 组件来导航. --> <!-- 通过传入 `to` 属性指定链接. --> <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 --> <router-link to="/foo">Go to Foo</router-link> <router-link to="/bar">Go to Bar</router-link> </p> <!-- 路由出口 --> <!-- 路由匹配到的组件将渲染在这里 --> <router-view></router-view> </div> <script> // 0. 如果使用模块化机制编程,導入Vue和VueRouter,要调用 Vue.use(VueRouter) // 1. 定义(路由)组件。 // 可以从其他文件 import 进来 const Foo = { template: '<div>foo</div>' } const Bar = { template: '<div>bar</div>' } // 2. 定义路由 // 每个路由应该映射一个组件。 其中"component" 可以是 // 通过 Vue.extend() 创建的组件构造器, // 或者,只是一个组件配置对象。 // 我们晚点再讨论嵌套路由。 const routes = [ { path: '/foo', component: Foo }, { path: '/bar', component: Bar } ] // 3. 创建 router 实例,然后传 `routes` 配置 // 你还可以传别的配置参数, 不过先这么简单着吧。 const router = new VueRouter({ routes // (缩写)相当于 routes: routes }) // 4. 创建和挂载根实例。 // 记得要通过 router 配置参数注入路由, // 从而让整个应用都有路由功能 const app = new Vue({ router }).$mount('#app') // 现在,应用已经启动了! </script>
复制
<router-link>
相关属性
to
表示目标路由的链接。 当被点击后,内部会立刻把 to 的值传到 router.push(),所以这个值可以是一个字符串或者是描述目标位置的对象。
过渡 & 动画
过渡
Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。
Vue 提供了内置的过渡封装组件,该组件用于包裹要实现过渡效果的组件。
语法格式
<transition name = "nameoftransition"> <div></div> </transition>
复制
我们可以通过以下实例来理解 Vue 的过渡是如何实现的:
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script> <style> /* 可以设置不同的进入和离开动画 */ /* 设置持续时间和动画函数 */ .fade-enter-active, .fade-leave-active { transition: opacity 2s } .fade-enter, .fade-leave-to /* .fade-leave-active, 2.1.8 版本以下 */ { opacity: 0 } </style> </head> <body> <div id = "databinding"> <button v-on:click = "show = !show">点我</button> <transition name = "fade"> <p v-show = "show" v-bind:style = "styleobj">动画实例</p> </transition> </div> <script type = "text/javascript"> var vm = new Vue({ el: '#databinding', data: { show:true, styleobj :{ fontSize:'30px', color:'red' } }, methods : { } }); </script> </body>
复制
Ajax(axios)
Vue.js 2.0 版本推荐使用 axios 来完成 ajax 请求。
Axios 是一个基于 Promise 的 HTTP 库,可以用在浏览器和 node.js 中。
安装方法:
使用 cdn:
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
使用 npm:
npm install axios
GET 方法
我们可以简单的读取 JSON 数据:
<div id="app"> {{ info }} </div> <script type = "text/javascript"> new Vue({ el: '#app', data () { return { info: null } }, mounted () { axios .get('https://www.runoob.com/try/ajax/json_demo.json') .then(response => (this.info = response)) .catch(function (error) { // 请求失败处理 console.log(error); }); } }) </script>
复制
使用 response.data 读取 JSON 数据:
<div id="app"> <h1>网站列表</h1> <div v-for="site in info" > {{ site.name }} </div> </div> <script type = "text/javascript"> new Vue({ el: '#app', data () { return { info: null } }, mounted () { axios .get('https://www.runoob.com/try/ajax/json_demo.json') .then(response => (this.info = response.data.sites)) .catch(function (error) { // 请求失败处理 console.log(error); }); } }) </script>
复制
GET 方法传递参数格式如下:
// 直接在 URL 上添加参数 ID=12345 axios.get('/user?ID=12345') .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); }); // 也可以通过 params 设置参数: axios.get('/user', { params: { ID: 12345 } }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); });
复制
POST 方法
<div id="app"> {{ info }} </div> <script type = "text/javascript"> new Vue({ el: '#app', data () { return { info: null } }, mounted () { axios .post('/try/ajax/demo_axios_post.php') .then(response => (this.info = response)) .catch(function (error) { // 请求失败处理 console.log(error); }); } }) </script>
复制
POST 方法传递参数格式如下:
axios.post('/user', { firstName: 'Fred', // 参数 firstName lastName: 'Flintstone' // 参数 lastName }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); });
复制
执行多个并发请求
function getUserAccount() { return axios.get('/user/12345'); } function getUserPermissions() { return axios.get('/user/12345/permissions'); } axios.all([getUserAccount(), getUserPermissions()]) .then(axios.spread(function (acct, perms) { // 两个请求现在都执行完成 }));
复制
axios API
可以通过向 axios 传递相关配置来创建请求。
axios(config) // 发送 POST 请求 axios({ method: 'post', url: '/user/12345', data: { firstName: 'Fred', lastName: 'Flintstone' } }); // GET 请求远程图片 axios({ method:'get', url:'https://static.runoob.com/images/runoob-logo.png', responseType:'stream' }) .then(function(response) { response.data.pipe(fs.createWriteStream('ada_lovelace.jpg')) }); axios(url[, config]) // 发送 GET 请求(默认的方法) axios('/user/12345');
复制
响应接口
Vue 可以添加数据动态响应接口。
例如以下实例,我们通过使用$watch
属性来实现数据的监听,$watch
必须添加在 Vue 实例之外才能实现正确的响应。
实例中通过点击按钮计数器会加 1。setTimeout 设置 10 秒后计算器的值加上 20 。
<div id = "app"> <p style = "font-size:25px;">计数器: {{ counter }}</p> <button @click = "counter++" style = "font-size:25px;">点我</button> </div> <script type = "text/javascript"> var vm = new Vue({ el: '#app', data: { counter: 1 } }); vm.$watch('counter', function(nval, oval) { alert('计数器值的变化 :' + oval + ' 变为 ' + nval + '!'); }); setTimeout( function(){ vm.counter += 20; },10000 ); </script>
复制
10秒后,计数器的值+20
点击一下,计数器的值+1
如果将
vm.$watch('counter', function(nval, oval) { alert('计数器值的变化 :' + oval + ' 变为 ' + nval + '!'); });
复制
去掉,数值依然会变化,但每次变化时,不会弹出alert。
实例
本章节为大家介绍几个 Vue.js 实例,通过实例练习来巩固学到的知识点。
导航菜单
<div id="main"> <!-- 激活的菜单样式为 active 类 --> <!-- 为了阻止链接在点击时跳转,我们使用了 "prevent" 修饰符 (preventDefault 的简称)。 --> <nav v-bind:class="active" v-on:click.prevent> <!-- 当菜单上的链接被点击时,我们调用了 makeActive 方法, 该方法在 Vue 实例中创建。 --> <a href="#" class="home" v-on:click="makeActive('home')">Home</a> <a href="#" class="projects" v-on:click="makeActive('projects')">Projects</a> <a href="#" class="services" v-on:click="makeActive('services')">Services</a> <a href="#" class="contact" v-on:click="makeActive('contact')">Contact</a> </nav> <!-- 以下 "active" 变量会根据当前选中的值来自动变换 --> <p>您选择了 <b>{{active}} 菜单</b></p> </div> <script> // 创建一个新的 Vue 实例 var demo = new Vue({ // DOM 元素,挂载视图模型 el: '#main', // 定义属性,并设置初始值 data: { active: 'home' }, // 点击菜单使用的函数 methods: { makeActive: function(item){ // 模型改变,视图会自动更新 this.active = item; } } }); </script>
复制