Vue組件化通訊

Vue組件化通訊

1. Vue的組成文件(.vue)

分為三部分,分別對應html,js,css

  • <template></template>
  • <script></script>
  • <style></style>

2. Vue的生命周期函數(watch的時候dom也沒有更新)

  1. beforeCreate() 創建數據之前
  2. created() 創建數據 我們在這里的得到我們在data里面創建的數據
  3. beforeMount() // Dom渲染完成前
  4. mounted() //Dom渲染完成
  5. beforeUpdate() // 更新視圖 在beforeUpdate觸發時,視圖已經更新完成
  6. Updated() //更新數據調用的函數、。
<div id='app'>
  <p>{{msg}}</p>
  <input type='text' v-model='msg'>
</div>

  
var app = new Vue({
  el: '#app',
  data() {
    return {
      msg: 1
    }
  },
  beforeCreate() {
    console.log('beforeCreate', this.msg); //beforeCreate undefined
    console.log('beforeCreate: ', document.getElementsByTagName('p')[0]) //beforeCreate <p>{{msg}}</p>
  },
  created() {
    // 創建數據
    console.log('created', this.msg); //beforeCreate 1 
    console.log('created: ', document.getElementsByTagName('p')[0]) //beforeCreate <p>{{msg}}</p>
    // 異步處理得到渲染的dom數據
    setTimeout(() => {
      this.msg = 100
      console.log('nextTick', document.getElementsByTagName('p')[0])  
    }, 100)
    // nextTick  <p>100</p>
  },
  beforeMount() {
    console.log('beforeMount', this.msg) //beforeMount 1
    console.log('beforeMount: ', document.getElementsByTagName('p')[0]) // beforeMount  <p>{{msg}}</p>
  },
  mounted() {
    // 渲染dom
    console.log('mounted', this.msg) //mounted 1
    console.log('mounted: ', document.getElementsByTagName('p')[0]) //mounted <p>1</p>
  },
  beforeUpdate() {
    console.log('beforeUpdate', this.msg) //beforeUpdate 100
    console.log('beforeUpdate: ', document.getElementsByTagName('p')[0]) //beforeUpdate <p>100</p>
  },
  updated() {
    console.log('updated', this.msg) // updated 1
    console.log('updated: ', document.getElementsByTagName('p')[0]) // updated <p>100</p>
  }
})

生命周期參考鏈接

3. export default

