ref:引用
ref属性绑定到html标签上时可以获取该标签的DOM,ref属性绑定到组件上时,可以使用this.$refs.组件名.data获取组件中的数据,可以利用此方法在父组件中获取子组件的data数据或方法
动态组件和动态组件切换时动画效果
在使用组件时可以用下面两种方式,第二种方式的好处是可以动态的绑定所需要的组件,即动态组件
<com-a></com-a>
<p :is='comA'></p>
组件切换时也可以用动画效果
但是默认动画的模式是先进新的后消失旧的,即in-out,所以组件切换时或有2个组件同时存在的一瞬间,使用mode=‘out -in’解决这个问题
<transition name='fade' mode='out-in'>
<p :is='comA'></p>
</transition>
多元素动画过渡时如果标签名相同,必须使用不同的key,否则不会触发动画
<transition name='fade' mode='out-in'>
<p v-if='show' key='1'>aaa</p>
<p v-else key='2'>bbb</p>
</transition>
使用keep-alive时可以在切换组件时获得组件的缓存,类似路由的缓存
<keep-alive>
<p :is='comA'></p>
<keep-alive>
子组件接收数据时props类型可以是数组或对象
接收数据时可以用数组的方法表示接收时的数据是不固定的,如[String, Object]可以表示接收时可以是字符串或对象
props: ['aaa', 'bbb']
props: {
'aaa': [String, Object],
'bbb': Number
}
事件修饰符
默认是冒泡机制,即先触发当前元素的事件,后触发外层元素的事件
.stop 阻止冒泡
. prevent 阻止默认事件,如a标签的默认跳转事件会被阻止,表单标签提交事件也会被阻止
.capture 捕获机制,先触发当前元素的事件,后触发内层元素的事件
.self 只有被点击自己时才触发事件,如内层元素被点击时,默认会冒泡至外层,外层也会触发事件,修饰在外层元素中时就不会触发这个不是自身被点击的事件
.once 事件值触发一次
过滤器
过滤器只可以用在两个地方:mustache 插值表达式和 v-bind 表达式
注意:当有局部和全局两个名称相同的过滤器时候,会以就近原则进行调用,即局部过滤器优先于全局过滤器被调用!
### 私有过滤器
1. HTML元素:
<td>{{item.ctime | dataFormat('yyyy-mm-dd')}}</td>
2. 私有 `filters` 定义方式:
filters: {
dataFormat(input, pattern) {
var dt = new Date(input);
// 获取年月日
var y = dt.getFullYear();
var m = (dt.getMonth() + 1).toString().padStart(2, '0');
var d = dt.getDate().toString().padStart(2, '0');
// 如果 传递进来的字符串类型,转为小写之后,等于 yyyy-mm-dd,那么就返回 年-月-日
// 否则,就返回 年-月-日 时:分:秒
if (pattern.toLowerCase() === 'yyyy-mm-dd') {
return `${y}-${m}-${d}`;
} else {
// 获取时分秒
var hh = dt.getHours().toString().padStart(2, '0');
var mm = dt.getMinutes().toString().padStart(2, '0');
var ss = dt.getSeconds().toString().padStart(2, '0');
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`;
}
}
}
// 定义一个全局过滤器
Vue.filter('dataFormat', function (input, pattern = '') {
// 内容同局部过滤器
});
watch方法
监听data中的数据变化
<body>
<div id="app">
<input type="text" v-model="firstname"> +
<input type="text" v-model="lastname"> =
<input type="text" v-model="fullname">
</div>
<script>
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {
firstname: '',
lastname: '',
fullname: ''
},
methods: {},
watch: { // 使用这个 属性,可以监视 data 中指定数据的变化,然后触发这个 watch 中对应的 function 处理函数
'firstname': function (newVal, oldVal) {
this.fullname = newVal + '-' + this.lastname
},
'lastname': function (newVal) {
this.fullname = this.firstname + '-' + newVal
}
}
});
</script>
</body>
监听路由地址的改变
watch: {
'$route.path': function (newVal, oldVal) {
if (newVal === '/login') {
console.log('欢迎进入登录页面')
} else if (newVal === '/register') {
console.log('欢迎进入注册页面')
}
}
}
键盘修饰符以及自定义键盘修饰符
通过`Vue.config.keyCodes.名称 = 按键值`来自定义按键修饰符的别名:
Vue.config.keyCodes.f2 = 113;
使用自定义的按键修饰符:
<input type="text" v-model="name" @keyup.f2="add">
自定义指令
钩子函数
-
bind
:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。 -
inserted
:只调用一次,被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。 -
update
:所在组件的 VNode 更新时调用 -
注意与js行为有关的操作尽量放在
inserted中,因为此时元素已被插入到DOM中,而样式可以放在bind中
自定义全局指令 v-focus,为绑定的元素自动获取焦点:
Vue.directive('focus', {
inserted: function (el) { // inserted 表示被绑定元素插入父节点时调用
el.focus();
}
});
自定义局部指令 v-color 和 v-font-weight,为绑定的元素设置指定的字体颜色和字体粗细:
directives: {
color: { // 为元素设置指定的字体颜色
bind(el, binding) {
el.style.color = binding.value;
}
},
自定义指令的简写形式,等同于把代码写到了 bind 和 update 两个钩子函数中
'font-weight': function (el, binding2) {
el.style.fontWeight = binding2.value;
}
}
自定义指令的使用方式
注意在v-color中绑定的是一个‘red’字符串,这样binding.value可以取到这个绑定值
<input type="text" v-model="searchName" v-focus v-color="'red'" v-font-weight="900">
钩子函数参数
指令钩子函数会被传入以下参数:
el
:指令所绑定的元素,可以用来直接操作 DOM 。binding
:一个对象,包含以下主要属性:name
:指令名,不包括v-
前缀。value
:指令的绑定值,例如:v-my-directive="1 + 1"
中,绑定值为2
。oldValue
:指令绑定的前一个值,仅在update
和componentUpdated
钩子中可用。无论值是否改变都可用。expression
:字符串形式的指令表达式。例如v-my-directive="1 + 1"
中,表达式为"1 + 1"
。
vue实例的生命周期
主要的生命周期函数分类:
创建期间的生命周期函数:
beforeCreate:实例刚在内存中被创建出来,此时,还没有初始化好 data 和 methods 属性
created:实例已经在内存中创建OK,此时 data 和 methods 已经创建OK,此时还没有开始 编译模板
beforeMount:此时已经完成了模板的编译,但是还没有挂载到页面中
mounted:此时,已经将编译好的模板,挂载到了页面指定的容器中显示
运行期间的生命周期函数:
beforeUpdate:状态更新之前执行此函数, 此时 data 中的状态值是最新的,但是界面上显示的 数据还是旧的,因为此时还没有开始重新渲染DOM节点
updated:实例更新完毕之后调用此函数,此时 data 中的状态值 和 界面上显示的数据,都已经完成了更新,界面已经被重新渲染好了!
销毁期间的生命周期函数:
beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。
destroyed:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
vue-resource 实现 get, post, jsonp请求
发送get请求:
getInfo() {
this.$http.get('http://127.0.0.1:8899/api/getlunbo').then(res => {
console.log(res.body);
})
}
发送post请求:
postInfo() {
var url = 'http://127.0.0.1:8899/api/post';
// post 方法接收三个参数:
// 参数1: 要请求的URL地址
// 参数2: 要发送的数据对象
// 参数3: 指定post提交的编码类型为 application/x-www-form-urlencoded
this.$http.post(url, { name: 'zs' }, { emulateJSON: true }).then(res => {
console.log(res.body);
});
}
发送JSONP请求获取数据:
jsonpInfo() {
var url = 'http://127.0.0.1:8899/api/jsonp';
this.$http.jsonp(url).then(res => {
console.log(res.body);
});
}
过渡动画
自定义样式动画
// 进入之前和离开之后
.v-enter, .v-leave-to {
opacity: 0;
transform: translate3d(300px, 0, 0);
}
// 进入过程和离开过程
.v-enter-active, .v-leave-active {
transition: all 2s linear;
}
// 进入之后和离开之前
// 可以默认不写
.v-enter-to, .v-leave {
opacity: 1;
transform: translate3d(0, 0, 0);
}
使用animate.css实现动画,导入animate.css后(https://daneden.github.io/animate.css/)
// :duration='200'表示入场0.2s,出场0.2s
<transition enter-active-class="animated bounceIn" enter-active-class="animated bounceOut" :duration='200'>
<h3 v-show="show">这是一个H3</h3>
</transition>
// 也可以这么写
<transition enter-active-class="bounceIn" enter-active-class="bounceOut" :duration='200'>
<h3 v-show="show" class="animated">这是一个H3</h3>
</transition>
// 使用duration绑定对象实现入场和出场不同的时间
<transition enter-active-class="bounceIn" enter-active-class="bounceOut" :duration='{enter: 200, leave: 400}'>
<h3 v-show="show" class="animated">这是一个H3</h3>
</transition>
上面的两种方式都不能实现半场动画,需要借助JavaScript钩子实现半场动画
举例购物车添加时的小球动画,使用JavaScript钩子实现半场动画
<body>
<div id="app">
<input type="button" value="加入购物车" @click="show = !show">
<transition @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter">
<div class="ball" ref="ball" v-show="show"></div>
</transition>
</div>
<script>
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {
show: false
},
methods: {
// 动画开始时的起始位置
beforeEnter (el) {
el.style.opacity = 1
el.style.transform = 'translate(0,0)'
},
// 动画结束时的位置
enter (el, done) {
// 强制刷新动画,必须写
el.offsetWidth
el.style.transform = 'translate(300px,500px)'
el.style.transition = 'all .3s linear'
// done()是必须的,调用done() 其实就是直接调用afterEnter()函数
done()
},
afterEnter (el) {
// el.style.opacity = 0
this.show = false
}
}
})
</script>
</body>
列表过渡
通过给transition-group添加appear属性可以实现整个列表刚展示出来时的动画效果
<div id="app">
<label>id:<input type="text" v-model="id"></label>
<label>name:<input type="text" v-model="name"></label>
<button @click="add">添加</button>
<ul>
<transition-group appear>
<li v-for="(item,i) of list" :key="i" @click="del(i)">{{item.name}}</li>
</transition-group>
</ul>
</div>
<style>
li {
border: 1px dashed #999;
width: 30%;
margin: 20px;
padding: 20px;
}
li:hover {
background-color: red;
transition: all .6s ease;
}
.v-enter, .v-leave-to {
opacity: 0;
transform: translateY(80px);
}
.v-enter-active, .v-leave-active {
transition: all .6s ease;
}
.v-move {
transition: all .6s ease;
}
.v-leave-active {
position: absolute;
}
</style>
使用transition-group时每个li元标签外会包裹一个span标签,不符合W3C规范,可以先删除外层的ul标签,在transition-group中添加tag=‘ul’达到同样效果
<transition-group appear tag='ul'>
<li v-for="(item,i) of list" :key="i" @click="del(i)">{{item.name}}</li>
</transition-group>