花里胡哨的vue傳值

前言

在vue項目中,不可避免的會在不同組件之間進(jìn)行傳值 ,不同需求下有各式各樣的傳值方式。就比如說,兄弟組件傳值,父子子父之間傳值,路由傳值,ref方式傳值或者是共享狀態(tài)(數(shù)據(jù))等,一些花里胡哨的方式,都有各自使用場景且有可能不經(jīng)常使用導(dǎo)致容易忘記,故總結(jié)記之,方便自己以后更好運(yùn)用自如。

目錄

[TOC]

使用props傳值

  1. 簡單的示例
    父組件:
<template lang="html">
    <div class="">
      <h1>首頁</h1>
      <home1 :msg='str'></home1>
    </div>
</template>

<script>
import home1 from './home1'

export default {
  data(){
    return {
      str:'我是在父組件的數(shù)據(jù)通過props傳遞給子組件'
    }
  },
  components: {
    home1
  }
}
</script>
<style>
</style>

子組件:

<template>
  <div id="">
    <h2>{{msg}}</h2>
  </div>
</template>
<script>
export default {
  props: ['msg'],
  name: "",
  data: () => ({

  })
}
</script>
<style scoped>
</style>

小結(jié):通過以上代碼,就可以明顯看出,在子組件vue實例聲明props屬性以及在父元素中子組件進(jìn)行賦值操作,即可實現(xiàn)父子組件傳值。值得注意的是,也可通過在子組件中定義一個函數(shù),在父組件觸發(fā)這個函數(shù),也可達(dá)到父傳子的效果。詳情下料聊

  1. props實現(xiàn)子組件向父組件傳值,其原理實現(xiàn)如上小結(jié),實現(xiàn)時值得注意的是:
    • 在父組件中,傳值的是函數(shù)名,而不是函數(shù)的執(zhí)行結(jié)果
    • 在子組件中觸發(fā)函數(shù)時機(jī)時:通過this.函數(shù)名取得父傳子的函數(shù),并傳參(即是子向父傳遞的數(shù)據(jù))執(zhí)行。這樣父可以拿到子的數(shù)據(jù)。

父組件代碼如下:

<template lang="html">
    <div class="">
      <h1>首頁</h1>
      <home1 :fn='parent'></home1>
      <!-- 來展示從子組件傳來的值 -->
      <h2>{{ num }}</h2>
    </div>
</template>

<script>
import home1 from './home1'

export default {
  data(){
    return {
      // 來保存從子組件傳來的值
      num:''
    }
  },
  components: {
    home1
  },
  methods: {
    parent(data) {
      // 如果子組件觸發(fā)函數(shù)會調(diào)轉(zhuǎn)到父組件來執(zhí)行該函數(shù),即把傳遞進(jìn)來的參數(shù)賦值給vue實例中的data數(shù)據(jù)中的num變量中
      this.num = data;
    }
  }
}
</script>


<style media="screen">

</style>

子組件代碼如下:

<template>
  <div id="">
    <h2>hello</h2>
  </div>
</template>
<script>
export default {
  props: ['fn'],
  name: "",
  data: () => ({
    str:'我是子組件里面的數(shù)據(jù)要通過props傳遞給父組件'
  }),
  mounted() {
    //do something after mounting vue instance
    // 在子組件渲染完畢時,觸發(fā)從父組件傳遞過來的函數(shù)
    this.fn(this.str)
  }
}
</script>
<style scoped>
</style>

使用路由傳值

路由傳值:主要分為在同一路由下傳值(同一組件)和不同路由跳轉(zhuǎn)傳值(不同組件),其中重要知識點有:

  1. 路由傳參有兩種情況:編程式傳參和聲明式傳參,格式用法見下代碼實例
  2. 通過this.$route.params.? 來接收路由參數(shù)(這一般存放小數(shù)據(jù)),而this.$route.query.?來接收存放在路由的數(shù)據(jù),一般是存放大數(shù)據(jù)
  3. 當(dāng)然如果是同一路由下傳參,要配置路由如格式:{name:'home',path:'/home/:id',component:Home},...
  1. 同一路由下傳值實現(xiàn)代碼如下:
<template lang="html">
    <div class="">
      <h1>首頁</h1>
      <!-- 點擊路由鏈接向當(dāng)前路由傳遞參數(shù) -->
      <!-- 1.聲明式傳參 -->
      <router-link :to="{ name: 'home', params: { id: 'hello'}}">1</router-link>
      <!-- 2.編程式參參 -->
      <p @click='fn1'>2</p>
      <!-- 點擊按鈕獲取當(dāng)前url路徑的參數(shù) -->
      <button @click="fn" type="button" name="button">獲取動態(tài)路由參數(shù)</button>
      <h4>我是動態(tài)數(shù)據(jù):{{num}}</h4>
      <!-- 通過query中值獲得數(shù)據(jù) -->
      <h5>{{num1.name}}</h5>
      <h5>{{num1.age}}</h5>
    </div>
