超詳細!Vue的九種通信方式


1,父傳子 props


子組件中定義props字段,類型為數組(如果需要限制字段值類型,也可以定義為對象的形式)。如下圖的例子,父組件掛載子組件HelloWorld,在組件標簽上給title賦值,子組件HelloWorld定義props,里面有一個值是title,這樣子組件就可以使用父組件的值了。

父組件

<template>
  <div>
    <HelloWorld :title="msg" />
  </div>
</template>

<script>
import HelloWorld from "../components/HelloWorld.vue";

export default {
  name: "Home",
  data() {
    return {
      msg: "搜索音樂",
    };
  },
  components: {
    HelloWorld,
  },
};
</script>

子組件

<template>
  <div class="hello">
    <h1>{{ title }}</h1>
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  props:["title"],
  data() {
    return {};
  },
};
</script>

2,子傳父 $emit


子傳父,需要在子組件中觸發一個事件,在事件中,調用$emit('父組件的方法名', '傳遞的值'),然后在父組件中,通過自定義事件接收傳遞過來的值。

子組件

<template>
  <div class="hello">
    <h1 @click="add">{{ title }}</h1>
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  props: ["title"],
  data() {
    return {
      age:18
    };
  },
  methods: {
    add(){
      this.$emit("childEvent", this.age);
    }
  },
};
</script>

父組件

<template>
  <div>
    <HelloWorld @childEvent="parentEvent" :title="msg" />
  </div>
</template>

<script>
import HelloWorld from "../components/HelloWorld.vue";

export default {
  name: "Home",
  data() {
    return {
      msg: "搜索音樂",
    };
  },

  methods: {
    parentEvent(e) {
      console.log(e);
    },
  },
  components: {
    HelloWorld,
  },
};
</script>

3,兄弟組件傳值 eventBus


1,先新建一個bus.js文件,在bus.jsnew一個Vue實例,充當傳輸數據的中間層。

import Vue from 'vue';
export default new Vue;

2,在組件A中引入bus.js,通過bus.$emit('事件名','參數')傳遞參數

<template>
  <div class="hello">
    <h1 @click="add">{{ title }}</h1>
  </div>
</template>

<script>
import bus from "../publicFn/bus.js";

export default {
  name: "HelloWorld",
  props: ["title"],
  data() {
    return {
      age:18
    };
  },
  methods: {
    add(){
      bus.$emit("childEvent", this.age);
    }
  },
};
</script>

3,在B組件mounted周期中使用$on('事件名', function(){})接收

<template>
  <div id='swiper'>
    <button>我是按鈕</button>
  </div>
</template>

<script>

import bus from "../publicFn/bus.js";

export default {
  name:'Swiper',
  data (){
    return {

    }
  },
  mounted(){
    bus.$on("childEvent", (e) => {
      console.log(e)
    })
  }
}
</script>

4,父組件使用子組件的數據和方法 $refs


1,在子組件標簽上寫上ref屬性

2,父組件通過this.$refs.id.方法名或者this.$refs.id.屬性名的方式可以訪問子組件。

父組件

<template>
  <div>
    <HelloWorld :title="msg" ref="hello" />
    <button @click="parentEvent">我是父親</button>
  </div>
</template>

<script>
import HelloWorld from "../components/HelloWorld.vue";

export default {
  name: "Home",
  data() {
    return {
      msg: "搜索音樂",
    };
  },

  methods: {
    parentEvent() {
      this.$refs.hello.add();
      console.log(this.$refs.hello.age);
    },
  },
  components: {
    HelloWorld
  },
};
</script>

子組件

<template>
  <div class="hello">
    <h1>{{ title }}</h1>
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  props: ["title"],
  data() {
    return {
      age:18
    };
  },
  methods: {
    add(){
      console.log("我是子組件");
    }
  },
};
</script>

5,子組件使用父組件的數據和方法 $parent


在子組件中,可以使用$parent訪問其上級父組件的數據和方法,如果是多重嵌套,也可以使用多層$parent

父組件

<template>
  <div>
    <HelloWorld :title="msg" ref="hello" />
  </div>
