组件渲染完成后都会生成一个实例(像new Obj),一般情况下不需要关注实例只需要关注数据,但有些情况肯定需要实例操作的,比如一些插件的挂载echarts这种
ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例:
<template>
<div>
<p ref="p">1111</p>
<ChildrenA ref="pp"/>
<button @click="refs">Ref</button>
</div>
</template>
<script>
import ChildrenA from './components/ChildrenA'
export default {
methods:{
refs(){
console.log(this.$refs)
}
},
components:{
ChildrenA
}
}
</script>
<style>
</style>
那么这个pp就是子组件,可以认为就是子组件中的this
那么在子组件中,声明一个data
data(){
return {
name:'Vue'
}
}
直接就可以在主组件中打印了
methods:{
refs(){
console.log(this.$refs.pp.name) //Vue
}
},
传统的获取父组件实例会用到$parent $children
这种递归的方式,很麻烦
https://blog.csdn.net/luobosiji/article/details/90696147(跨层级获取实例,需要安装插件,保存一下,用到的时候可看)
那么实例肯定是DOM挂载好之后才能获取,所以对于ref的操作要在mounted之后
created(){
console.log(this.$refs)
},
mounted(){
console.log(this.$refs)
}
不然会报错无法找到DOM
那么对于实例还要对nextTick的用法注意,首先看个Demo
<template>
<div>
<div ref="msgDiv">{{msg}}</div>
<div v-if="msg1">Message got outside $nextTick: {{msg1}}</div>
<div v-if="msg2">Message got inside $nextTick: {{msg2}}</div>
<div v-if="msg3">Message got outside $nextTick: {{msg3}}</div>
<button @click="changeMsg">
Change the Message
</button>
</div>
</template>
<script>
import ChildrenA from './components/ChildrenA'
export default {
data(){
return{
msg: 'Hello Vue.',
msg1: '',
msg2: '',
msg3: ''
}
},
methods: {
changeMsg() {
this.msg = "Hello world."
this.msg1 = this.$refs.msgDiv.innerHTML
this.$nextTick(() => {
this.msg2 = this.$refs.msgDiv.innerHTML
})
this.msg3 = this.$refs.msgDiv.innerHTML
}
}
}
</script>
<style>
</style>
此时方法的逻辑是这样,修改了响应式数据msg的值,其中msg2使用了nextTickm,msg1msg3并没有
可以看到,msg1 msg2是msg修改之前的内容,只有msg2是修改后的内容
那么在刚才肯定是触发了更新函数,这里就不演示了
Vue的官方文档中详细解释:
Vue 异步执行 DOM 更新。只要观察到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据改变。如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作上非常重要。然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。Vue 在内部尝试对异步队列使用原生的 Promise.then 和MessageChannel,如果执行环境不支持,会采用 setTimeout(fn, 0)代替。
例如,当你设置vm.someData = 'new value',该组件不会立即重新渲染。当刷新队列时,组件会在事件循环队列清空时的下一个“tick”更新。多数情况我们不需要关心这个过程,但是如果你想在 DOM 状态更新后做点什么,这就可能会有些棘手。虽然 Vue.js 通常鼓励开发人员沿着“数据驱动”的方式思考,避免直接接触 DOM,但是有时我们确实要这么做。为了在数据变化之后等待 Vue 完成更新 DOM ,可以在数据变化之后立即使用Vue.nextTick(callback) 。这样回调函数在 DOM 更新完成后就会调用。
看不懂可以像我这么理解,你可以认为,当你点击修改数据的时候,重新初始化了数据。原本meg是'Hello Vue',现在初始化的数据是‘Hello world.’,但是在created钩子函数中,msg1与msg3已经被这个老msg的值(Hello Vue.)赋值了,但是在mounted钩子函数中,新的HelloWorld 值赋值给了msg2...
总之记住一句话,nextTick操作的是DOM更新之后的状态(后面写一些小项目,比如上拉加载或者什么的再看看)
过滤 filter
Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式
在组件中声明
filters:{
zero(value){
return `0${value}`.slice(-2)
}
},
注意单词是filters,组件中有个s
<template>
<div>
{{num | zero}}
</div>
</template>
也可以实行串联形式
,类似高级函数的compose
<template>
<div>
{{price | toFixed(2) | toUSD}}
<hr>
</div>
</template>
<script>
import ChildrenA from './components/ChildrenA'
export default {
data(){
return{
price:23.333
}
},
filters:{
toFixed(price,limit){
return price.toFixed(limit)
} ,
toUSD(val){
return `$${val}`
}
},
}
</script>
<style>
</style>
插值中的方法第一个参数默认就是前一个数据的return,所以参数是第二个函数开始写的
可以在main.js中设置全局的filter
但是一般情况下我们是这么引入的
贴下代码!
单独设置一个js
export function zero(val){
return `0${val}`.slice(-2)
}
暴露一个同样的方法,然后再main.js中引入
import * as filters from './filter/filter'
然后通过Object注册到实例
Object.keys(filters).forEach(key=>{
Vue.filter(key,filters[key])
})
就可以直接使用了,项目应该大多都是如此引用的