Обобщить взаимодействие компонентов Vue

внешний интерфейс Vue.js
Обобщить взаимодействие компонентов Vue

написать впереди

Суммирование - это способ обучения, и обучение у сильных сторон друг друга - это изучение. Полный текст суммирует методы связи между 6 составляющими Vue. Если есть недоразумение, пожалуйста, поправьте меня!

1. реквизит/$ излучать

Наиболее часто используемый способ передачи данных между родителем и потомком.

описывать:

Родительские компоненты передают данные дочерним компонентам посредством связывания свойств, а дочерние компоненты передаютpropsсвойства для получения соответствующих данных; дочерние компоненты передаются$emitСобытия отправляют сообщения родительскому компоненту, передавая собственные данные родительскому компоненту.

Инструкции:

// 父组件compA
<template>
    <div>
        <compB
        :title="value"
        :moreBtn="moreBtn"
        @more="onMore"/>
    </div>
    
</template>
<script>
import compB from './compB'
export default{
    name: 'compA',
    components:{
        compB
    },
    data(){
        return {
            value: '',
            moreBtn: true
        }
    },
    method:{
        onMore(value){
            console.log('value', value)
            //点击查看更多按钮
        }
    }
}
</script>
//子组件compB
<template>
    <div>
        <div class="title">{{value}}</div>
        <div v-if="moreBtn" @click="handleMore">查看更多</div>
    </div>
</template>
<script>
export default{
    name: 'compB',
    data(){
        return {
        }
    },
    props: {
        title: {
            type: String,
            default: '标题'
        },
        moreBtn: {
            type: Boolean,
            default: false
        }
    }
    method:{
        handleMore(){
            this.$emit('more', '点击查看更多按钮')
        }
    }
}
</script>

Реквизиты формируют односторонний поток данных между родителем и дочерним элементом.При обновлении родительского элемента состояние дочернего элемента также изменится. Но, наоборот, это затруднит понимание потока данных вашего приложения.

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

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

В некоторых случаях дочернему компоненту необходимо изменить значение родительского компонента.Рекомендуется использовать синтаксический сахар .sync, добавленный в версии (2.3.0+).

Инструкции:

// A.vue
<template>
    <add-modal 
      v-if="modalVisiable" 
      :visiable.sync='modalVisiable' 
      @submit="saveForm"
    />
</template>
<script>
export default {
    name: 'A',
    data(){
        return {
            modalVisiable: false
        }
    }
}
</script>
// B.vue
<template>
    <Modal 
      v-model="show"
      width="600"
      title="弹框" 
      :loading='true'
      @on-cancel="$emit('update:visiable', false)"
    >
    </Modal>
</template>
<script>
export default {
    name: 'A',
    data(){
        return {
            show: false,
        }
    },
    created(){
        this.show = this.visiable
    },
    props: {
        visiable: {
          type: Boolean,
          default: false
        }
    },
}
</script>

пройти черезthis.$emit('update:visiable', false)изменить состояние родительского элемента

2. $выпустить/$на

шина событий eventBus

описывать:

Этот метод заключается в создании пустого экземпляра vue в качестве центра обработки (шины событий) события $emit и инициировании и мониторинге событий через него, что облегчает связь между любыми компонентами, включая родительско-дочерние, братские и межпоколенческие компоненты.

Возьмем в качестве примера следующий рисунок. Мы хотим добиться того, чтобы компоненты A и C передавали данные компоненту B.

Инструкции:

<!--home.vue-->
<template>
  <div>
    <div>我是父元素,我的num的值是:{{num}}</div>
    <a-comp :event="bus" :num.sync='num'></a-comp>
    <c-comp :event="bus" :num='num'></c-comp>
    <b-comp :event="bus"></b-comp>
  </div>
</template>
<script>
import Vue from 'vue';
import aComp from './a.vue';
import bComp from './b.vue';
import cComp from './c.vue';
// 创建一个空的vue实例
const bus = new Vue();
export default {
  'name': 'example',
  data() {
    return {
      bus,
      'num': 1
    };
  },
  'components': {
    aComp,
    bComp,
    cComp
  }
};
</script>
<!--a.vue-->
<template>
  <div class="a-content">
    我是组件A,
    <el-button type="primary" @click="send">点击我向B发送东西</el-button>
  </div>
