在视图中访问子组件数据

时间:2017-10-05 16:27:01

标签: php laravel laravel-5 vue.js vuejs2

目前我正在使用Laravel 5.2和Elixir 5和Vue 2.0。

我坚持如何使用类似v-if的方式从元素视图访问和导入组件的数据。

这是我的设置:

资源\视图\ vuetest.blade.php

<div id="app">
    <modal v-if="showModal"></modal>

    <button>Show Modal</button>
</div>

资源\资产\ vuejs \ app.js

import Vue from 'vue';
import Modal from './components/modals/show-modal.vue';
Vue.component('modal', Modal);

if (document.getElementById("app")){
    var app = new Vue({
        el: '#app',

        data: {

        },

        methods: {

        },

        computed: {

        },

        components: {
            'modal': Modal
        }

    });

    window.vue = app;
}

资源\资产\ vuejs \部件\模态\显示-modal.vue

<template>
    <div id="myModal" class="modal fade" role="dialog">
    <div class="modal-dialog">

    <!-- Modal content-->
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal">&times;</button>
        <h4 class="modal-title">Modal Header</h4>
      </div>
      <div class="modal-body">
        <p>Some text in the modal.</p>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
      </div>
    </div>
</template>

<script>
    export default {
        data() {
            return {
                showModal: false
            }
        },

        components: {

        },
    }
</script>

现在如果我只是在没有v的情况下使用它,那么它可以工作并正确地拉入模板。

但是,如果我使用我的示例中的内容,则会给出错误:

app.js:967 [Vue warn]: Property or method "showModal" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option.

(found in <Root>)

如果我在主app.js中添加数据,它可以访问它,但不能在导入的子组件中访问它。我宁愿不使主app.js凌乱,更好地使用导入并将组件保存在有组织的子文件夹中。如何正确访问这些子组件数据?

4 个答案:

答案 0 :(得分:1)

如果要更改子组件的状态,可以在组件上设置ref并直接访问属性。

在此示例中,在每个模态组件上设置ref

<bootstrap-modal ref="modal1">

然后,要更改引用组件中的数据值,只需将其设置为与任何其他javascript值一样。

 <button type="button" class="btn btn-primary" @click="$refs.modal1.visible = true">Show Modal One</button>

console.clear()

const BootstrapModal = {
  template: "#modal-template",
  data() {
    return {
      visible: false
    }
  },
  watch: {
    visible(show) {
      if (show) $(this.$el).modal('show')
      else $(this.$el).modal('hide')
    }
  },
  mounted() {
    // listen for the close event
    $(this.$el).on("hidden.bs.modal", () => {
      this.visible = false
    })
  }
}

new Vue({
  el: "#app",
  components: {
    BootstrapModal
  }
})
<script src="https://unpkg.com/vue@2.4.2"></script>
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">

<div id="app">
  <button type="button" class="btn btn-primary" @click="$refs.modal1.visible = true">Show Modal One</button>
  <bootstrap-modal ref="modal1">
    <span slot="title">Modal One</span>
    <p slot="body">Modal One Content</p>
  </bootstrap-modal>
  <button type="button" class="btn btn-success" @click="$refs.modal2.visible = true">Show Modal Two</button>
  <bootstrap-modal ref="modal2">
    <span slot="title">Modal Two</span>
    <p slot="body">Modal Two Content</p>
  </bootstrap-modal>
</div>

<template id="modal-template">
  <div class="modal fade">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title"><slot name="title">Modal Title</slot></h5>
        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body">
        <slot name="body"><p>Modal Body</p></slot>
      </div>
      <div class="modal-footer" v-if="$slots.footer">
        <slot name="footer"></slot>
      </div>
    </div>
  </div>
</div>
</template>

答案 1 :(得分:0)

您需要在主应用上声明var showModal

data: {
    showModal: false
},

您还需要在每次点击按钮时切换该变量,然后将其添加到按钮:

<button @click="showModal = !showModal">Show Modal</button>

另外我建议用div包装模板里面的模板。由于vuejs需要这个。

<template>
    <div>
        <div id="myModal" class="modal fade" role="dialog">
            <div class="modal-dialog">
                <div class="modal-content">
                    <div class="modal-header">
                        <button type="button" class="close" data-dismiss="modal">&times;</button>
                        <h4 class="modal-title">Modal Header</h4>
                    </div>
                    <div class="modal-body">
                        <p>Some text in the modal.</p>
                    </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
                </div>
            </div>
        </div>
    </div>
</template>

答案 2 :(得分:0)

简短回答:您正在尝试访问父组件(或您的案例中的Root实例)范围内的子组件的属性。您应该在Parent组件上声明showModal属性。

var app = new Vue({
    el: '#app',
    components: {Modal},
    data: {
        showModal: false

    },
});

然后你会有按钮改变你的财产状态: <button @click="showModal = true"></button>

棘手的部分是关闭模态 - 因为当模态处于活动状态时,您无法再触及按钮。您必须从子组件更改父组件的状态。在这种情况下,您可以使用自定义事件,如下所示:

show-modal.vue

<div class="modal-footer">
    <button type="button" class="btn btn-default" @click="close">
       Close
   </button>
  </div>

    ...

 <script>
export default {
    methods: {
         close() {
             this.$emit('close');
         }
    }
}

现在,我们所要做的就是听一下我们刚刚在主模板中触发的自定义事件,就像这样;

<modal v-if="showModal" @close="showModal = false"></modal>

答案 3 :(得分:0)

不确定是否有最好的方法,但我在这方面的帮助下弄清楚了: VueJS access child component's data from parent

我所做的是在我的孩子组件中,我提出以下内容:

<template>
    <div>
        <div id="myModal" class="modal fade" role="dialog">
        <div class="modal-dialog">

        <!-- Modal content-->
        <div class="modal-content">
          <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal">&times;</button>
            <h4 class="modal-title">Modal Header</h4>
          </div>
          <div class="modal-body">
            <p>Some text in the modal.</p>
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
          </div>
        </div>
    </div>
</template>

<script>
    export default {
        data: function () {
            return {
                showModal: false
            }
        },

        components: {

        },
    }
</script>

然后在我的vuetest.blade.php中我把它:

<div id="app">
    <modal v-if="modalData.showModal"></modal>

    <button>Show Modal</button>
</div>

然后最后在我的app.js中我这样做了:

import Vue from 'vue';
import Modal from './components/modals/show-modal.vue';

if (document.getElementById("app")){
    var app = new Vue({
        el: '#app',

        data: {
            modalData: Modal.data()
        },

        methods: {

        },

        computed: {

        },

        components: {
            'modal': Modal
        }

    });

    window.vue = app;
}

我没有明确地完成show modal按钮的代码,但至少使用这种方式我现在可以访问子数据。我只需要为每个组件定义这个,这个组件应该考虑它在数据中包含的多个变量。

还要感谢Carlos建议将其包装成div。