</template>

<script>
// import home1 from './home1'

export default {
  data(){
    return {
      num:'',
      // 在路由的query對象存放大量數(shù)據(jù)方便存取
      num1:''
    }
  },
  methods: {
    // 點擊按鈕獲取當(dāng)前url路徑的參數(shù)的函數(shù)
    fn() {
      this.num = this.$route.params.id;
      this.num1 = this.$route.query;
    },
    // 點擊’2‘后,進(jìn)行編程式路由跳轉(zhuǎn)并傳遞參數(shù)
    fn1() {
      this.$router.push(
        {name:'home',params:{id:'world'},query:{
          name:'zhangsna',
          age:23
        }}
      )
    }
  },
  components: {
    // home1
  }
}
</script>


<style media="screen">

</style>


  1. 不同路由下實現(xiàn)傳值:
    跳轉(zhuǎn)前路由組件代碼如下:
<template lang="html">
    <div class="">
      <h1 @click='fn'>首頁</h1>

    </div>
</template>

<script>
export default {
  data(){
    return {
      num:''
    }
  },
  methods: {
    fn(){
      this.$router.push({
        name:'car',
        query:{
          name:'xioahang',
          age:23
        }
      })
    }
  }
}
</script>

<style media="screen">
</style>

調(diào)轉(zhuǎn)后路由組件代碼如下

<template lang="html">
    <div class="car">
      <h1>我的購物車</h1>
      <h2>{{ msg.name }}</h2>
      <h2>{{ msg.age }}</h2>
    </div>

</template>

<script>
export default {
  data() {
    return {
      msg:{}
    }
  },
  created() {
    //do something after creating vue instance
    this.msg = this.$route.query
  }
}
</script>


<style media="screen">

</style>

使用ref方式傳值

盡管有props和events,但是仍然需要在JavaScript中直接訪問子組件。為此可以使用ref為子組件指定一個索引ID。
值得注意的是:ref的屬性所對應(yīng)的屬性值是一個固定值,不是一個變量。因為ref不是動態(tài)更新的

用法非常簡單,示例如下:
父組件:

<template lang="html">
    <div class="">
      <h1>首頁</h1>
      <!-- 在子組件書寫ref屬性以及值 -->
      <home1 ref='mark'></home1>
      <!-- 在父組件中,測試從子組件拿到的值 -->
      <h2>通過ref來拿到子組件的數(shù)據(jù)傳遞給 {{num}}</h2>
    </div>
</template>

<script>
// 導(dǎo)入子組件
import home1 from './home1'

export default {
  data(){
    return {
      num:''
    }
  },
  methods: {

  },
  components: {
    home1
  },
  mounted() {
    // 向子組件拿到的數(shù)據(jù)賦值給父vue實例中的變量
    this.num = this.$refs.mark.str;
    // 在父組件中,測試從子組件拿到的函數(shù)
    this.$refs.mark.fn();
  }

}
</script>

<style media="screen">
</style>

子組件:

<template>
  <div id="">
    <h2>hello</h2>
  </div>
</template>
<script>
export default {
  name: "",
  data: () => ({
    str:'我是子組件里面的數(shù)據(jù),父組件通過ref來向子組件拿值'
  }),
  methods: {
    fn() {
      console.log('我是子組件的方法,父組件可通過ref來拿到我這里的值!');
    }
  }
}
</script>
<style scoped>
</style>

使用BUS傳值

BUS傳值主要運(yùn)用了events事件的原理。實現(xiàn)步驟如下:首先,在定義一個第三方的vue實例并導(dǎo)出,然后通過BUS.$on()來注冊事件,其中里面的函數(shù)中this的指向格外注意,普通函數(shù)this指向BUS,而不是當(dāng)前的vue實例,可使用es6的箭頭函數(shù),它的this指向當(dāng)前的vue實例。最后在傳值的那個組件,使用BUS.$emit()觸發(fā)事件并傳值,即可實現(xiàn)兩個組件之間的傳值。一般用于兄弟組件之間傳值及父子子父之間傳值等

以下實例通過BUS實現(xiàn)父子傳值:

import Vue from 'vue'
export default new Vue()
<template lang="html">
    <div class="">
      <h1>首頁</h1>
      <home1></home1>
      <h1>我是通過bus事件傳遞過來的值為:{{num}}</h1>
    </div>
</template>

<script>
// 導(dǎo)入Busvue實例
import Bus from '../bus'
import home1 from './home1'

export default {
  data(){
    return {
      num:''
    }
  },
  methods: {

  },
  components: {
    home1
  },
  created() {
    Bus.$on('sendVal',(data) => {
      this.num = data
    });
  }

}
</script>

<style media="screen">
</style>

<template>
  <div id="">
    <h2>hello</h2>
  </div>
</template>
<script>
import Bus from '../bus'