</template>
<script>
export default {
  'name': 'aComp',
  'props': [
    'event',
    'num'
  ],
  data() {
    return {'nb': 0};
  },
  created() {
    this.nb = this.num;
  },
  'methods': {
    send() {
      this.nb = this.nb + 1;
      this.$emit('update:num', this.nb);
      // 通过$emit 来触发phone-a事件
      this.event.$emit('phone-a', '我是组件A啊', this.nb);
    }
  }
};
</script>
<!--c.vue-->
<template>
  <div>
    我是组件C,
    <el-button type="primary" @click="send">点击我向B发送东西</el-button>
  </div>
</template>
<script>
export default {
  'name': 'cComp',
  'props': [
    'event',
    'num'
  ],
  data() {
    return {};
  },
  'methods': {
    send() {
      console.log(this.num);
      this.event.$emit('phone-c', `我是组件C啊${this.num}`);
    }
  }
};
</script>
<!--b.vue-->
<template>
  <div class="b-content">
    <div>我是组件B,我会接收组件A及组件C</div>
    <div>
      A: {{a}}
    </div>
    <div>
      B: {{c}}
    </div>
  </div>
</template>
<script>
export default {
  'name': 'bComp',
  data() {
    return {
      'a': '',
      'c': ''
    };
  },
  'props': ['event'],
  mounted() {
    // 通过$on来监听 phone-a 、phone-c 事件
    this.event.$on('phone-a', (a, num) => {
      this.a = `${a},我在改变父元素传过来的值num: ${num}`;
    });
    this.event.$on('phone-c', c => {
      this.c = c;
    });
  }
};
</script>

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

3. предоставить / ввести

описывать:

Эту пару параметров необходимо использовать вместе.Родительский компонент использует предоставление для предоставления данных вниз, а все дочерние компоненты под ним могут быть внедрены через инъекцию. Можно вводить несколько данных, предоставленных разными родителями, независимо от количества поколений между ними.

  • Параметр предоставления — это объект или функция, которая возвращает объект. Объект содержит свойства, которые можно внедрить в его потомков.
  • Опция inject представляет собой массив строк или объект

Инструкции:

// 父组件
<template>
  <div>
    <com-a></com-a>
  </div>
</template>
<script>
import ComA from './a';

export default {
  'name': 'home',
  'components': {ComA},
  provide() {
    return {
      'a': 'Hello',
      'show': val => !val
    };
  }
};
</script>

// 子组件
<template>
  <div>
    <el-button @click="showFn(textShow)">点击我切换下面文字展示及隐藏</el-button>
    <div v-if="textShow">我是一段随意被操控的文字{{a}}</div>
  </div>
</template>
<script>
export default {
  'name': 'ComA',
  data() {
    return {'textShow': true};
  },
  'inject': [
    'a',
    'show'
  ],
  'methods': {
    showFn(val) {
      this.textShow = this.show(val);
    }
  }
};
</script>

Если глобальная регистрационная информация находится в файле app.vue (корневом файле), на нее можно ссылаться во всем маршруте. (аналогично глобальному управлению данными vuex)

<template>
    <div>
        <router-view></router-view>
    </div>
</template>
<script>
export default {
    name: 'app',
    provide(){
        return {
            app: this
        }
    }
}
</script>

Далее, пока какой-либо компонент внедряется в приложение через inject, он может напрямую обращаться ко всем экземплярам app.vue через this.app.xx.

4. $родитель / $дети

описывать:

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

<template>
  <div class="b-content">
    <div>我是子组件</div>
    <span>{{msgText}}</span>
  </div>
</template>
<script>
export default {
  'name': 'childComp',
  data() {
    return {
      'msgText': '',
      'childMsg': '来自子元素的呐喊'
    };
  },
  created() {
    this.msgText = this.$parent.parentMsg;
    // MsgText: 来自父组件的呵呵
  }
};
</script>

