vue api
vue.nexttick
nextTick是全局vue的一个函数,在vue系统中,用于处理dom更新的操作。vue里面有一个watcher,用于观察数据的变化,然后更新dom,vue里面并不是每次数据改变都会触发更新dom,而是将这些操作都缓存在一个队列,在一个事件循环结束之后,刷新队列,统一执行dom更新操作。
通常情况下,我们不需要关心这个问题,而如果想在DOM状态更新后做点什么,则需要用到nextTick。在vue生命周期的created()钩子函数进行的DOM操作要放在Vue.nextTick()的回调函数中,因为created()钩子函数执行的时候DOM并未进行任何渲染,而此时进行DOM操作是徒劳的,所以此处一定要将DOM操作的JS代码放进Vue.nextTick()的回调函数中。而与之对应的mounted钩子函数,该钩子函数执行时所有的DOM挂载和渲染都已完成,此时该钩子函数进行任何DOM操作都不会有个问题。
var nextTick=(function () {
//存储需要触发的回调函数
var callbacks=[];
//是否正在等待的标志(false:允许触发在下次事件循环触发callbacks中的回调,
// true: 已经触发过,需要等到下次事件循环)
var pending=false;
//设置在下次事件循环触发callbacks的触发函数
var timerFunc;
//处理callbacks的函数
function nextTickHandler() {
// 可以触发timeFunc
pending=false;
//复制callback
var copies=callbacks.slice(0);
//清除callback
callbacks.length=0;
for(var i=0;i<copies.length;i++){
//触发callback的回调函数
copies[i]();
}
}
//如果支持promise,使用promise实现
if(typeof Promise !=='undefined' && isNative(promise)){
var p=Promise.resolve();
var logError=function (err) {
console.error(err);
};
timerFunc=function () {
p.then(nextTickHandler).catch(logError);
//iOS的webview下,需要强制刷新队列,执行上面的回调函数
if(isIOS) {setTimeout(noop);}
};
// 如果Promise不支持,但支持MutationObserver
// H5新特性,异步,当dom变动是触发,注意是所有的dom都改变结束后触发
} else if (typeof MutationObserver !=='undefined' && (
isNative(MutationObserver) ||
MutationObserver.toString()==='[object MutationObserverConstructor]')){
var counter = 1;
var observer=new MutationObserver(nextTickHandler);
var textNode=document.createTextNode(String(counter));
observer.observe(textNode,{
characterData:true
});
timerFunc=function () {
counter=(counter+1)%2;
textNode.data=String(counter);
};
} else {
//上面两种都不支持,用setTimeout
timerFunc=function () {
setTimeout(nextTickHandler,0);
};
}
//nextTick接收的函数,参数1:回调函数 参数2:回调函数的执行上下文
return function queueNextTick(cb,ctx) {
//用于接收触发Promise.then中回调的函数
//向回调函数中pushcallback
var _resolve;
callbacks.push(function () {
//如果有回调函数,执行回调函数
if(cb) {cb.call(ctx);}
//触发Promise的then回调
if(_resolve) {_resolve(ctx);}
});
//是否执行刷新callback队列
if(!pending){
pending=true;
timerFunc();
}
//如果没有传递回调函数,并且当前浏览器支持promise,使用promise实现
if(!cb && typeof Promise !=='undefined'){
return new Promise(function (resolve) {
_resolve=resolve;
})
}
}
})
vue.set
mixin时,mixin中的属性会添加到组件属性中<template>
<div class="mixins">
<span>{{msg | uppercase}}</span>
</div>
</template>
<script>
const myMixin = {
created(){
this.hello();
},
methods: {
hello(){
window.console.log(this.msg)
}
}
};
export default {
mixins: [myMixin],
name: 'mixins',
data () {
return {
msg: 'mixin',
}
}
}
</script>
全局mixin(使用Vue.mixin()方法)
Vue.mixin({
created(){
console.log('global mixin')
}
});
在定义全局mixin之创建的Vue实例都会将mixin对象里的属性添加到实例中new Vue({
el: '#app',
router,
template: '<App/>',
components: { App }
});
const Component = Vue.extend({
template:'<span>121</span>'
});
Vue.mixin({
created(){
window.console.log('global mixin')
}
});
const component=new Component();
这段代码中由于mixin是在App生成之后定义的,只会在创建Component实例的时候才会添加到实例属性中,created执行一次。
vue.watch
对应一个对象,键是观察表达式,值是对应回调。值也可以是方法名,或者是对象,包含选项。在实例化时为每个键调用 $watch() ;
<template>
//观察数据为字符串或数组
<input v-model="example0"/>
<input v-model="example1"/>
/当单观察数据examples2为对象时,如果键值发生变化,为了监听到数据变化,需要添加deep:true参数
<input v-model="example2.inner0"/>
</template>
<script>
export default {
data(){
return {
example0:"",
example1:"",
example2:{
inner0:1,
innner1:2
}
}
},
watch:{
example0(curVal,oldVal){
console.log(curVal,oldVal);
},
example1:'a',//值可以为methods的方法名
example2:{
//注意:当观察的数据为对象或数组时,curVal和oldVal是相等的,因为这两个形参指向的是同一个数据对象
handler(curVal,oldVal){
console.log(curVal,oldVal)
},
deep:true
}
},
methods:{
a(curVal,oldVal){
conosle.log(curVal,oldVal)
}
}
}
</script>
$children $parent
使用 this.$parent查找当前组件的父组件。
使用 this.$children查找当前组件的直接子组件,可以遍历全部子组件, 需要注意 $children 并不保证顺序,也不是响应式的。
使用 this.$root查找根组件,并可以配合$children遍历全部组件。
使用 this.$refs查找命名子组件。
父组件Game.vue
<template>
<div class="game">
<h2>{{ msg }}</h2>
<LOL ref="lol"></LOL>
<DNF ref="dnf"></DNF>
</div>
</template>
<script>
import LOL from '@/components/game/LOL'
import DNF from '@/components/game/DNF'
export default {
name: 'game',
components: {
LOL,
DNF
},
data () {
return {
msg: 'Game',
lolMsg:'Game->LOL',
dnfMsg:'Game->DNF',
}
},
methods: {
},
mounted(){ //注意 mounted
//读取子组件数据,注意$children子组件的排序是不安全的
console.log(this.$children[0].gameMsg);//LOL->Game
//读取命名子组件数据
console.log(this.$refs.dnf.gameMsg);//DNF->Game
//从根组件查找组件数据
console.log(this.$root.$children[0].msg); //APP
console.log(this.$root.$children[0].$children[0].msg); //Game
console.log(this.$root.$children[0].$children[0].$children[0].msg); //Game->LOL
console.log(this.$root.$children[0].$children[0].$children[1].msg); //Game->DNF
}
}
</script>
<style lang="css">
.game{
border: 1px solid #00FF00;
width: 200px;
}
</style>
子组件LOL.vue
<template>
<div class="lol">
<h2>{{ msg }}</h2>
</div>
</template>
<script>
export default {
name: 'LOL',
data () {
return {
msg: 'LOL',
gameMsg:'LOL->Game',
}
},
methods:{
},
created(){
//读取父组件数据
this.msg = this.$parent.lolMsg;
}
}
</script>
子组件DNF.vue
<template>
<div class="dnf">
<h2>{{ msg }}</h2>
</div>
</template>
<script>
import Bus from '../../utils/bus.js'
export default {
name: 'DNF',
data () {
return {
msg: 'DNF',
gameMsg:'DNF->Game',
}
},
methods:{
},
created(){
//从根组件向下查找父组件数据
this.msg = this.$root.$children[0].$children[0].dnfMsg;
}
}
</script>

浙公网安备 33010602011771号