1.起步
创建一个html,然后通过如下方式引入 Vue:
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
或
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
1.1 HelloWorld
<div id="app">
<p>{{ msg }}</p><!-- {{}}插值表达式-->
</div>
<script type="text/javascript">
var vm = new Vue({
el:'#app',
data:{
msg:'Hello Vue!'
}
})
</script>
以上就成功创建了第一个Vue应用!Vue将数据和DOM之间建立了关联,所有东西都是响应式的。打开控制台修改msg的值,你将看到上例相应地更新。
除了文本插值,我们还可以像这样来绑定元素特性:
<div id="app-2">
<span v-bind:title="message">
鼠标悬停几秒钟查看此处动态绑定的提示信息!
</span>
</div>
<script type="text/javascript">
var app2 = new Vue({
el: '#app-2',
data: {
message: '页面加载于 ' + new Date().toLocaleString()
}
})
</script>
v-bind特性被称为指令。指令带有前缀 v-以表示它们是 Vue 提供的特殊特性。该指令的意思是:“将这个元素节点的 title 特性和 Vue 实例的 message属性保持一致”。
v-text与v-cloak:
<style>
[v-cloak]{
display: none;
}
</style>
<div id="app">
<p v-cloak>{{ msg }}</p>
</div>
var vm = new Vue({
el:'#app',
data:{
msg:'Hello World'
}
})
使用v-cloak时当网速较慢时不会将插值表达式{{ msg }}显示出来,只有当加载完毕时才会渲染到页面上,且使用v-cloak时可以在插值表达式两侧写其他内容并且会显示到页面上
<div id="app">
<p v-cloak></p>
</div>
结果为:
左边-------- Hello World 右边+++++++++++
但是如果使用v-text则不需要写样式,直接绑定即可解决问题,但是标签中不能写任何内容,否则会被覆盖
<div id="app">
<p v-text="msg"></p>
<p v-text="msg">Hello World</p>
</div>
如上其中第一个p标签和第二个p标签显示的内容是一样的Hello World并不会被显示出来
v-text和插值表达式共同点是:
其内容都会被当做文本来解析,即使内容是html格式
如果想把内容当作html来解析则使用v-html,同样v-html标签体中的内容也不会显示
<div id="app">
<div v-html="msg">哈哈哈哈哈哈</div>
</div>
var vm = new Vue({
el:'#app',
data:{
msg:'<h1>这是一个大大的H1</h1>'
}
})
1.2条件循环v-if与v-for
条件:
控制元素是否显示:
<div id="app-3">
<p v-if="seen">现在你看到我了</p>
</div>
<script type="text/javascript">
var app3 = new Vue({
el: '#app-3',
data: {
seen: true
}
})
</script>
当seen为true时会将p标签显示出来,为false时之前显示的消息消失了。
v-show与v-if功能一样可以控制隐藏与显示,但是不同点是v-if每次都会重新删除或者创建元素,而v-show则不会每次都进行DOM的删除和创建操作只是添加了display:none样式
v-if有较高的切换性能消耗
v-show有较高的初始化渲染消耗
如果元素涉及到频繁的切换,最好不要使用v-if,如果元素可能永远也不会被显示出来被用户看到则推荐使用v-if
循环:
v-for 指令可以绑定数组的数据来渲染一个项目列表:
<div id="app-4">
<ol>
<li v-for="todo in todos">
{{ todo.text }}
</li>
<!-- 也可以获得序号-->
<li v-for="(todo,i) in todos">
索引值:{{i}}--->元素:{{ todo.text }}
</li>
</ol>
</div>
var app4 = new Vue({
el: '#app-4',
data: {
todos: [
{ text: '学习 JavaScript' },
{ text: '学习 Vue' },
{ text: '整个牛项目' }
]
}
})
可以看到:
1. 学习 JavaScript
2. 学习 Vue
3. 整个牛项目
在控制台里,输入 app4.todos.push({ text: ‘新项目’ }),你会发现列表最后添加了一个新项目。
v-for遍历对象
<div id="app-4">
<p v-for="(value,key) in user">
{{key}}:{{value}}
</p>
</div>
<script type="text/javascript">
var app4 = new Vue({
el: '#app-4',
data: {
user:{
id:'1',
name:'zhangsan',
sex:'男',
age:'18'
}
}
})
</script>
运行结果:
id:1
name:zhangsan
sex:男
age:18
在遍历对象的键值对时除了 value ,key在第三个位置还有一个索引
v-for="(value,key,index) in user"
v-for迭代数字
<div id="app-4">
<p v-for="count in 10">
这是第 {{count}} 次循环
</p>
</div>
count迭代从1开始
v-for中key的使用
使用key来强制数据关联
<div id="app-4">
<label>id:<input type="text" v-model="id"/></label>
<label>name:<input type="text"v-model="name"/></label>
<button type="button" @click="add">添加</button>
<!-- 注意:v-for循环的时候,key属性只能使用number获取string-->
<!-- 注意:key在使用的时候,必须使用v-bind属性绑定的形式指定key的值 -->
<p v-for="item in list" :key="item.id">
<input type="checkbox"/>{{item.id}}-{{item.name}}
</p>
</div>
<script type="text/javascript">
var app4 = new Vue({
el: '#app-4',
data: {
list:[
{id:1, name:'赵高'},
{id:2, name:'嬴政'},
{id:3, name:'李斯'},
{id:4, name:'荀子'}
]
},
methods:{
add: function(){//添加方法
this.list.push({id:this.id, name: this.name});
}
}
})
</script>
1.3数据绑定v-bind
<div id="app-2">
<span v-bind:title="message">
鼠标悬停几秒钟查看此处动态绑定的提示信息!
</span>
</div>
var app2 = new Vue({
el: '#app-2',
data: {
message: '页面加载于 ' + new Date().toLocaleString()
}
})
v-bind是vue中提供的用于绑定属性的指令,v-bind可以简写为:要绑定的属性,v-bind中还可以写合法js表达式如:
<div id="app-2">
<span v-bind:title="message + 'hellod world'">
鼠标悬停几秒钟查看此处动态绑定的提示信息!
</span>
</div>
1.4事件绑定v-on
为了让用户和你的应用进行交互,我们可以用 v-on 指令添加一个事件监听器,通过它调用在 Vue 实例中定义的方法:
<div id="app">
<p>{{ message }}</p>
<button v-on:click="reverseMessage">逆转消息</button>
</div>
var app5 = new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!'
},
methods: {
reverseMessage: function () {
this.message = this.message.split('').reverse().join('')
}
}
})
注意reverseMessage方法中,我们不用直接操作DOM即可更新状态
除了v-on:click,v-on事件可以绑定:mouseenter 、mouseleave等事件
v-on事件缩写:@事件名
事件修饰符:
.stop阻止冒泡
.prevent阻止默认事件
.capture添加事件侦听器使用事件捕获模式
.self只当事件在该事件本身(比如不是子元素)触发时触发回调
.once事件只触发一次
1.5事件修饰符案例
<div id="app">
<div class="innder" @click="divhandler">
<button type="button" @click="btnhandler">戳他</button>
</div>
</div>
var vm = new Vue({
el:'#app',
data:{
},
methods:{
divhandler:function(){
console.log('这是触发了inner div的点击事件')
},
btnhandler:function(){
console.log('这是触发了 btn 按钮的点击事件')
}
}
})
运行结果:(冒泡机制限制性当前的事件再往外冒)
这是触发了 btn 按钮的点击事件
事件修饰符.html:29 这是触发了inner div的点击事件
如果想要阻止冒泡则在@click上加.stop:
<div id="app">
<div class="innder" @click="divhandler">
<button type="button" @click.stop="btnhandler">戳他</button>
</div>
</div>
执行结果(阻止了事件向外冒泡):
这是触发了 btn 按钮的点击事件
阻止默认行为.prevent
<div id="app">
<a href="www.baidu.com" @click="linkClick">点我到百度</a>
</div>
如上点击会跳转到百度,如果想阻止a标签的默认跳转事件则:
//创建vue实例得到ViewModel
var vm = new Vue({
el:'#app',
data:{
},
methods:{
linkClick:function(){
alert("弹出");
}
}
})
1.6简单案例:跑马灯效果
<div id="app">
<input type="button" value="浪起来" @click="lang"/>
<input type="button" value="低调"@click="stop"/>
<h4>{{ message }}</h4>
</div>
<script type="text/javascript">
var vm = new Vue({
el:'#app',
data:{
message:'猥琐发育,别浪!',
intervalId:null//在data上定义定时器id
},
methods:{
lang: function() {
//注意在vm实例中想要获取data上的数据,或者想要调用methods中的方法
//必须要使用this来进行访问
var that = this;//解决内部访问问题
//在开启之前先将之前开启的定时器关闭,避免重复开启
clearInterval(this.intervalId)
that.intervalId = setInterval(function(){
//截取第一个字符串
var start = that.message.substring(0,1);
//截取剩下的字符串
var end = that.message.substring(1);
//拼接剩下的字符串
that.message = end + start;
},400)
//vue会监听自己身上data中所有数据的改变,只要数据发生变化,就会自动更新DOM
},
stop:function() {
clearInterval(this.intervalId)
}
}
})
/*
分析:
1.给【浪起来按钮】绑定一个点击事件:v-on
2.在按钮的事件处理函数中,写相关的业务逻辑代码:拿到message字符,然后
调用字符串的substring来进行字符串截取操作,把第一个字符截取出来,放到最后
一个位置即可
3.为了实现点击一下按钮自动截取的功能需要2步骤中的代码,放到一个定时器中
*/
</script>
1.7v-model指令
v-bind只能实现数据的单项绑定,从M自动绑定到V,无法实现数据的双向绑定
v-model它能轻松实现表单输入和应用状态之间的双向绑定。
<div id="app-6">
<p>{{ message }}</p>
<input v-model="message">
</div>
var app6 = new Vue({
el: '#app-6',
data: {
message: 'Hello Vue!'
}
})
注意v-model只能运用在表单元素中
input(radio,text,address,email…)
select
checkbox
textarea
1.8v-model简易计算器
<div id="app">
<input type="text" v-model="n1" />
<select v-model="opration">
<option value ="+">+</option>
<option value ="-">-</option>
<option value ="*">*</option>
<option value ="/">/</option>
</select>
<input type="text" v-model="n2" />
<input type="button" value="=" @click="sulotion"/>
<input type="text" v-model="result" />
</div>
<script type="text/javascript">
var vm = new Vue({
el:'#app',
data:{
n1:0,
n2:0,
result:0,
opration:'+'
},
methods:{
sulotion:function(){//计算器计算方法
//逻辑
sulotion:function(){//计算器计算方法
var codeStr = 'parseInt(this.n1)'+ this.opration +'parseInt(this.n2)'
this.result = eval(codeStr);
}
}
}
})
</script>
1.9在vue中使用样式
1.数组方式:class="['thin','red','i']"
<style type="text/css">
.red{
color: red;
}
.thin{
font-weight: 200;
}
.i{
font-style: italic;
}
.active{
letter-spacing: 0.5em;
}
</style>
<div id="app">
<h1 :class="['thin','red','i']">这是一个h1,测试vue中使用样式</h1>
</div>
<script type="text/javascript">
var vm = new Vue({
el:'#app',
data:{
},
method:{
}
})
</script>
2.在数组中使用三元表达式::class="['thin','red',flag?'active':'']"
<div id="app">
<h1 :class="['thin','red',flag?'active':'']">这是一个h1,测试vue中使用样式</h1>
</div>
其中flag是data中定义的变量
3.在数组中使用对象代替三元表达式提高可读性{'active':flag}
<h1 :class="['thin','red',{'active':flag}]">这是一个h1,测试vue中使用样式</h1>
4.直接使用对象:
:class="{'thin':true,'red':true,'active':true}"
<h1 :class="{'thin':true,'red':true,'active':true}">这是一个h1,测试vue中使用样式</h1>
5.间接绑定:
<div id="app">
<h1 :class="classObj">这是一个h1,测试vue中使用样式</h1></div>
</div>
var vm = new Vue({
el:'#app',
data:{
classObj:{'thin':true,'red':true,'active':true}
}
})
6.使用style
也可以间接绑定
<div id="app">
<h1 :style="{color:'red', font-weight:'200' }">这是一个h1,测试vue中使用样式</h1></div>
</div>
3.v-on按键修饰符
3.1作用说明
文档地址:https://cn.vuejs.org/v2/guide/events.html
在监听键盘事件时,我们经常需要监听常见的键值,vue允许v-on在监听键盘事件时添加按键修饰符:
- enter
- table
- delete (捕获‘删除’和‘退格’键)
- esc
- space
- up
- down
- left
- right
1.0.8+支持单字母按键别名
3.2案例
#app{
width: 600px;
margin: 0 auto;
}
table {
width:100%;
border-collapse: collapse;
color: black;
margin-top: 15px;
}
th {
color: white;
background-color: dodgerblue;
}
table,
tr,
td,
th {
text-align: center;
border: 1px solid #FF0000;
}
<div id="app">
<label>id:<input type="text" v-model="id" /></label>
<!-- #### 重点看这里:-->
<!-- 注册keydown事件,不加修饰符时只要按键改变就会触发,所以要加按键修饰符 -->
<label>姓名:<input type="text" v-model="name" @keydown.enter="add"/></label>
<button type="button" @click="add">添加</button>
<table>
<thead>
<tr>
<th>选择</th>
<th>ID</th>
<th>姓名</th>
<th>操作</th>
</tr>
</thead>
<tr v-show="list.length ==0">
<td colspan="4">当前列表没有任何数据</td>
</tr>
<tr v-for="user in list" :key="user.id">
<td><input type="checkbox" /></td>
<td>{{ user.id }}</td>
<td>{{ user.name }}</td>
<td><a href="#" @click="deleteEle">删除</a></td>
</tr>
</table>
</div>
var app4 = new Vue({
el: '#app-4',
data: {
list: [
{
id: 1,
name: '赵高'
},
{
id: 2,
name: '嬴政'
},
{
id: 3,
name: '李斯'
},
{
id: 4,
name: '荀子'
}
],
id: 0,
name: null
},
methods: {
add: function() { //添加方法
this.list.push({
id: this.id,
name: this.name
});
},
deleteEle: function(id) {
var index = this.list.findIndex(function(item) {
//根据item中的id属性来判断这个item是否是上面id中
//对应的数据,如果是返回一个true ,否返回false,继续下面的一条数据的遍历,以此类推
return item.id == id; //如果返回true,那么findIndex方法会将这个item对应的id返回到外面接受
});
//删除
this.list.splice(index, 1);
}
}
})
3.3 可以自定义按键别名
Vue.config.keyCodes.f2 = 113;//f2自定义按键名称,113对应的键盘码
console.log(Vue.config.keyCodes)
3.4 自定义指令
在vue2.0中,代码复用和抽象的主要形式是组件。然而,有的情况下,你仍然需要对普通DOM元素进行底层操作,这时候就会用到自定义指令。
自定义指令最重要的两个部分就是钩子函数和钩子函数对应的参数。
3.4.1 钩子函数
一个指令定义对象可以提供如下几个钩子函数 (均为可选):
bind只调用一次,指令第一次绑定到元素时调用,在这里可以进行一次性的初始化设置。
inserted被绑定元素插入父节点时调用(仅保证父节点存在,但不一定已被插入文档中)。
update所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
componentUpdated指令所在组件的 VNode 及其子 VNode 全部更新后调用。
unbind只调用一次,指令与元素解绑时调用。
3.4.2钩子函数参数
指令钩子函数会被传入以下参数:
el:
指令所绑定的元素,可以用来直接操作 DOM 。
binding:
一个对象,包含以下属性:
name:
指令名,不包括 v- 前缀。
value:
指令的绑定值,例如:v-my-directive="1 + 1"
中,绑定值为 2。
oldValue:
指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
expression:
字符串形式的指令表达式。例如 v-my-directive="1 + 1"
中,表达式为 “1 + 1”。
arg:
传给指令的参数,可选。例如v-my-directive:foo
中,参数为 “foo”。
modifiers:
一个包含修饰符的对象。例如:v-my-directive.foo.bar
中,修饰符对象为 { foo: true, bar: true }
。
vnode:
Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。
oldVnode:
上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
除了 el 之外,其它参数都应该是只读的,切勿进行修改。如果需要在钩子之间共享数据,建议通过元素的 dataset 来进行。
3.4.3 自定义全局属性指令用法
//vue1.0中提供了一个Vue.directive(自定义指令名称,回调函数)来供程序员自定义指令
//注意:在定义指令时不需要加v-前缀但是使用时必须加v-前缀
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function(el) {
// 聚焦元素
el.focus()
}
})
//定义一个v-color指令
Vue.directive('color', {
// 当被绑定的元素被绑定时
bind: function(el,binding) {
el.style.color = binding.value;
}
})
使用自定义指令
<input type="text" v-focus v-color="customColor" placeholder="请输入筛选条件" v-model="searchtext" />
3.4.4 自定义私有指令
var app4 = new Vue({
el: '#app-4',
data: {},
directives: {
focus: {
// 指令的定义
inserted: function(el) {
el.focus()
}
}
}
使用自定义元素
<input type="text" v-focus placeholder="请输入筛选条件" v-model="searchtext" />
3.4.5 函数简写
在很多时候,你可能想在 bind 和 update 时触发相同行为,而不关心其它的钩子。比如这样写:
Vue.directive('color-swatch', function (el, binding) {
el.style.backgroundColor = binding.value
})
3.4.6 对象字面量
如果指令需要多个值,可以传入一个 JavaScript 对象字面量。记住,指令函数能够接受所有合法的 JavaScript 表达式。
<div v-demo="{ color: 'white', text: 'hello!' }"></div>
Vue.directive('demo', function (el, binding) {
console.log(binding.value.color) // => "white"
console.log(binding.value.text) // => "hello!"
})
4.vue生命周期
所有的生命周期钩子自动绑定 this 上下文到实例中,因此你可以访问数据,对属性和方法进行运算。这意味着你不能使用箭头函数来定义一个生命周期方法 (例如 created: () => this.fetchTodos()
)。这是因为箭头函数绑定了父上下文,因此 this 与你期待的 Vue 实例不同,this.fetchTodos 的行为未定义。
4.1生命周期图示
4.2生命周期方法
beforeCreate
类型:Function
详细:
在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
created
类型:Function
详细:
在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。
beforeMount
类型:Function
详细:
在挂载开始之前被调用:相关的 render 函数首次被调用。
该钩子在服务器端渲染期间不被调用。
mounted
类型:Function
详细:
el
被新创建的vm.$el
替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当 mounted 被调用时vm.$el
也在文档内。
注意 mounted 不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick
替换掉 mounted
mounted: function () {
this.$nextTick(function () {
// Code that will run only after the
// entire view has been rendered
})
}
该钩子在服务器端渲染期间不被调用。
beforeUpdate
类型:Function
详细:
数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。
该钩子在服务器端渲染期间不被调用,因为只有初次渲染会在服务端进行。
updated
类型:Function
详细:
由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用计算属性或 watcher 取而代之。
注意 updated 不会承诺所有的子组件也都一起被重绘。如果你希望等到整个视图都重绘完毕,可以用 vm.$nextTick
替换掉 updated:
updated: function () {
this.$nextTick(function () {
// Code that will run only after the
// entire view has been re-rendered
})
}
beforeDestroy
类型:Function
详细:
实例销毁之前调用。在这一步,实例仍然完全可用。
该钩子在服务器端渲染期间不被调用。
destroyed
类型:Function
详细:
Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
该钩子在服务器端渲染期间不被调用。
5.进入/离开 & 列表过渡
5.1 概述
Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。
包括以下工具:
在 CSS 过渡和动画中自动应用 class
可以配合使用第三方 CSS 动画库,如 Animate.css
在过渡钩子函数中使用 JavaScript 直接操作 DOM
可以配合使用第三方 JavaScript 动画库,如 Velocity.js
5.2 transition过渡
Vue 提供了 transition 的封装组件,在下列情形中,可以给任何元素和组件添加进入/离开过渡
- 条件渲染 (使用 v-if)
- 条件展示 (使用 v-show)
- 动态组件
- 组件根节点
.fade-enter-active,
.fade-leave-active {
transition: opacity .5s;
}
.fade-enter,
.fade-leave-to
/* .fade-leave-active below version 2.1.8 */
{
opacity: 0;
}
<div id="demo">
<button v-on:click="show = !show">
Toggle
</button>
<transition name="fade">
<p v-if="show">hello</p>
</transition>
</div>
new Vue({
el: '#demo',
data: {
show: true
}
})
当插入或删除包含在transition
组件中的元素时,Vue 将会做以下处理:
- 自动嗅探目标元素是否应用了 CSS 过渡或动画,如果是,在恰当的时机添加/删除 CSS 类名。
- 如果过渡组件提供了 JavaScript 钩子函数,这些钩子函数将在恰当的时机被调用。
- 如果没有找到 JavaScript 钩子并且也没有检测到 CSS 过渡/动画,DOM 操作 (插入/删除) 在下一帧中立即执行。(注意:此指浏览器逐帧动画机制,和 Vue 的
nextTick
概念不同)
过渡的类名
对需要进行动画控制的元素使用transition标签包裹有一个name属性值自定义如name=“fade”,但是使用css控制时的前缀必须与name值一致如fade-enter 。
在进入/离开的过渡中,会有 6 个 class 切换,以下v表示name值。
v-enter:
定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。v-enter-active:
定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。v-enter-to:
2.1.8版及以上 定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter 被移除),在过渡/动画完成之后移除。v-leave:
定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。v-leave-active:
定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。v-leave-to:
2.1.8版及以上 定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave 被删除),在过渡/动画完成之后移除。
对于这些在过渡中切换的类名来说,如果你使用一个没有名字的 <transition>
,则 v- 是这些类名的默认前缀。如果你使用了 <transition name="my-transition">
,那么 v-enter
会替换为my-transition-enter
。
v-enter-active
和 v-leave-active
可以控制进入/离开过渡的不同的缓和曲线。
5.3 利用钩子函数进行一半动画的控制
.show{
transition: all 0.4s ease;
}
<div id="app">
<button type="button" @click="show = !show">隐藏/显示</button>
<transition @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter">
<p v-if="show" class="show">Hello Animate css</p>
</transition>
</div>
new Vue({
el:'#app',
data:{
show:true
},
methods:{
//这里主要通过js定义当前实现动画的初始位置,el表示当前操作的元素
beforeEnter:function(el){
el.style.transform = "translate(100px,0)";
},
//通过js定义动画的结束位置
enter:function(el,done){
//设置刷新状态
el.offsetWidth;
//设置动画的结束位置
el.style.transform = "translate(0px,0)";
//手动调用done,保证动画即时结束
done();
},
//动画的状态复原设置
afterEnter:function(el){
this.show = !this.show;
}
}
})
6.组件注册
组件名
在注册一个组件的时候,我们始终需要给它一个名字。比如在全局注册的时候我们已经看到了:
Vue.component('my-component-name', { })
该组件名就是Vue.component
的第一个参数
你给予组件的名字可能依赖于你打算拿它来做什么。当直接在 DOM 中使用一个组件 (而不是在字符串模板或单文件组件) 的时候,我们强烈推荐遵循 W3C 规范中的自定义组件名 (字母全小写且必须包含一个连字符)。这会帮助你避免和当前以及未来的 HTML 元素相冲突
组件名大小写
定义组件名的方式有两种:
使用 kebab-case
Vue.component('my-component-name', { })
当使用 kebab-case (短横线分隔命名) 定义一个组件时,你也必须在引用这个自定义元素时使用 kebab-case,例如 <my-component-name>
。
使用 PascalCase
Vue.component('MyComponentName', { })
当使用 PascalCase (首字母大写命名) 定义一个组件时,你在引用这个自定义元素时两种命名法都可以使用。也就是说 <my-component-name>
和 <MyComponentName>
都是可接受的。注意,尽管如此,直接在 DOM (即非字符串的模板) 中使用时只有 kebab-case 是有效的。
6.1注册全局组件
到目前为止,我们只用过 Vue.component
来创建组件:
Vue.component('my-component-name', { })
这些组件是全局注册的。也就是说它们在注册之后可以用在任何新创建的 Vue 根实例 (new Vue) 的模板中。比如:
Vue.component('component-a', { })
Vue.component('component-b', { })
Vue.component('component-c', { })
new Vue({ el: '#app' })
使用组件
<div id="app">
<component-a></component-a>
<component-b></component-b>
<component-c></component-c>
</div>
在所有子组件中也是如此,也就是说这三个组件在各自内部也都可以相互使用。
6.2定义组件的三种方式
第一种方式
//方法1:定义组件
var login = Vue.extend({
template:'<h1>登陆页面</h1>'
})
//注册组件
Vue.component('login',login);
<div id="app">
<login></login>
</div>
第二种方式
//方法2:定义一个全局组件
Vue.component('register',{
template:'<h1>注册页面</h1>'
})
<div id="app">
<register></register>
</div>
第三种方式
//方法3:定义一个账号组件,建议使用方法三
Vue.component('account',{
template:'#account',
data:function(){
//与vue对象不同的是组件中的data是一个function,
//所以要这么写
return {
message:'账户组件'
}
},
methods:{
login:function(){
alert("Hello VueJs")
}
}
})
模板的事件写在对应的模板中
全局组件引用了一个在html中定义的组件模板account
<!--组件模板的定义 template和script定义都可以但是建议使用template-->
<template id="account">
<div>
{{message}}
<a href="#" @click.prevent="login">登陆</a> |
<a href="#">注册</a>
</div>
</template>
也可以使用script
定义但是建议使用template
标签
<script type="x-template" id="account">
<div>
<a href="#">登陆</a> |
<a href="#">注册</a>
</div>
</script>
值得注意的是,所有子元素必须使用一个共同的根标签包围,如div
6.3局部注册
全局注册往往是不够理想的。比如,如果你使用一个像 webpack 这样的构建系统,全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。
在这些情况下,你可以通过一个普通的 JavaScript 对象来定义组件:
var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }
var ComponentC = { /* ... */ }
然后在 components
选项中定义你想要使用的组件:
new Vue({
el: '#app',
components: {
'component-a': ComponentA,
'component-b': ComponentB
}
})
或者是在组件中定义子组件
//定义一个账号组件
Vue.component('account',{
template:'<div><h1>账号组件</h1><login></login></div>',
//在账号组件中定义一个登陆子组件
components:{
'login':{
template:'<h2>登陆子组件</h2>'
}
}
})
对于 components
对象中的每个属性来说,其属性名就是自定义元素的名字,其属性值就是这个组件的选项对象。
6.4组件的动态切换
首先注册两个组件,login和regist
Vue.component('login',{
template:'<h1>登陆页面</h1>'
})
Vue.component('regist',{
template:'<h1>注册页面</h1>'
})
<div id="app">
<a href="#" @click.prevent="cname = 'login'">登陆</a> |
<a href="#" @click.prevent="cname = 'regist'">注册</a>
<!-- 利用component标签中的:is参数来进行组件的切换 -->
<component :is="cname"></component>
</div>
组件的切换使用component
标签的is
属性
new Vue({
el:'#app',
data:{
cname:'login'
}
})
只要控制is的值即可控制组件的显示,如上通过点击事件改变cname
的值来切换组件
7.vue-router路由
Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。包含的功能有:
- 嵌套的路由/视图表
- 模块化的、基于组件的路由配置
- 路由参数、查询、通配符
- 基于 Vue.js 过渡系统的视图过渡效果
- 细粒度的导航控制
- 带有自动激活的 CSS class 的链接
- HTML5 历史模式或 hash 模式,在 IE9 中自动降级
- 自定义的滚动条行为
7.1路由写法和传参
引入vuejs和vue-router
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
//准备组件
var Ap = Vue.extend({});
var login = Vue.extend({
template:'<div><h1>登陆</h1></div>'
})
var regist = Vue.extend({
template:'<div><h1>注册{{name}}</h1></div>',
data:function(){
return {
name:''
}
},
created:function() {//在页面渲染是将参数赋值给name
this.name = this.$route.params.name
}
})
//实例化路由规则对象
var router = new VueRouter({
routes:[
{path:'/',redirect:'/login'},//如果是/则自动重定向到login
{path:'/login',component:login},
{path:'/regist/:name',component:regist}//获取参数
]
});
//开启路由对象
new Vue({
el:'#app',
router:router//开启路由对象
})
<div id="app">
<!-- 使用 router-link 组件来导航. -->
<!-- 通过传入 `to` 属性指定链接. -->
<!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
<router-link to="/login">登陆</router-link>
<!--通过router-link指定参数 -->
<router-link to="/regist/zhangsan">注册</router-link>
<!-- 路由出口 -->
<!-- 路由匹配到的组件将渲染在这里 -->
<router-view></router-view>
</div>
7.2嵌套路由
//准备组件
//准备组件
var App = Vue.extend({});
var account = Vue.extend({
template:'<div><h1>账号组件</h1></div>'
})
var login = Vue.extend({
template:'<div><h1>登陆</h1></div>'
})
var regist = Vue.extend({
template:'<div><h1>注册</h1></div>'
})
//实例化路由规则对象
var router = new VueRouter({
routes:[
{
path:'/account',
component:account,
children:[
{
path:'login',
component:login
},
{
path:'regist',
component:regist
}
]
}
]
});
//开启路由对象
new Vue({
el:'#app',
router:router//开启路由对象
})