文章目录
- 教程
- 安装
- 起步
- 模板语法
- 插值
- 指令
- 用户输入
- 过滤器
- 缩写
- 条件语句
- 循环语句
- 计算属性
- 监听属性
- 样式绑定
- 事件处理器
- 表单
- 组件
- 组件 - 自定义事件
- 自定义指令
- 钩子
- 路由( 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>