每一個模塊都是自己的作用域,相應的屬性來處理數據和函數

  1. data(聲明數據,可以是函數和屬性)
  • 類型Object | Function
  • 組件只接受函數
   // 對象的形式
   export default{
     data: {
       a:1
     }
   }
   // 函數的形式
   export default{
     data(){
       return {
         a: 1
       }
     }
   }
  1. methods(一些指令和其他屬性的調用方法)
    • 不要用箭頭函數來寫里面的函數
    • this指向Vue的實例
 export default{
   methods: {
     plus() {
       this.a++
     }
   }
 }
  1. components (組件化定義)
    • 類型: Object
    • 自定義元素,增加代碼的復用性
 // 當我們引用一個.vue文件的時候,就像使用這個文件來充當我們主體的一部分
 <div>
    <hello></hello>  
 </div>

 import hello from './hello.vue'
 export default {
   components: {
     hello
   }
 }
  1. computed(計算屬性)

    • 計算屬性的結果會被緩存,依賴的數據發生變化才會重新渲染
    • 注意計算屬性和methods,watch的區別
    {{this.total}} //[3,4]
    <button @click='add'>添加數據</button> //點擊會更新this.total    
    
    export default {
      data: () => ({
        a: 1,
        b: [2,3]
      }),
      methods: {
        add(){
          this.b.push(8);
        }
      },
      computed: {
        total(){
          return this.b.map((item)=>{
            return item+this.a
          })
        }
      }
    }
    
  2. watch(監聽對應的數據)

    • 鍵值對。鍵是我們需要監督的數據,值是相應的回調函數
    • 回調函數接受2個參數,新的值和舊的值(對于數組和對象不會出現舊值,對于簡單的數據會出現舊值)
    • 監聽對象的內部值變化,需要添加deep:true(數組不用)
    // 點擊后相應的變化
    data(){
        return {
          a: 1,
          b: [2,4,6],
          c:{name:'hcc',age:22}
        }
      },
    methods: {
       add(){
          this.a++
          this.b.push(8)
          this.c.name = 'yx'
        }
      },
    watch: {
        b: function(val, oldVal){
           console.log('new', val) //[2,4,6,8]
           console.log('new', oldVal) //[2,4,6,8]
        },
        a: function(val, oldVal){
          console.log(val);  //2
          console.log(oldVal); //1
        },
        c:{
          handler(val){
            console.log(val); //{name: 'yx',age: 22}
          } 
        }
    },
    
  3. props(用于接受父組件傳來的數據)

    • 規定和接受父組件的數據
    • 單向數據流,子組件不能修改傳遞過來的數據
    • 對象和數組是引用類型,指向同一個內存空間,如果 prop 是一個對象或數組,在子組件內部改變它會影響父組件的狀態。
    • 可以規定接受的數據類型和默認值,如果是對象和數組,默認值導出是一個函數
    // 父組件
    <hello :formParent='num'></hello>  //html
    components: {
      hello
    },
    data(){
      return {
        num: 3
      }
    }
    
    //子組件
    //1. 數組規定接受的數據
    props: ['hello']
    //2. 驗證的方式
    props:{
      hello: Number,
      hello: [String, Number],
      hello: {
        type: Object,
        default(){
          return {message: 'hello'}
        }
      }
    }
    
  4. v-on和v-emit(子組件向父元素傳遞數據)

    • vm.$emit: 子元素向父元素定義訊號和傳遞數據

      this.$emit('規定的訊號名稱', '想傳遞給父元素的數據')

    • vm.$on: 監聽訊號,并觸發相應的函數(函數內部不用傳參)

      @'規定的訊號名稱'='調用自己組件的方法并可以接受傳遞的參數'

    // 子組件
    data () {
      return {
        msg: 'Welcome to Your Vue.js App'
      }
    },
    methods: {
      change(){
        this.$emit('sendMsg',this.msg)  //把msg傳遞給父組件
      }
    }
    
    // 父組件
    // 引入子組件,并定義components
    components: {
      hello
    },
    methods: {
      show(msg){     // 這里接受子組件傳遞的參數
        console.log(msg);
      }
    }
    
    <hello @sendMsg='show'></hello>  // 這里不用傳遞參數,不然會覆蓋子元素傳遞的參數
    
  5. ref(用來獲取dom和子組件)

    • 可以用來操作dom<p ref="p">hello</p>

    • 可以用來組件中的通訊

    • 在組件中使用的this.refs是一個對象,包含了所有的綁定了的dom和子組件

      // html 
       <h1 ref="myElement">這是一個dom元素</h1>  //dom元素
       <hello :propnum="propnum" :obj='d' @getson='getMsg' ref='child'></hello> // 子組件
       >-- 組件中this.refs =>  {myElement: h1, child: VueComponent}
      
      // 運用(在父元素中調用子元素的方法)
      // html 
      <hello ref='child'></hello> 
      // 子元素hello
       methods: {
         change() {
           this.$emit('getson',this.msg)
           this.obj.name = 'yx'
         },
           drop(el) {
             el.style.background = 'red';
           }
       },
         
      // 父元素
      methods: {
        add() {
          console.log(this.refs); //{child: VueComponent}
          this.$refs.child.drop('這里傳遞父元素的dom節點')
        }
      }
      
      //如果有一個需求是,一個父元素有2個子組件,其中一個子組件的方法要調用另一個子組件的dom元素
      1. 一個子組件需要向父組件發送元素this.$emit('方法名',dom)
      2. 父元素接受到子組件的傳遞得到對應dom
      3. 父元素通過this.$refs調用對應的另一個子組件的方法并傳入參數
      // 子元素hello和world
        <div class="world">
          <h1 ref="world">這是world的dom元素</h1>
          <button @click='send'>給父元素傳遞dom</button>
        </div>
        methods: {
          send(){
            this.$emit('give',this.$refs.world); //給父元素發送dom
        }  
        <div class='hello'>
          <button>改變dom</button>
        </div>  
        methods: {
          changeDom(target){
            console.log(target)
          }
        }
          
        // 父元素
        <world @give='父親自己的方法'></world>
        <hello ref='helloChild'></hello>
        methods: {
          // 這里接受子元素傳遞過來的dom元素
          '父親自己的方法'(target) {
            this.refs.helloChild.changeDom(target)  //調用另一個子元素的方法,并把dom傳遞過去
          }
        }
      
  6. vm.nextTick(callback)

    • 下次dom更新循環結束后執行對應的回調函數

    • 在修改數據之后立即使用這個方法,可以獲取更新后的DOM結構

  • 使用場景
    • 在 Vue 生命周期的 created() 鉤子函數進行的 DOM 操作一定要放在 Vue.nextTick() 的回調函數中。原因是什么呢,原因是
      在 created() 鉤子函數執行的時候 DOM 其實并未進行任何渲染,而此時進行 DOM 操作無異于徒勞,所以此處一定要將 DOM 操作的 js 代碼放進 Vue.nextTick() 的回調函數中。
      與之對應的就是 mounted 鉤子函數,因為該鉤子函數執行時所有的 DOM 掛載和渲染都已完成,此時在該鉤子函數中進行任何DOM操作都不會有問題 。
    • 在數據變化后要執行的某個操作,而這個操作需要使用隨數據改變而改變的 DOM 結構的時候,這個操作都應該放進 Vue.nextTick() 的回調函數中。
// 需求一,如果我們想異步請求數據后,在鉤子函數mounted之前只用對應的dom
// 思路: 通過異步等dom更新后,然后獲得對應的dom
<template>
   <h1 ref='title'>{}</h1>
</template>
<script>
export default {
 data() {
      b: 'hello nextTick'
  },
  create() {
    console.log(this.refs.title)  // undefined
  }, 
// 這樣可以獲得對應的dom (當dom全部渲染后再執行console.log())
//  create() {
//   this.$nextTick(()=>{
//        console.log(this.refs.title);  // <h1>hello nextTick</h1>(輸出在mounted的后面)
//    })
//  }, 
  mounted() {
    console.log(this.refs.title)  // <h1>hello nextTick</h1>
  }
}
</script>

?

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,983評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,772評論 3 422
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,947評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,201評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,960評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,350評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,406評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,549評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,104評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,914評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,089評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,647評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,340評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,753評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,007評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,834評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,106評論 2 375

推薦閱讀更多精彩內容