Vue от Sweet Xiaobai до Pi Big Brother Series (6) Коммуникация компонентов

Vue.js
Vue от Sweet Xiaobai до Pi Big Brother Series (6) Коммуникация компонентов

🎉 Vue создает крупномасштабные одностраничные приложения для электронной коммерции с открытым исходным кодом!Нажмите на меня, чтобы увидеть исходный код 🚀🚀

阅读时间预估:8分钟

Связь между компонентами является наиболее распространенной и базовой частью Vue.Обычно связь перед компонентами делится на следующие типы:

  • 1. Родительские компоненты передают значения дочерним компонентам и передают события
  • 2. Дочерние компоненты передают значения родительским компонентам и передают события
  • 3. Передавайте значения и события между родственными компонентами

метод первый,props $emit v-on

1. Родительский компонент передает значение дочернему компоненту

Родительский компонент A взаимодействует с дочерним компонентом B через реквизиты

Далее мы используем пример, чтобы углубить понимание выше:

Настройте дочерний компонент Son.vue и добавьте его в родительский компонент. Определить данные в родительском компоненте

<template>
    <div id="app">
        <!-- 前者自定义名称便于子组件调用,后者要传递数据名 -->
        <son v-bind:user="user"></son>  
    </div>
</template>
<script>
import Son from './components/Son'

export default {
    name: 'app',
    components: {
        Son,
    },
    data () {
        return { // 父组件定义数据,传递给子组件
            user: ["james", "alice", "joho"]
        }
    },
  }
</script>
    

В дочернем компоненте тип значения значения, переданного родительским компонентом, определяется реквизитом, требуется ли это, и значение по умолчанию

<script>
export default {
    components: {

    },
    data () {
        return {

        };
    },
    computed: {

    },
    methods: {
    },
    props: {
        user: { //这个就是父组件中子标签自定义名字
            type: Array,
            required: true,
            default: []
        }
    },
}
</script>

Затем визуализируйте данные, переданные из родительского компонента, в соответствующей позиции.

<template>
    <div>
        <ul>
            <li v-for="(item,index) in user"
                :key="index">姓名:{{item}}</li>
        </ul>

    </div>
</template>

Когда браузер откроется, он отобразит значение в файле user.

Резюме: родительский компонент передает данные дочернему компоненту через свойства. Примечание. В компонентах есть три формы данных: данные, реквизиты, вычисляемые

2. Дочерние компоненты передают значения родительским компонентам (в виде пользовательских событий)

основная точка

  • 1. Использование подкомпонентовthis.$emit('fn',param)передать значение родительскому компоненту

  • 2. Родительский компонент проходитv-on:fn="fn"принять значение, переданное дочерним компонентом

В дочернем компоненте:

Дочерний компонент содержит событие клика

// 定义一个点击事件
 <son v-bind:user="user"
             @titleChange="changeTitle">
</son>

Передайте событие через this.$emit() в событии клика

<script>
//import x from ''
export default {
    components: {

    },
    data () {
        return {
            title: '我是子组件',
            toParentData: '我是子组件传递的数据'
        };
    },
    computed: {

    },
    methods: {
        btnClick () {
            this.$emit('titleChange', this.toParentData);
        }
    },
    }
</script>

В родительском компоненте: Примите имя события, созданное дочерним компонентом через v-on: titleChange, и привяжите его к собственному событию changeTitle.

<template>
    <div id="app">
        <!-- 前者自定义名称便于子组件调用,后者要传递数据名 -->
        <son v-bind:user="user"
             v-on:titleChange="changeTitle"></son>
        <p>{{msg}}</p>
    </div>
</template>

Реализуйте метод changeTitle для изменения данных сообщения в данных.

<script>
import Son from './components/Son'

export default {
    name: 'app',
    components: {
        Son,
    },
    data () {
        return {
            user: ["james", "alice", "joho"],
            msg: '我是父组件显示的内容'
        }
    },
    methods: {
        changeTitle (title) {
            this.msg = title;
        }
    }
}
</script>

Резюме: дочерний компонент отправляет сообщения родительскому компоненту через события, которые на самом деле представляют собой дочерний компонент, отправляющий свои собственные данные родительскому компоненту.

Метод 2 Центральная шина событий Шина для связи

Обнаружена проблема, если компонент внука передает значение компоненту дедушки, передатьpropsили$emitПуть очень болезненная штука, его нужно подключать через промежуточного отца, поэтому коммуникация явно сделает компоненты спаренными, а коммуникация между родственными компонентамиprops,$emitНе можете сделать это? Так вот вопрос, как решить?

Представьте здесьцентральный автобус событийТо, как имя длинное, на самом деле состоит в том, чтобы извлечь общедоступную среду экземпляра Vue для управления, компоненты, которые должны взаимодействовать, вводятся в шину, а затем связь и передача параметров между компонентами реализуются путем запуска и мониторинга событий шины соответственно.

  • 1. Сначала создайте экземпляр Vue как шину:
// Bus.js
import Vue from 'vue'
export default new Vue;
  • 2. Компоненты, которым необходимо обмениваться данными, импортируются в Bus.js и используют $emit для отправки информации:
// ComponentA.vue
<template>
  <div>
    <b>组件A:</b><button @click="handleBus">传递数值给需要的组件</button>
  </div>
</template>

<script>
  import Bus from './bus.js' 
  export default {
    methods: {
      handleBus () {
        Bus.$emit('someBusMessage','来自ComponentA的数据')
      }
    }
  }
