1. 程式人生 > >餓了麼專案---7、ref屬性註冊節點資訊,並獲取DOM節點(1)

餓了麼專案---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)

    其實解釋起來很簡單,當把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