Rumah > Artikel > hujung hadapan web > Bagaimana untuk berkomunikasi antara komponen Vue? Beberapa cara komunikasi komponen
VueBagaimana untuk berkomunikasi antara komponen? Artikel berikut akan memperkenalkan anda kepada kaedah komunikasi komponen Vue saya harap ia akan membantu anda!
Dua ciri utama vue ialah pengaturcaraan responsif dan komponenisasi. Komponen ialah fungsi teras Vue, tetapi skop setiap contoh komponen adalah bebas antara satu sama lain, yang bermaksud bahawa data antara komponen berbeza tidak boleh merujuk secara langsung antara satu sama lain. Jika anda ingin merujuk data merentas komponen, anda perlu menggunakan komunikasi komponen Sebelum berkomunikasi, anda mesti terlebih dahulu memahami hubungan antara komponen:
Seperti yang ditunjukkan dalam rajah di atas:
Hubungan bapa-anak: A dan B, A dan C, B dan D, C dan E
Hubungan abang: B dan C
Hubungan pemisahan generasi (mungkin lebih banyak generasi berbeza): A dan D, A dan E
Hubungan merentas peringkat: B dan E, D dan E, dsb.
props
$emit
dan komponen anak menerima data daripada komponen induk melalui v-bind
komponen anak mencetuskan peristiwa melalui props
, dan komponen induk menggunakan $emit
atau dalam Gunakan on()
pada teg tersuai subkomponen untuk mendengar peristiwa tersuai yang dicetuskan oleh subkomponen untuk menerima data daripada subkomponen. (Belajar perkongsian video: v-on
tutorial video vue)
kepada child.vue anak dan memaparkannya dalam child.vue books:['JavaScript高级程序设计', 'CSS新世界', '图解 HTTP 彩色版']
// 父组件parent.vue <template> <div> <child></child> </div> </template> <script> import Child from './components/Child.vue' export default { name: 'parent', components: { Child }, data() { return { books: ['JavaScript高级程序设计', 'CSS新世界', '图解 HTTP 彩色版'] } } } </script>
// 子组件child.vue <template> <div> <ul> <li>{{item}}</li> </ul> </div> </template> <script> export default { props: { books: { type: Array, default: () => { return [] } } } } </script>
Nota: Penghantaran data melalui prop adalah sehala Apabila data komponen induk berubah, ia akan dihantar kepada komponen anak, tetapi komponen anak tidak boleh mengubah suai keadaan komponen induk yang sepadan dengan mengubah suai data yang diluluskan. oleh props, yang dipanggil aliran data sehala.
, dan kemudian dapatkan $emit()
// 子组件child.vue <template> <div> <ul> <li>{{item}}</li> </ul> </div> </template> <script> export default { props: { books: { type: Array, default: () => { return [] } } }, methods: { like(item) { this.$emit('likeBook', item) } } } </script>daripada komponen induk
// 父组件parent.vue <template> <div> <child></child> </div> </template> <script> import Child from './components/Child.vue' export default { name: 'parent', components: { Child }, data() { return { books: ['JavaScript高级程序设计', 'CSS新世界', '图解 HTTP 彩色版'] } }, methods: { likeBook(val) { alert('我最喜欢的书籍是《' + val + '》') } } } </script>2
$parent
$children
// 父组件parent.vue <template> <div> <child></child> <button>获取子组件数据</button> </div> </template> <script> import Child from './components/Child.vue' export default { name: 'parent', components: { Child }, data() { return { books: ['JavaScript高级程序设计', 'CSS新世界', '图解 HTTP 彩色版'] } }, methods: { getChildData() { alert(this.$children[0].msg) } } } </script>
// 子组件child.vue <template> <div> <ul> <li>{{item}}</li> </ul> </div> </template> <script> export default { name: 'child', data() { return { bookLists: [], msg: '我是子组件的值!' } }, mounted() { this.bookLists = this.$parent.books } } </script>Nota:
mendapat objek Jika ia adalah komponen peringkat teratas tanpa komponen induk, ia mendapat $parent
; undefined
mendapatnya Ia adalah tatasusunan Jika tiada sub-komponen pada lapisan bawah, anda akan mendapat tatasusunan kosong ini hanya boleh digunakan untuk komunikasi komponen induk-anak $children
ref
// 父组件parent.vue <template> <div> <child></child> <button>获取子组件数据</button> </div> </template> <script> import Child from './components/Child.vue' export default { name: 'parent', components: { Child }, methods: { getChildData() { const msg = this.$refs['child'].msg console.log(msg) this.$refs['child'].say() } } } </script>
// 子组件child.vue <script> export default { name: 'child', data() { return { msg: '我是子组件的值!' } }, methods: { say() { alert('你好,我是子组件!') } }, } </script>4
provide
inject
, dan komponen keturunan. menyuntik pembolehubah melalui provide
untuk mendapatkan data komponen nenek moyang, tidak kira sedalam mana komponen keturunan bersarang Selagi suntikan dipanggil, data dalam menyediakan boleh disuntik. Berikut ialah kod khusus: inject
// 父组件 <template> <div> <h1>康熙</h1> <son></son> </div> </template> <script> import Son from './components/Son.vue' export default { components: { Son }, provide() { return { FatherToSon: this.FatherToSon, FatherToGrandson: this.FatherToGrandson, } }, data() { return { FatherToSon: '我是康熙,雍正,你是我儿子!', FatherToGrandson: '我是康熙,乾隆,你是我孙子!', } } } </script>
// 子组件 <template> <div> <h1>雍正</h1> <button>接收</button> <grandson></grandson> </div> </template> <script> import Grandson from './Grandson.vue' export default { components: { Grandson }, inject: ['FatherToSon'], methods: { receive() { alert(this.FatherToSon) } } } </script>
// 孙组件 <template> <div> <h1>乾隆</h1> <button>接收</button> </div> </template> <script> export default { inject: ['FatherToGrandson'], methods: { receive() { alert(this.FatherToGrandson) } } } </script>
Nota: berikan/suntik hanya boleh menghantar nilai dari atas ke bawah dan tidak responsif Kepada menjadi respons Jenis data yang disediakan perlu menyediakan fungsi
eventBus
/$emit
$on
eventBus juga dipanggil bas acara. Dalam Vue, eventBus boleh digunakan sebagai konsep jambatan komunikasi Ia seperti semua komponen berkongsi pusat acara yang sama dan boleh mendaftar untuk menghantar acara atau menerima acara ke pusat, jadi komponen boleh memberitahu komponen lain secara selari ke atas dan ke bawah.
$emit('name',args)
: name:发布的消息名称 , args:发布的消息$on('name',fn)
: name:订阅的消息名称, fn: 订阅的消息$once('name',fn)
: name:订阅的消息名称, fn: 订阅的消息。与$on相似但是只触发一次,一旦触发之后,监听器就会被移除$off('name',callback)
:name:事件名称,callback:回调监听器
eventbus可以实现任何组件之前的通信,下面以兄弟组件为例
// main.js // 全局添加事件总线 Vue.prototype.$bus = new Vue()
在parent.vue引入ChildA和ChildB组件,使它们成为兄弟组件
// 父组件parent.vue <template> <div> <childa></childa> <childb></childb> </div> </template> <script> import ChildA from './components/childA' import ChildB from './components/childB' export default { components: { ChildA, ChildB } } </script>
在ChildA组件中用$emit
发送事件
// ChildA组件 <template> <div> <h1>组件A</h1> <button>发送</button> </div> </template> <script> export default { methods: { // 发送事件 send() { this.$bus.$emit('message', '欢迎使用eventBus!') } } } </script>
在ChildB组件中用$on
接收ChildA发送的事件
// ChildB组件 <template> <div> <h1>组件B</h1> </div> </template> <script> export default { mounted() { // 接收事件 this.$bus.$on('message', data => { alert('我是组件B,我收到的消息为:' + data) }) }, beforeDestroy() { this.$bus.$off('message') } } </script>
注意:$on
监听的事件不会自动移除监听,因此在不用时最好使用$off
移除监听以免产生问题
$attrs
/$listeners
当组件为两级嵌套时,一般采用props
和$emit
,但遇到多级组件嵌套时这种方法就不太适用了,如果不做中间处理,只传递数据用Bagaimana untuk berkomunikasi antara komponen Vue? Beberapa cara komunikasi komponen有点大材小用了。因此在vue2.4
中为了解决这一需求,便引入了$attrs
和$listeners
, 新增了inheritAttrs
属性
$attrs
:当父组件传递了很多数据给子组件时,子组件没有声明props来进行接收,么子组件中的attrs属性就包含了所有父组件传来的数据(除开已经props声明了的);子组件还可以使用v−bind="$attrs"
的形式将所有父组件传来的数据(除开已经props声明了的)传向下一级子组件,通常和interitAttrs
属性一起使用。$listeners
:包含了父组件中(不含.native
修饰器的)v-on 事件监听器,通过v-on="$listeners"
,可以将这些事件绑定给它自己的子组件
下面看一个例子:
// 父组件 <template> <div> <childa></childa> </div> </template> <script> import ChildA from './components/childA' export default { name: 'parent', components: { ChildA, }, data() { return { name: '小明', age: 18, sex: '男' } }, methods: { // 获取名字 getName() { console.log('我的名字是' + this.name) }, // 获取年龄 getAge() { console.log('我今年' + this.age + '岁'); } } } </script>
// 子组件A <template> <div> <h1>组件A</h1> {{ msgA }} <hr> <childb></childb> </div> </template> <script> import ChildB from './childB.vue' export default { name: 'ChildA', components: { ChildB }, data() { return { msgA: null, height: '175cm' } }, props: { sex: { type: String, default: '' } }, mounted() { this.msgA = this.$attrs console.log('组件A获取的$listeners:', this.$listeners) }, methods: { // 获取身高 getHeight() { console.log('我的身高是' + this.height); } } } </script>
// 孙组件B <template> <div> <h1>组件B</h1> {{ msgB }} </div> </template> <script> export default { name: 'ChildB', data() { return { msgB: null } }, mounted() { this.msgB = this.$attrs console.log('组件B获取的$listeners:', this.$listeners) } } </script>
$attrs获取的结果:
$listeners获取的结果:
如代码和图所示组件A中props
声明接收了sex属性,因此组件中$attrs
获取的是父组件中绑定的除去sex属性的值;组件A中使用了v-bind="$attrs"
和v-on="$listeners"
,则组件B获取不仅是组件A中本身绑定的属性和方法还包含组件A获取父组件绑定的属性和方法
如果父组件传递了很多参数给子组件,而子组件没有用props完全接收,那么没有接收的这些属性作为普通的 HTML attribute
应用在子组件的根元素上
如果你不希望子组件的根元素继承特性,你可以在组件的选项中设置inheritAttrs: false
以上面的组件B为例,当Bagaimana untuk berkomunikasi antara komponen Vue? Beberapa cara komunikasi komponen(inheritAttrs默认为true)
当Bagaimana untuk berkomunikasi antara komponen Vue? Beberapa cara komunikasi komponen
// 孙组件B export default { name: 'ChildB', inheritAttrs: false, data() { return { msgB: null } }, mounted() { this.msgB = this.$attrs console.log('组件B获取的$listeners:', this.$listeners) } }
Vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
状态管理包含以下几个部分:
视图发生变化会导致数据源的改变,数据源发生变化则会改变视图,则上面表示是一个“单向数据流”。但是当我们的应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏:
因此,为了解决这种问题我们把组件的共享状态抽取出来,以一个全局单例模式管理。在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为!
通过定义和隔离状态管理中的各种概念并通过强制规则维持视图和状态间的独立性,我们的代码将会变得更结构化且易维护。
1、state
:存储应用中需要共享的状态,是Vuex中的唯一数据源。
2、getters
:类似Vue中的计算属性computed
,getter 的返回值会根据它的依赖被缓存起 来,且只有当它的依赖值发生了改变才会被重新计算。
3、mutations
:更改 Vuex 的 store 中的状态(state)的唯一方法,且mutation 必须是同步函数
4、actions
:类似于 mutation,提交的是 mutation,而不是直接变更状态;可以包含任意异步操作
5、modules
:将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割
// 父组件 <template> <div> <h1>父组件</h1> <hr> <childa></childa> <hr> <childb></childb> </div> </template> <script> import ChildA from './components/ChildA' import ChildB from './components/ChildB' export default { name: 'parent', components: { ChildA, ChildB } } </script>
// 子组件A <template> <div> <h1>组件A</h1> <p>A获取的值: {{ count }}</p> <button>ChildA-add</button> </div> </template> <script> export default { computed: { count() { return this.$store.state.count } }, methods: { // 改变store里count的值 add(num) { this.$store.dispatch('countAdd', num) } } } </script> <style> </style>
// 子组件B <template> <div> <h1>组件B</h1> <p>B获取的值: {{ countB }}</p> <button>ChildB-add</button> </div> </template> <script> import { mapMutations, mapGetters } from 'Bagaimana untuk berkomunikasi antara komponen Vue? Beberapa cara komunikasi komponen' export default { computed: { ...mapGetters({ countB: 'getCount' }) }, methods: { ...mapMutations(['countAdd']), // 改变store里count的值 add(num) { this.countAdd(num) } } } </script> <style> </style>
store.js
import Vue from 'vue' import Vuex from 'Bagaimana untuk berkomunikasi antara komponen Vue? Beberapa cara komunikasi komponen' Vue.use(Vuex) export default new Vuex.Store({ state: { count: 0, }, getters: { getCount: (state) => { return state.count } }, mutations: { countAdd(state, num) { state.count += num } }, actions: { countAdd(context, num) { context.commit('countAdd', num) } }, modules: { } })
localStorage
/sessionStorage
localStorage:本地存储对象,存储的数据是永久性数据,页面刷新,即使浏览器重启,除非主动删除不然存储的数据会一直存在
sessionStorage:与localStorage相似,但是只有在当前页面下有效,关闭页面或浏览器存储的数据将会清空
localStorage和sessionStorage常用的API:
setItem (key, value) —— 保存数据,以键值对的方式储存信息。 getItem (key) —— 获取数据,将键值传入,即可获取到对应的value值。 removeItem (key) —— 删除单个数据,根据键值移除对应的信息。 clear () —— 删除所有的数据 key (index) —— 获取某个索引的key
// 存储 setItem() { window.localStorage.setItem('name1', '小明') window.sessionStorage.setItem('name2', '小红') }
// 接收 receive() { const name1 = window.localStorage.getItem('name1') const name2 = window.sessionStorage.getItem('name2') console.log(name1) // 打印结果为:小明 console.log(name2) // 打印结果为:小红 }
localStorage和sessionStorage通过setItem()
存储数据会自动转换为String
类型,但是通过getItem()
其类型并不会转换回来(localStorage和sessionStorage使用方法一样,下面均以localStorage为例)
const num = 1 window.localStorage.setItem('num', num) const numRec = window.localStorage.getItem('num') console.log(numRec, typeof(numRec)) // 1 string
因此正确的存储方式应该为:存储之前用JSON.stringify()
方法将数据转换成json字符串
形式;需要使用数据的时候用JSON.parse()
方法将之前存储的字符串转换成json对象
const num = 1 window.localStorage.setItem('num', JSON.stringify(num)) const obj = { name: '小红', age: 18 } window.localStorage.setItem('obj', JSON.stringify(obj)) const numRec = JSON.parse(window.localStorage.getItem('num')) console.log(numRec, typeof(numRec)) // 1 'number' const objRec = JSON.parse(window.localStorage.getItem('obj')) console.log(objRec, typeof(objRec)) // {name: '小红', age: 18} 'object'
注意:localStorage.setItem()和sessionStorage.setItem()不能直接存储对象,必须使用JSON.stringify()
和JSON.parse()
转换实现
以上8种通信方式主要应用在以下三类场景:
props
/$emit
Ia juga lebih mudah digunakan $parent>
/$children
untuk ibu bapa tunggal -komunikasi komponen anak; komponen induk ref
juga sering digunakan untuk mendapatkan contoh komponen kanak-kanak; 🎜> juga boleh digunakan untuk berkomunikasi dengan komponen adik-beradik: provide
Untuk pemindahan data mudah, anda boleh menggunakan inject
's $attrs
/$listeners
untuk data yang kompleks, lebih mudah digunakan localStorage
; anda juga boleh menggunakan sessionStorage
/eventBus
Untuk komunikasi komponen bersarang seperti bapa, anak lelaki dan cucu, $emit
/$on
dan Vuex
/localStorage
sering digunakan; jika data untuk komunikasi komponen merentas peringkat tidak rumit, sessionStorage
dan provide
Tamatinject
$attrs
Artikel ini hanyalah rekod ringkas yang saya lihat pada komunikasi komponen yang biasa digunakan. kaedah, dan tidak memperkenalkan butiran secara mendalam Jika terdapat sebarang kesilapan, sila betulkan saya $listeners
eventBus
(Perkongsian video pembelajaran: localStorage
Pembangunan bahagian hadapan websessionStorage
, Vuex
Video asas pengaturcaraan<.>)
Atas ialah kandungan terperinci Bagaimana untuk berkomunikasi antara komponen Vue? Beberapa cara komunikasi komponen. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!