export default {
  name: "",
  data: () => ({
    str:'我是這個子組件中的數(shù)據(jù)'
  }),
  methods: {
    fn() {
    }
  },
  created() {
    //do something after creating vue instance
    Bus.$emit('sendVal',this.str)
  }
}
</script>
<style scoped>
</style>

通過$parent,$children方法來拿值

通過$parent,$children方法調(diào)取層級關(guān)系的組件內(nèi)的數(shù)據(jù)和方法,該方法的弊端,就是增強(qiáng)組件之間的耦合,不利于組件的復(fù)用

使用$parent,$children來進(jìn)行父子子父之間傳值
父組件代碼:

<template lang="html">
    <div class="">
      <h1>首頁</h1>
      <home1></home1>
      <p>{{num1}}</p>
    </div>
</template>

<script>
import home1 from './home1'

export default {
  data(){
    return {
      num:'我是父組件的數(shù)據(jù)',
      num1:''
    }
  },
  methods: {
    parentFn(){
      console.log('我是父組件的方法');
    }
  },
  components: {
    home1
  },
  mounted() {
      // console.log(this.$children);
      // 值得注意的是 this.$children 獲取到是一個數(shù)組,并非是一個對象
      this.num1 = this.$children[0].$data.str  // 獲取子組件的數(shù)據(jù)
      this.$children[0].sonFn()  // 獲取子組件的方法
  }

}
</script>

<style media="screen">
</style>

子組件代碼:

<template>
  <div id="">
    <h2>hello</h2>
    <h4>{{str1}}</h4>
  </div>
</template>
<script>

export default {
  name: "",
  data: () => ({
    str:'我是這個子組件中的數(shù)據(jù)',
    str1:''
  }),
  methods: {
    sonFn() {
      console.log('我是子組件的方法');
    }
  },
  created() {
    //do something after creating vue instance
    // 獲取父組件的數(shù)據(jù)
    this.str1 = this.$parent.num;
    // 獲取父組件的方法
    this.$parent.parentFn()
  }
}
</script>
<style scoped>
</style>

vue原型傳值

vue原型同js對象有著的原型鏈,故向vue組件中存放值與方法,子組件即可通過原型鏈獲取值與方法

import Vue from 'vue'
Vue.prototype.num =  'test prototype'
Vue .prototype.sayFn = function () { console.log('hello world!'); }

使用localStorage或sessionStorage存儲

localStorage、sessionStorage以及cookie存儲,都是js實現(xiàn)本地存儲的方式 。實現(xiàn)方法如下:
保存數(shù)據(jù):

  1. sessionStorage.setItem(key,value)
  2. localStorage.setItem(key,value)
    讀取數(shù)據(jù):
  3. var v = sessionStorage.getItem(key)
  4. var v = localStorage.getItem(key)
    移除數(shù)據(jù):
  5. sessionStorage.removeItem(key)
  6. localStorage.removeItem(key)
    清除數(shù)據(jù):
  7. sessionStorage.clear()
  8. localStorage.clear()

利用vue-x方式進(jìn)行傳值

vue-x是vue的共享狀態(tài)(即數(shù)據(jù))的模塊,官網(wǎng)介紹為:Vuex 是一個專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。

  1. 一個表示“單向數(shù)據(jù)流”理念的極簡示意:
    image

    當(dāng)我們的應(yīng)用遇到多個組件共享狀態(tài)時,單向數(shù)據(jù)流的簡潔性很容易被破壞,故使用vuex如下圖所示:
image

2.其中核心概念有:
* state:存放狀態(tài),即數(shù)據(jù)
* mutations:存放改變state數(shù)據(jù)的同步方法
* actions:存放改變state數(shù)據(jù)的異步方法
* getters:相當(dāng)于計算屬性,避免了直接向state數(shù)據(jù)取值

  1. 代碼具體實現(xiàn)如下:

首先創(chuàng)建store實例

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

export default new Vuex.Store({
  state:{
    // 共享狀態(tài)
    num:0
  },
  mutations:{
    addNum(state,step){
      state.num += step;
    },
    reduceNum(state,step){
      state.num -= step;
    }
  },
  actions:{

  },
  getters:{
    getNum(state){
      return state.num
    }
  }
})

在任意組件中,取共享狀態(tài)中數(shù)據(jù)

<template lang="html">
    <div class="">
      <h1>首頁</h1>
      <p>{{getNum}}</p>
      <button @click='fn' type="button" name="button">點我增加共享數(shù)據(jù)</button>
      <button @click='fn1' type="button" name="button">點我減少共享數(shù)據(jù)</button>
    </div>
</template>

<script>

export default {
  data(){
    return {
      num:''
    }
  },
  methods: {
    fn(){
      this.$store.commit('addNum',1)
    },
    fn1(){
      this.$store.commit('reduceNum',1)
    }
  },
  components: {

  },
  computed:{
    getNum(){
      return this.$store.state.num;
    }
  },
  created() {
    //do something after creating vue instance

  }

}
</script>

<style media="screen">
</style>

生活寄語

愛代碼,愛生活!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容