$children может проходить через все дочерние компоненты, следует отметить, что $children не гарантирует порядок и не отвечает.

<template>
  <div class="b-content">
    <div>我是父组件</div>
    <child-comp></child-comp>
  </div>
</template>
<script>
import childComp from './child';

export default {
  'name': 'parentComp',
  data() {
    return {'parentMsg': '来自父组件的呵呵'};
  },
  'components': {childComp},
  mounted() {
    // 读取子组件数据,注意$children子组件的排序是不安全的
    console.log(this.$children[0].childMsg);
    // 来自子元素的呐喊
  }
};
</script>

5. $root и ссылки

описывать:

Свойство $root находится в дочернем компоненте каждого нового экземпляра Vue, и доступ к его корневому экземпляру можно получить через свойство $root. Например, в этом корневом экземпляре:

// Vue 根实例
new Vue({
  data: {
    foo: 1
  },
  computed: {
    bar: function () { /* ... */ }
  },
  methods: {
    baz: function () { /* ... */ }
  }
})

Все дочерние компоненты могут обращаться к этому экземпляру или использовать его в качестве глобального хранилища.

// 获取根组件的数据
this.$root.foo

// 写入根组件的数据
this.$root.foo = 2

// 访问根组件的计算属性
this.$root.bar

// 调用根组件的方法
this.$root.baz()

Свойство $refs используется, когда вам нужно получить доступ к дочернему компоненту непосредственно в JavaScript. Вы можете назначить ссылку ID дочернему компоненту через атрибут ref. Объект, содержащий все элементы DOM и экземпляры компонентов, для которых зарегистрирован атрибут ref. Например:

<my-component ref="childrenCompA"></my-component>
访问子组件:this.$refs.childrenCompA

6. Векс

При выполнении средних и крупных одностраничных приложений, таких как совместная разработка нескольких человек, глобальное обслуживание статуса входа в систему и т. д., мы можем выбрать vuex для управления состоянием.

Состояние — это данные, хранящиеся в vuex.При регистрации параметра хранилища в корневом экземпляре экземпляр хранилища будет внедрен во все подкомпоненты корневого компонента, и доступ к подкомпонентам можно будет получить через this.$store.

Когда вам нужно получить несколько данных, вы можете сделать это следующим образом:

import {mapState} from 'vuex'
computed:{
    ...mapState('commissionSetting', [
      'listData'
    ])
},

Не все состояния подходят для размещения в vuex, некоторые состояния принадлежат только одному компоненту, так что все еще зависит от ситуации.

Единственный способ для мутаций изменить состояние в хранилище Vuex — это зафиксировать мутацию.

const mutations = {
  updateListData(state, payload){
    state.listData = payload
  }
}

Вы не можете вызвать updateListData напрямую, вам нужно вызвать метод store.commit с соответствующим типом:

store.commit('updateListData', data)

Действия вызывают мутации, а не изменения состояния напрямую. Действие может содержать произвольные асинхронные операции.

Напишите простое действие:

async getListAction({commit}, params){
    const result = await getList(params)
    const {code, message, data} = result
    if(code === SUCCESS && data){
      // 提交更改数据
      commit('updateListData', data.rows)
    }else{
      vueInit.$Message.error({
        content: message || '请您稍后再试~'
      });
    }
    return result
  },

Vuex не ограничивает структуру вашего кода. Однако он предписывает некоторые правила, которые необходимо соблюдать:

  • Состояние уровня приложения должно быть централизовано в одном объекте хранилища.
  • Выполнение мутаций — единственный способ изменить состояние, и этот процесс является синхронным.
  • Асинхронная логика должна быть инкапсулирована в действии.

Пока вы следуете приведенным выше правилам, вы можете организовать свой код по своему желанию. Если ваш файл хранилища слишком велик, просто разделите действия, мутации и геттеры на отдельные файлы.

наконец

Жизнь продолжается, обучение продолжается. Новые знания появляются нескончаемым потоком, и для нас, разработчиков, самое главное — усвоить и применить их в практических проектах.

Подписывайтесь на нас

关注公众号前端论道