饿了么项目---7、ref属性注册节点信息,并获取DOM节点(1)

本笔记重点:
- 如何通过vue的refs属性获取DOM节点
- 如何在vue的示例中获取到节点元素
- 在created函数中不可使用的问题

一、refs的使用

1.1 官方介绍

    被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素; 如果用在子组件上,引用就指向组件实例:

<!-- vm.$refs.p will be the DOM node -->
<p ref="p">hello</p>
<!-- vm.$refs.child will be the child comp instance -->
<child-comp ref="child"></child-comp>

1.2 使用方式

通俗的解释:为想要获取的DOM节点元素添加ref属性,值为你命名的该节点名,此节点名就是你要获取的节点对象。这里有一个模仿饿了么的案例:
html代码如下:

<template>
   <div class="goods">
        <div ref='menuWrapper'>
           ....此处省略一行行行行的代码...
        </div>
         <div class='goodsLists' ref='foodsWrapper'>
            ....此处省略一行行行行的代码...
         </div>
   </div>
</template>

在vue1.版本中是使用的指令v-el,到了vue2.以后直接在元素上使用属性命名的方式就可以注册引用信息。在js代码中是如何获取此节点的呢?
js代码如下:

import BScroll from 'better-scroll';
export default {
  name: 'goods',
  props: {
    seller:{
        type:Object
    }
  },
  data(){
    return{
       goods:[],//商品信息
       listHeight:[]   //每个菜单将要滑动的height
    }
  },
  created(){
    //此处为使用DOM节点的测试部分
    console.log(this.$refs); //此时返回空对象
    this.$nextTick(()=>{
               console.log(this.$refs); //返回
        })
    //数据请求
    this.$http.get('/api/goods').then((response)=>{
      response = response.body;
      if(response.errno){
        this.goods =response.data;
        this.$nextTick(()=>{
              this._initScroll();
        })
      }
    },(response)=>{
      console.log(response)
    });
  },
  methods:{
    _initScroll() {
        this.meunScroll = new BScroll(this.$refs.menuWrapper, {

        });
        this.foodsScroll = new BScroll(this.$refs.foodsWrapper, {

        });
  }
}
</script>

在 methods 中编写 _initScroll方法,获取menuWrapper 与 foodsWrapper两个节点对象,并有相关的功能,在created钩子函数中调用该函数

结果图:

这里写图片描述

在created钩子函数中一开始是获取不到包含了两个DOM节点的 this. refs使this. nextTick函数时,方可获取到对象节点。这是为什么呢?

原因(官方解释):

关于ref注册时间的重要说明:因为ref本身是作为渲染结果被创建的,在初始渲染的时候你不能访问它们 - 它们还不存在!$refs 也不是响应式的,因此你不应该试图用它在模版中做数据绑定。

此时要使用此DOM节点是需要使用方法this.$nextTick()


该部分原理请看下一节

1.3 $nextTick 使用(1)

其实在vuejs官网教程中的这一点已经解释的很清楚了,此处贴上链接 https://cn.vuejs.org/v2/guide/reactivity.html

    其实解释起来很简单,当把javascript对象传给vue实例的data 选项,Vue将遍历此对象的所有属性,并对他们追踪依赖,属性变化和更改时都能响应变化。然而,在实例对象data以外更改它的属性,vue是无法响应的。

解决方法:使用方法Vue.set(Object,key,value) ,也可以在组件实例中直接用this代替全局vue:this.set(Object,key,value)
demo:

var vm = new Vue({
  data:{
  a:1
  }
})
// `vm.a` 是响应的
vm.b = 2
// `vm.b` 是非响应的

Vue.set(vm.someObject, 'b', 2)

1.3 $nextTick 使用(2)

注意: Vue异步执行DOM更新

demo:
html:

<div id="example">{{message}}</div>                     

js:

var vm = new Vue({
  el: '#example',
  data: {
    message: '123'
  }
})
vm.message = 'new message' // 更改数据
vm.$el.textContent === 'new message' // false
Vue.nextTick(function () {
  vm.$el.textContent === 'new message' // true
})

此处可以在组件实例中用this代替全局vue

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值