Как использовать компонент несколько раз, передавая ему разные данные? - PullRequest
1 голос
/ 22 марта 2020

Я пытаюсь создать компонент снэк-бара для отображения простых уведомлений. Он может быть использован во многих местах во всем приложении, а также на одной странице. Я создал компонент как дочерний компонент и импортировал его в родительский компонент, где я хочу его использовать. В этом родительском компоненте много раз этот дочерний элемент может быть использован. Как следует реализовать таким образом, чтобы каждый раз, когда вызывался этот компонент, он получал соответствующие данные (например, для error color = red text = "error", для success color = "green" message = "success).

Есть предложения как это реализовать?

parent.vue----------------------------

<snackbar
      :snackbar="snackbar"
      :color="color"
      :text="message"
      v-on:requestClose="close"
    />


data() {
    return {
      snackbar: false,
      color: "orange",
      timeout: 3000,
      message: "calling from employee compoenent"
    };
  },
  methods: {
    hello() {
      console.log("button clicked!!!");
      this.snackbar = true;
    },
    close() {
      this.snackbar = false;
    },


child.vue-----------------------------------------------

<template>
  <v-snackbar v-model="snackbar" right top :timeout="timeout" :color="color"
    >{{ text }}
    <v-btn dark text @click.native="$emit('requestClose')">Close</v-btn>
  </v-snackbar>
</template>

<script>
export default {
  name: "snackbar",
  data() {
    return {
      timeout: 3000
    };
  },
  props: ["snackbar", "text", "color"],

};
</script>

<style></style>

Ответы [ 3 ]

3 голосов
/ 25 марта 2020

Я сделал это, используя комбинацию глобальных компонентов и Vuex. Ответ немного длинен, потому что я привожу пример вместе с описанием, пожалуйста, потерпите меня:)

Сначала я создаю закусочную с color и text в качестве state и setSnackbar() action, который получает цвет и текст в качестве параметров. Затем вы можете создать свой Snackbar компонент и не забудьте указать в нем свои методы получения, действия. Фрагмент кода:

// snackbar component
<template>
  <v-snackbar v-model="snackbar.show" :color="snackbar.color" :timeout="6000" bottom right>
    {{ snackbar.text }}
    <v-btn dark text @click="snackbarClosed()">Close</v-btn>
  </v-snackbar>
</template>

<script lang="ts">
import Vue from "vue";
import { mapGetters, mapActions } from "vuex";

export default Vue.extend({
  computed: {
    ...mapGetters(["snackbar"])
  },
  methods: {
    snackbarClosed() {
      this.resetSnackbar();
    },
    ...mapActions(["resetSnackbar"])
  }
});
</script>
// snackbar store
const state = {
  snackbar: {
    show: false,
    text: '',
    color: ''
  }
};
const getters = {
  snackbar: (state: any) => state.snackbar
};
const actions = {
  async setSnackbar({ commit }, params) {
    commit('updateSnackbar', Object.assign({}, { show: true }, params))
  },
  async resetSnackbar({ commit }) {
    const setting: SnackbarSetting = {
      show: false,
      text: '',
      color: ''
    };
    commit('updateSnackbar', setting)
};
const mutations = {
  updateSnackbar: (state: any, snackbar: SnackbarSetting) => {
    state.show = snackbar.show;
    state.text = snackbar.text;
    state.color = snackbar.color;
  }
};

Чтобы сделать компонент Snackbar глобально доступным, импортируйте компонент Snackbar в main.ts и добавьте строку Vue.component('Snackbar', Snackbar); перед new Vue. Его целью является глобальная регистрация компонента Snackbar перед инициализацией экземпляра Vue. Пример:

// main.ts
import Snackbar from './components/Snackbar.vue';

Vue.component('Snackbar', Snackbar);

new Vue({
...

Прежде чем вы захотите отобразить свою закусочную в приложении, по моей рекомендации вы должны поместить <Snackbar /> в App.vue, чтобы эта закусочная могла появляться перед вашими компонентами, и вы не будете быть лицом к отсутствующей закусочной при переключении между компонентами.

Если вы хотите отобразить снэк-бар, просто сделайте это в своем компоненте:

// any of your component
methods: {
  someEvent() {
    this.someApiCall({
      // some data passing
    }).then(() => {
      this.setSnackbar({
        text: 'Data has been updated.',
        color: 'success'
      });
    }).catch(() => {
      this.setSnackbar({
        text: 'Failed to update data.',
        color: 'error'
      });
    });
  },
  ...mapActions(['setSnackbar'])
}

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

1 голос
/ 22 марта 2020

Рекомендуется для создания пользовательской оболочки Vue plugin

plugins / snackbar / index. js

import snackbar from './snackbar.vue'

export default {
  install (Vue) {
    // INSTALL
    if (this.installed) return
    this.installed = true

    // RENDER
    const root = new Vue({ render: h => h(snackbar) })
    root.$mount(document.body.appendChild(document.createElement('div')))

    // APIs
    let apis = Vue.prototype['$snackbar'] = {
      show: ({ text="Foo", color="blue" }) => root.$emit('show', { text, color }), // SHOW
      hide: () => root.$emit('hide') // HIDE
    }

    Vue.prototype['$snackbar'] = apis
    Vue.snackbar = apis
  }
}

плагины / закусочная / закусочная. vue

<template>
  <v-snackbar right top v-model="show" :timeout="timeout" :color="color">
    {{ text }}
    <v-btn dark text @click.native="this.show = false">Close</v-btn>
  </v-snackbar>
</template>

<script>
export default {
  name: "snackbar",

  data() {
    return {
      show,
      timeout: 3000,
      text: "",
      color: ""
    };
  },

  mounted () {
   // LISTENING :: SHOW
   this.$root.$on('show', ({ text, color }) => {      
    this.text = text
    this.color = color
    this.show = true
   })

   // LISTENING :: HIDE
   this.$root.$on('hide', () => this.show = false)
  }
};
</script>

// main. js

import Snackbar from './plugins/snackbar/index.js'
Vue.use(Snackbar)

To show / hide это в любом компоненте

this.$snackbar.show({ text: "Foo bar", color: "red" }) // OR
Vue.snackbar.show({ text: "Foo bar", color: "red" })

В соответствии с вариантом использования вы можете постоянно обновлять свой плагин, добавляя больше параметров / API.


Альтернатива: Используя event bus

шину событий / шину. js

// Create an event bus
import Vue from 'vue'
export default new Vue()

приложение . vue

<template>
 // Render the component in app.vue
 <v-snackbar 
  right top 
  v-model="snackbar.show" 
  :timeout="snackbar.timeout" 
  :color="snackbar.color"
 >
  {{ snackbar.text }}
  <v-btn 
   dark text 
   @click.native="this.snackbar.show = false"
  >
   Close
  </v-btn>
 </v-snackbar>
</template>

<script>
import bus from './event-bus/bus.js'

export default {
 data () {
  return {
   snackbar: {
    show: false,
    text: '',
    color: '',
    timeout: 3000
   }
  }
 },

 mounted () {
  // LISTEN TO SHOW
  bus.$on('show', ({ text, color }) => {
   this.snackbar.text = 'foo'
   this.snackbar.color = 'red'
   this.snackbar.show = true
  })

  // LISTEN TO HIDE
  bus.$on('hide', () => this.snackbar.show = false)
 }
}
</script>

К show / hide Снэкбар из любой компонент

import bus from './event-bus/bus.js

export default {
 mounted () {
  bus.emit('show', { text: 'Foo bar baz', color: 'orange' }) // TO SHOW
  // bus.emit('hide') // TO HIDE
 }
}

Другой способ : с помощью Vuex

Визуализировать <v-snackbar> в приложении. vue как сделано в альтернативе Подойдите и используйте Vuex state / getters, чтобы передать значение в props v-закусочной.

0 голосов
/ 22 марта 2020

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


watch: {
color: function(value) {
"add color value to your dom css class"
}
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...