</script>
  • 3. Если вам нужна информация о компоненте A, используйте $on для прослушивания:
// ComponentB.vue
<template>
  <div>
    <b>组件B:</b><button @click="handleBus">接收组件A的信息</button>
    <p>{{message}}</p>
  </div>
</template>

<script>
  import Bus from './bus.js' 
  export default {
    data() {
      return {
        message: ''
      }
    },
    created () {
      let that = this // 保存当前对象的作用域this
      Bus.$on('someBusMessage',function (data) {
        that.message = data
      })
    },
    beforeDestroy () {
      // 手动销毁 $on 事件,防止多次触发
      Bus.$off('someBusMessage', this.someBusMessage)
    }
  }
</script>

Преимущества центральной шины: компонент развязки может облегчить связь между братьями

Способ третий$parent / $children & $refs

  • $parent / $children: Указывает созданный экземпляр, устанавливая отношения родитель-потомок между ними. Подэкземпляры могут использоваться сthis.$parentДоступ к родительскому экземпляру, дочерний экземпляр помещается в родительский$childrenсередина.

  • $refs: объект, который содержит зарегистрированныйrefВсе элементы DOM и экземпляры компонентов для атрибута.refИспользуется для регистрации ссылок на элементы или подкомпоненты. Справочная информация будет зарегистрирована в объекте $refs родительского компонента.

  • При использовании на обычном элементе DOM ссылка указывает на элемент DOM; при использовании на дочернем компоненте ссылка указывает на компонент.

родительский компонент

<template>
    <div id="app">
        <!-- 前者自定义名称便于子组件调用,后者要传递数据名 -->
        <p>{{msg}}</p>
        <child-one ref="childOne"></child-one>
        <child-two ref="childTwo"></child-two>
        <button @click="oneContent">显示child-one传过来的数据</button>
        <button @click="twoOneContent">显示hild-two传过来的数据</button>

    </div>
</template>

<script>
// 引入子组件
import ChildOne from './components/ChildOne'
import ChildTwo from './components/ChildTwo'
export default {
    name: 'app',
    components: {
        ChildOne,
        ChildTwo
    },
    data () {
        return {
            msg: '我是父组件',
            content: 'James' //子组件要用的数据
        }
    },
    methods: {
        // button 的事件响应 
        oneContent () {
            const childOne = this.$refs.childOne;
            this.msg = childOne.msg;
        },
        twoOneContent () {
            // 通过$refs取到childTwo
            const childTwo = this.$refs.childTwo;
            this.msg = childTwo.msg;
        }
    },
}
</script>

подкомпонент 1

<template>
    <div>
        <p>{{title}} 我的父组件是{{content}}</p>
    </div>
</template>

<script>
//import x from ''
export default {
    components: {
    },
    data () {
        return {
            content: '',
            title: '我是子组件 childOne',
            msg: '我只子组件childOne hello ereryOne'
        };
    },
    mounted () {
        // 从父组件里取contet的数据
        this.content = this.$parent.content;
    },
}
</script>

Подкомпонент 2:

<template>
    <div>
        <p>{{title}} 我的父组件是{{content}}</p>
    </div>
</template>

<script>
//import x from ''
export default {
    data () {
        return {
            content: '',
            title: '我是子组件 childTwo',
            msg: '我是子组件childTwo hello ereryOne'
        };
    },
    mounted () {
        // 加载父组件content的内容
        this.content = this.$parent.content;
    },
}
</script>

Способ 4: режим публикации-подписки

Официальный гитхаб

  • 1. Пройтиnpm install pubsub-js --saveСпособ импорта библиотеки pubsub
  • 2. Создатьevent-type.jsОпределить данные типа Symbol и экспортировать
// event-types.js
export const MY_TOPIC = Symbol('MY_TOPIC')
  • 3. Укажите, где вам нужно публиковать (события доставки)pubsubа такжеevent=type.jsи опубликовать событие через
import PubSub from 'pubsub-js'
import { MY_TOPIC } from './event-types.js'
PubSub.publish(MY_TOPIC, 'world');

  • 4. Укажите, где вам нужно подписаться (принять события)pubsubа такжеevent=type.js, и принять событие через
import PubSub from 'pubsub-js'
import { MY_TOPIC } from './event-types.js'
PubSub.subscribe(MY_TOPIC, function (msg, data) {
	console.log(data)
});
  • 5. Не забудьте удалить уведомление перед уничтожением компонента~
 beforeDestroy() {
    // 销毁通知
    PubSub.subscribe(MY_TOPIC)
    console.log("通知被销毁了!")
  },

Метод 5

официальный портал

Vuex — это идеальное решение, официально рекомендованное Vue для решения проблем связи в компонентах, а также обязательное решение для разработки проектов:

Нажмите на меня, чтобы изучить Vuex

Внимательно прочитав эту статью, вы сможете мысленно просмотреть ментальную карту, и у вас будет более глубокое понимание и понимание пунктов знаний в этом блоке.

Vue组件思维导图

Если мой рассказ вдохновит героя перед вами, пожалуйста, не скупитесь на большие пальцы,Высшая вежливость программистаНравится ✨ Способ комментирования и обмена побуждает меня продолжать делиться и приветствовать всех, кто делает ошибки и высказывает ценные мнения.

Обратите внимание на официальный аккаунт и ответьте: Учитесь получать самые свежие и полные учебные материалы на переднем конце, вы также можете войти в группу, чтобы учиться и общаться с большими парнями.

Ткните в мой передовой продвинутый блог