</template>

<script>
import HelloWorld from "../components/HelloWorld.vue";

export default {
  name: "Home",
  data() {
    return {
      msg: "搜索音樂",
    };
  },

  methods: {
    parentEvent() {
      console.log("我是父組件的方法");
    },
  },
  components: {
    HelloWorld
  },
};
</script>

子組件

<template>
  <div class="hello">
    <h1 @click="add">{{ title }}</h1>
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  props: ["title"],
  data() {
    return {
      age:18
    };
  },
  methods: {
    add(){
      console.log(this.$parent.msg)
      this.$parent.parentEvent();
    }
  },
};
</script>

6,Vuex傳值


Vuex 是一個專為 Vue.js 應用程序開發的狀態管理模式。它采用集中式存儲管理應用的所有組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。一般小項目不需要用到。

6.1,定義store

import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    school: "清華大學",
    a:"nice"
  },
  getters: {
    returnVal(state) {
      return state.school + state.a;
    },
  },
  mutations: {
    changeSchool(state, val) {
      state.school = val;
      console.log('修改成功');
    },
  },
  actions: {},
  modules: {}
});

6.2,掛載

import Vue from 'vue';
import App from './App.vue';
import router from "./router";
import store from "./store";
import ElementUI from "element-ui";
import "element-ui/lib/theme-chalk/index.css";
import publicFn from "./publicFn/publicFn";

Vue.config.productionTip = false


const url = process.env.VUE_APP_URL;
Vue.prototype.$url = url;
Vue.prototype.$publicFn = publicFn;

Vue.use(ElementUI);

new Vue({
  router,
  store,
  render: h => h(App),
}).$mount('#app')

6.3,使用

<template>
  <div class="hello">
    <h1 @click="add">{{ title }}</h1>
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  props: ["title"],
  data() {
    return {
      age:18
    };
  },
  methods: {
    add(){
      console.log(this.$store.state.school);//獲取值
      //this.$store.commit('changeSchool', '北京大學');//修改值
      // console.log(this.$store.getters.returnVal)//獲取過濾后的值
    }
  },
};
</script>

7,祖先組件傳子組件 provide / inject


允許一個祖先組件向其所有子孫后代注入一個依賴,不論組件層次有多深,並在其上下游關系成立的時間里始終生效

注意:provide 和 inject 綁定並不是可響應的,然而,如果你傳入了一個可監聽的對象,那么其對象的 property 還是可響應的

7.1,祖先組件通過provide注入值

<template>
	<div id="communication">
		<Head :keys="keys" />
	</div>
</template>

<script>
import Head from '../../components/head'

export default {
	name: 'Communication',
	components: {
		Head
	},
	provide() {
		return {
			obj: this.obj
		}
	},
	data() {
		return {
			title: 'hello world',
			keys: 1998,
			obj: {
				set: 'hello provide'
			}
		}
	}
}
</script>

父組件

<template>
	<div id="head">
		<div class="head_box">
			<Title :value="index" />
		</div>
	</div>
</template>

<script>
import Title from '../title'

export default {
	name: 'Head',
	components: {
		Title
	},
	data() {
		return {
			index: 'WoW'
		}
	}
}
</script>

7.2,子組件通過inject拿到值

<template>
	<div id="title">
		<div class="title_box">
			<p>我是 {{ obj.set }}</p>
		</div>
	</div>
</template>

<script>
export default {
	name: 'Title',
	inject: {
		obj: {
			from: 'Communication',
			default: {}
		}
	},
	data() {
		return {
			index: 1
		}
	}
}
</script>

8,爺爺組件傳孫子組件 $attrs / $listeners


8.1,$attrs

包含了父作用域中不作為prop被識別獲取)的attribute綁定(class 和 style 除外)

爺爺組件

<template>
	<div id="communication">
		<Head :keys="keys" num="3000" />
	</div>
</template>

<script>
import Head from '../../components/head'

export default {
	name: 'Communication',
	components: {
		Head
	},
	data() {
		return {
			keys: 1998
		}
	}
}
</script>

父親組件

