vue之实例属性
Vue实例暴露了一些有用的实例属性与方法,这些属性与方法都有前缀$以便于与代理的属性区分
实例私有属性
- $parent 用来访问组件实例的父实例
- $root 获取根元素的vm实例(main.js中new 的Vue实例)
- $children 用来访问当前组件实例的直接子组件实例
- $refs:用来访问v-ref指令的子组件或者dom元素
- $el用来挂载当前组件实例的dom元素
- $options:用于当前 Vue 实例的初始化选项。需要在选项中包含自定义 property 时会有用处:
- $data 用来访问组件实例观察的数据对象
实例方法/事件
vm.$on("myEvent",fn)
:向事件池中添加myEvent
事件,并绑定fn函数,==能被调用无数次==vm.$once("myEvent",fn)
:向事件池中添加myEvent
事件,==并规定被调用一次之后就销毁=vm.$emit("myEvent",parm1,parm2,...)
:执行事件池中的myEvent
事件函数,并把第二个及以后的实参赋值给myEvent
绑定的函数vm.$off("myEvent")
:删除掉事件池中的myEvent
事件
实例方法/数据
vm.$set(obj,"name","lisa")
:给vm实例data中的obj添加一个name属性,值为lisa,==并且把它变为响应式状态值==,(默认在data之外添加数据this.obj.name="lisa"
是不会变成响应式数据的,不会触发页面重新渲染的)vm.$delete(obj,"name")
:与$set作用相对应,删除vm实例data中obj对象中的name属性,==并且通知页面重新渲染==,(默认在data之外删除数据delete this.obj.name
是不会触发页面重新渲染的)vm.$watch
:观察 Vue 实例上的一个表达式或者一个函数计算结果的变化。回调函数得到的参数为新值和旧值。表达式只接受简单的键路径。对于更复杂的表达式,用一个函数取代。
实例方法/生命周期
vm.$mount("#box")
:如果 Vue 实例在实例化时没有收到 el 选项,则它处于“未挂载”状态,没有关联的 DOM 元素。可以使用vm.$mount()
手动地挂载一个未挂载的实例。(只有被vue挂载上的#box标签,内部才能用vue的框架的各种属性)vm.$forceUpdate()
:执行该方法会强制刷新页面渲染vm.$nexTick([callback])
将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。它跟全局方法Vue.nextTick
一样,不同的是回调的this
自动绑定到调用它的实例上。vm.$destory()
:触发beforeDestory()、destoryed()
钩子函数阶段
<template>
<div class="about">
{{ obj }}
</div>
</template>
<script>
export default {
name: "About",
data() {
obj: {
name: "lili",
age: 28,
},
};
mounted() {
this.obj.num = 1000; //在data外添加的数据是非响应式的,数据更新了,页面没刷新
this.$forceUpdate(); //页面强制刷新
this.$set(this.obj, "muma", 1000); //把numa变成响应式的
delete this.obj["name"]; //数据变了,页面没有更新
this.$forceUpdate(); //页面强制刷新
this.$delete(this.obj, "age"); //和set一样,删除数据并且更新页面
},
};
</script>
//数组的七大方法也可以更新数据 (push/pop/shift/unshift/splice/sort/reverse)
$nexTick详解
1.在created()钩子函数执行的时候DOM 其实并未进行任何渲染,而此时进行DOM操作无异于徒劳,所以此处一定要将DOM操作的js代码放进Vue.nextTick()的回调函数中。
与之对应的就是beforeMount()、mounted()钩子函数,因为该钩子函数执行时所有的DOM挂载和渲染都已完成,此时在该钩子函数中进行任何DOM操作都不会有问题 。
2.在数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的DOM结构的时候,这个操作都应该放进Vue.nextTick()的回调函数中
案例一
<template>
<div class="one">
<h1 ref="one">1111</h1>
</div>
</template>
<script>
export default {
name: "One",
data() {
return {};
},
created() {
//data 方法都有了 el没有挂载
console.log(this.$refs.one); //undefined ,真实dom还没生成
//nextTick为异步回调,diff算法完毕后执行异步回调
//diff算法的本质就是:找出两个对象之间的差异,目的是尽可能做到节点复用。”
this.$nextTick(() => {
console.log(this.$refs.one);
});
},
beforeMount() {
//虚拟dom已经生成,还没有挂载,可以操做虚拟dom,但是不能获取真实dom
console.log(this.$refs.one); //undefined
},
mounted() {
//真实dom已经生成,挂载完了数据,
//ref写在dom元素上获取的是真实dom在mounted里真实dom已经生成
console.log(this.$refs.one);
},
};
</script>
案例二
<template>
<div class="one">
<h3 v-for="item in arr" ref="a">{{ item }}</h3>
</div>
</template>
<script>
export default {
name: "One",
data() {
return {
arr: [10, 20, 30],
};
},
mounted() {
console.log(this.$refs.a);
console.log(this.$refs.a.length); //3 真实dom长度
this.arr.pop(); //弹出一个 这时候数据是2了
console.log(this.$refs.a.length);
//3; 页面变化了,但是,是在mounted 渲染之后里面访问的是真实dom长度
// 还没有走到updated更新钩子,这时候数组长度还是3
this.$nextTick(() => {
//异步操作nextTick八大钩子已经走完,在访问真实dom已经是2了
console.log(this.$refs.a.length); //2
});
},
};
</script>
.组件的切换效果(动态组件)
<component></component>
:渲染一个“元组件”为动态组件。依 is
的值,来决定哪个组件被渲染。
- 用法:
<component is="coma"></component>
,它会找==new Vue()==的components中去找coma组件渲染 - 如果想动态绑定值,用v-bind:
<component :is="bindprop"></component>
<div class="about">
<h1>about</h1>
<button @click="flag = 'coma'">coma</button>
<button @click="flag = 'comb'">comb</button>
<button @click="flag = 'comc'">comc</button>
<hr />
<component :is="flag"></component>
</div>
</template>
<script>
import coma from "../components/coma.vue";
import comb from "../components/comb.vue";
import comc from "../components/comc.vue";
export default {
name: "About",
data() {
return {
flag: "coma",
};
},
components: {
coma,
comb,
comc,
},
};
</script>
自定义指令
使用Vue.directive(id,definition)注册全局自定义指令,使用组件的directives选项注册局部自定义指令。
指令定义函数提供了几个钩子函数(可选):
- bind:只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。
- inserted:被绑定元素插入DOM(父节点)时调用(父节点存在即可调用,不必存在于 document 中)。
- update:第一次是紧跟在 bind 之后调用,获得的参数是绑定的初始值,之后被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新(详细的钩子函数参数见下)。
- componentUpdated:被绑定元素所在模板完成一次更新周期时调用。
- unbind:只调用一次, 指令元素解绑时调用。
钩子函数的参数(el, binding, vnode, oldVnode)
- 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.a.b,modifiers的值为{'a':true,'b':true}
用法:
<template>
<div class="two">
<input type="text" />
<input type="text" v-focus="1 + 1" />
<h1 v-bgcolor="'blue'">1111</h1>
</div>
</template>
<script>
export default {
directives: {
focus: {
//插入到dom上
inserted: function (el, binding, vnode, oldvnode) {
//console.log(el);//设置的目标元素
//console.log(binding);//设置值的相关信息
//console.log(binding.value);//2,结果
//console.log(binding.expression);//1+1 过程
//console.log(vnode);//所有信息,包含子元素
el.focus(); //自动获取焦点
},
},
bgcolor: {
inserted: function (el, binding) {
console.log(binding.value); //传过来的blue
// el.style.backgroundColor = "red";
el.style.backgroundColor = binding.value;
},
},
},
};
</script>
vue过渡与动画
过渡
vue提供了transition
的内置组件,在下列情形中,可以给任何元素和组件添加==进入/离开==过渡
- 条件渲染(使用
v-if
) - 条件显示(使用
v-show
) - 动态组件
- 组件根节点
过渡的类名:在进入/离开的过渡中,会有6个class切换
==使用方式==:transition标签默认存在六个类名,这些类名都可以在style标签中用类选择器进行样式定义:
v-enter
:定义进入过渡的开始状态,在过渡开始之前生效,在DOM元素被插入之后的下一帧移除v-enter-active
:定义进入过渡生效时的状态,在整个过渡的阶段中应用,在过渡/动画完成之后移除【==用来定义进入过渡的过程时间,延迟和曲线函数(transition)==】v-enter-to
:定义进入过渡的结束状态。在DOM元素被插入之后的下一帧生效,在过渡/动画完成之后移除v-leave
:定义离开过渡的开始状态。在离开过渡被触发时立即生效,下一帧立即移除v-leave-active
:定义离开过渡生效时的状态,在整个离开过渡的阶段中应用,在过渡/动画完成之后移除【==用来定义进入过渡的过程时间,延迟和曲线函数(transition)==】v-leave-to
:定义离开过渡结束状态。在元素被插入之后,在离开过渡被触发之后下一帧生效 (与此同时v-leave
被删除),在过渡/动画完成之后移除。
应用
<div id="demo">
<--!transition标签默认存在-->
<transition name="mytran">
<p v-if="show">
hello
</p>
</transition>
</div>
<script>
new Vue({
el:"#demo",
data:{
show:true
}
})
</script>
<style>
.mytran-enter-active {
transition: all .3s ease;
}
.mytran-leave-active {
transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}
.mytran-enter, .mytran-leave-to
/* .mytran-leave-active for below version 2.1.8 */ {
transform: translateX(10px);
opacity: 0;
}
</style>
自定义类名:**对于以上6个类名,如果我们直接用<transition>
标签,则类名都是v-xxx
,如果想与默认的transition区分出来,需要给标签添加name标签<transition name="mytran">
,==这时这个标签动画的所有类名就变成了mytran-xxx
==
动画
使用第三方 CSS 动画
一. 导入动画类库:https://animate.style/
<link rel="stylesheet" type="text/css" href="./lib/animate.css">
脚手架中使用
1.npm install animate.css@3
2.Main.js中引入
import animated from 'animate.css'
Vue.use(animated)
二. 定义 transition 及属性:
enter-class
enter-active-class
enter-to-class
(2.1.8+)leave-class
leave-active-class
leave-to-class
(2.1.8+)
栗子
<template>
<div class="two">
<button @click="flag = !flag">显示隐藏</button>
<transition
enter-active-class=" animated bounceInDown"
leave-active-class=" animated bounceInLeft"
:duration="{ enter: 500, leave: 800 }"动画时长
>
<h1 v-show="flag">1111</h1>
</transition>
//------------第二种--------
<transition
enter-active-class="bounceInDown"
leave-active-class="bounceInLeft"
>
<h1 class="animated" v-show="flag">1111</h1>
</transition>
</div>
</template>
<script>
export default {
name: "Two",
data() {
return {
flag: false,
};
},
};
</script>
列表过渡
列表过渡常用在v-for的标签里边,这时标签名就要用<transition-group>
- 不同于
<transition>
,它会以一个真实元素呈现:默认为一个<span>
。你也可以通过tag
attribute 更换为其他元素。 - 过渡模式不可用,因为我们不再相互切换特有的元素。
- 内部元素总是需要提供唯一的
key
attribute 值。 - CSS 过渡的类将会应用在内部的元素中,而不是这个组/容器本身。
栗子
<div id="list-demo" class="demo">
<button v-on:click="add">Add</button>
<button v-on:click="remove">Remove</button>
<transition-group name="list" tag="p">
<span v-for="item in items" v-bind:key="item" class="list-item">
{{ item }}
</span>
</transition-group>
</div>
--------------------------------------------------------
new Vue({
el: '#list-demo',
data: {
items: [1,2,3,4,5,6,7,8,9],
nextNum: 10
},
methods: {
randomIndex: function () {
return Math.floor(Math.random() * this.items.length)
},
add: function () {
this.items.splice(this.randomIndex(), 0, this.nextNum++)
},
remove: function () {
this.items.splice(this.randomIndex(), 1)
},
}
})
-----------------------------------------
.list-item {
display: inline-block;
margin-right: 10px;
}
.list-enter-active, .list-leave-active {
transition: all 1s;
}
.list-enter, .list-leave-to
/* .list-leave-active for below version 2.1.8 */ {
opacity: 0;
transform: translateY(30px);
}