<template>
	<div id="head">
		<div class="head_box">
			<Title v-bind="$attrs" />
		</div>
	</div>
</template>

<script>
import Title from '../title'

export default {
	name: 'Head',
	components: {
		Title
	},
	data() {
		return {}
	}
}
</script>

孫子組件

<template>
	<div id="title">
		<div class="title_box">
			<p>爺爺的值:{{ $attrs.keys }}</p>
			<p>爺爺的值:{{ $attrs.num }}</p>
		</div>
	</div>
</template>

<script>
export default {
	name: 'Title',
	data() {
		return {}
	}
}
</script>

8.2,$listeners

包含了父作用域中的 (不含 .native 修飾器的) v-on 事件監聽器

爺爺組件

<template>
	<div id="communication">
		<Head :keys="keys" @handleChildAdd="handleAdd" />
	</div>
</template>

<script>
import Head from '../../components/head'

export default {
	name: 'Communication',
	components: {
		Head
	},
	data() {
		return {
			keys: 1998
		}
	},
	methods: {
		// 父組件的事件
		handleAdd() {
			this.keys++
		}
	}
}
</script>

父親組件

<template>
	<div id="head">
		<div class="head_box">
			<Title v-bind="$attrs" v-on="$listeners" />
		</div>
	</div>
</template>

<script>
import Title from '../title'

export default {
	name: 'Head',
	components: {
		Title
	},
	data() {
		return {}
	}
}
</script>

孫子組件

<template>
	<div id="title">
		<div class="title_box">
			<p>爺爺的值:{{ $attrs.keys }}</p>
			<span @click="chlidEvent">點擊觸發爺爺的事件</span>
		</div>
	</div>
</template>

<script>
export default {
	name: 'Title',
	data() {
		return {}
	},
	methods: {
		chlidEvent() {
			// 通過$emit調用爺爺的方法
			this.$emit('handleChildAdd')
		}
	}
}
</script>

9,路由傳值


9.1 通過query傳值

注意:該方式刷新頁面參數不丟失,並且會在地址欄后將參數顯露,http://localhost:9000/#/conter?id=10086&name=%E9%B9%8F%E5%A4%9A%E5%A4%9A

頁面A

<template>
  <div>
    <HelloWorld :title="msg" ref="hello" />
    <button @click="parentEvent">跳轉</button>
  </div>
</template>

<script>
import HelloWorld from "../components/HelloWorld.vue";

export default {
  name: "Home",
  data() {
    return {
      msg: "搜索音樂",
    };
  },

  methods: {
    parentEvent() {
      this.$router.push({
        path:"/conter",
        name:'conter',
        query:{
          id:10086,
          name:"鵬多多"
        }
      })
    },
  },
  components: {
    HelloWorld
  },
};
</script>

頁面B

<template>
  <div id='conter'>

  </div>
</template>

<script>

export default {
  name:'conter',
  data (){
    return {

    }
  },
  created (){
    console.log(this.$route.query.id, this.$route.query.name);
  },
}
</script>

9.2 通過params傳值

注意:該方式刷新頁面參數會丟失,可以接收后存在sessionStorage

A頁面

<template>
  <div>
    <HelloWorld :title="msg" ref="hello" />
    <button @click="parentEvent">跳轉</button>
  </div>
</template>

<script>
import HelloWorld from "../components/HelloWorld.vue";

export default {
  name: "Home",
  data() {
    return {
      msg: "搜索音樂",
    };
  },

  methods: {
    parentEvent() {
      this.$router.push({
        path:"/conter",
        name:"conter",
        params:{
          id:10086,
          name:"鵬多多"
        }
      })
    },
  },
  components: {
    HelloWorld
  },
};
</script>

B頁面

<template>
  <div id='conter'>

  </div>
</template>

<script>

export default {
  name:'conter',
  data (){
    return {

    }
  },
  created (){
    console.log(this.$route.params.id, this.$route.params.name);
  },
}
</script>

如果看了覺得有幫助的,我是@鵬多多,歡迎 點贊 關注 評論;
END

面向百度編程

往期文章

個人主頁


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM