boostrap模态不用vue js v2双向绑定更新

时间:2017-06-05 14:30:26

标签: javascript jquery twitter-bootstrap laravel vue.js

我是vue js的新手,并尝试将其与引导模式一起使用以查看更多数据。我的场景是一个包含多个记录的表和一个按钮,用于查看bootstrap模式中单击记录的深度详细信息。点击第一个按钮后,它会缓存并且不会在选择另一个按钮时更新它。

有人看到我做错了吗?

(它是Laravel,jQuery和VueJS的组合)

HTML表:

<table class="table table-striped">
<thead>
    <tr>
        <th>E-mail address</th>
        <th>Status</th>
        <th>Sent at</th>
        <th>Expires in</th>
        <th></th>
    </tr>
</thead>
<tbody>
    <tr>
        <td class="v-align-middle">
            john@doe.example
        </td>
        <td class="v-align-middle">
            <span class="label label-default">
                pending
            </span>
        </td>
        <td class="v-align-middle">
            2017-06-05 17:59:15
        </td>
        <td class="v-align-middle">
            29 days
        </td>
        <td>
            <div class="btn-group pull-right">
                <a href="#" class="btn btn-default" data-toggle="modal" data-target="#inviteDetailsModal" data-email="john@doe.example">
                    <i class="fa fa-eye"></i>
                </a>
            </div>
        </td>
    </tr>
    <tr>
        <td class="v-align-middle">
            jane@doe.example
        </td>
        <td class="v-align-middle">
            <span class="label label-default">
                pending
            </span>
        </td>
        <td class="v-align-middle">
            2017-06-05 13:27:25
        </td>
        <td class="v-align-middle">
            29 days
        </td>
        <td>
            <div class="btn-group pull-right">
                <a href="#" class="btn btn-default" data-toggle="modal" data-target="#inviteDetailsModal" data-email="jane@doe.example">
                    <i class="fa fa-eye"></i>
                </a>
            </div>
        </td>
    </tr>
</tbody>

JavaScript的:

$('[data-target="#inviteDetailsModal"]').on('click', function () {
    let email = $(this).data('email'),
        baseUrl = $('html').data('base');

    Vue.component('invite-details', {
        data: function () {
            return {
                email: null,
                token: null,
                logs: [],
                expires: null
            }
        },
        methods: {
            update: function (data) {
                this.email = data['email'];
                this.token = data['token'];
                this.logs = data['logs'];
                this.expires = data['expires'];
            },
            fetchData: function () {
                this.$http.get(baseUrl + '/system/invites/' + email + '/details')
                    .then(response => {
                        this.update(response.body);
                    }, response => {
                        console.log('whoops something went wrong');
                    });
            }
        },
        mounted: function () {
            this.$el.addEventListener('shown.bs.modal', this.fetchData());
        },
        beforeDestroy: function () {
            this.$el.removeEventListener('shown.bs.modal', this.fetchData());
        }
    });

    new Vue({
        el: '#inviteDetailsModal'
    });
});

引导模式:

<div class="modal fade slide-up" id="inviteDetailsModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog">
    <div class="modal-content-wrapper">
        <invite-details inline-template>
            <div class="modal-content" id="details">
                <div class="modal-header clearfix text-left">
                    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">
                        <i class="pg-close fs-14"></i>
                    </button>
                    <h5>
                        Invite details for <span class="semi-bold">@{{ email }}</span>
                    </h5>
                    <p class="p-b-10">
                        <span data-tooltip="true" data-placement="bottom" title="token">
                            <em>@{{ token }}</em>
                        </span>
                    </p>
                </div>
                <div class="modal-body">
                    <table class="table table-striped">
                        <thead>
                        <tr>
                            <th>#</th>
                            <th>Sent at</th>
                            <th>Status</th>
                        </tr>
                        </thead>
                        <tbody>
                        <tr v-for="log in logs">
                            <td>@{{ log.number }}</td>
                            <td>@{{ log.sentAt }}</td>
                            <td>@{{ log.status }}</td>
                        </tr>
                        </tbody>
                    </table>
                </div>
                <div class="modal-footer text-center">
                    <span class="hint-text">
                        <em>expires in <strong>@{{ expires }}</strong> days</em>
                    </span>
                </div>
            </div>
        </invite-details>
    </div>
</div>

2 个答案:

答案 0 :(得分:1)

好吧,我深入挖掘这项工作并加倍努力,因为你提到你是VueJS的新人。我在你的代码中认识了我的旧自我,你用JQuery思维模式进入VueJS; - )

在删除完整代码之前的几个快速说明:

  • 使用表格DB行的整数ID来引用所有用户。 这样,当电子邮件更新时,您仍然知道它是谁 前端。通过检查代码,我看到电子邮件可以更改 (因为它是一个可更新的data属性,但它也被用于 您的GET请求:baseUrl + '/system/invites/' + email + '/details'

  • 随后,您可以使用此ID轻松生成唯一实例 您的模态:-)这是您希望与VueJS合作的方式!

  • 由于您在多个地方使用相同的数据,请查看 Vuex商店。起初看起来可能令人生畏,但它曾经很棒 你可以掌握它。在您的情况下,相同的数据集将是 用于原始表模态。如果一个更新, 一切都在更新!

  • 使用Vuex,您可以从任何地方触发更新。现在的数据 每次单击眼睛按钮时都会更新。但是,这是 非常hacky,因为我已经将按钮作为模态模板的一部分, 每次点击它都会调用fetchData()(检查 安慰)。理想情况下,您要做的就是使用Vuex并生成 从单一真实数据集的一切。目前,如果 模态的数据已更新,原始表格未更新。

  • 使用VueJS,您可以轻松创建自己的模态。好处的好处 这可以减少代码的开销,因为您可以使用v-if,所以它 除非确实需要,否则不会加载到DOM中。并判断 从您当前的代码中,将单击详细信息按钮 偶尔

  • 如果您还没有安装VueJS调试器: https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd, 它会帮助你看到&#39;引擎盖下。

好吧,现在代码!首先,将此行添加到app.js文件中:

import JaimyTable from './components/stackoverflow/JaimyTable.vue'

var app = new Vue({行的正上方。并将其添加到您的组件中,因此最终得到如下内容:

import JaimyTable from './components/stackoverflow/JaimyTable.vue'

var app = new Vue({

    components: {
        JaimyTable,
    },

});

这是JaimyTable.vue文件:

<template>
    <div class="container">
        <table class="table table-striped">
            <thead>
            <tr>
                <th>E-mail address</th>
                <th>Status</th>
                <th>Sent at</th>
                <th>Expires in</th>
                <th></th>
            </tr>
            </thead>
            <tbody>
            <tr>
                <td class="v-align-middle">
                    john@doe.example
                </td>
                <td class="v-align-middle">
            <span class="label label-default">
                pending
            </span>
                </td>
                <td class="v-align-middle">
                    2017-06-05 17:59:15
                </td>
                <td class="v-align-middle">
                    29 days
                </td>
                <td>
                    <div class="btn-group pull-right">

                        <jaimy-modal id="1"></jaimy-modal>

                    </div>
                </td>
            </tr>
            <tr>
                <td class="v-align-middle">
                    jane@doe.example
                </td>
                <td class="v-align-middle">
                <span class="label label-default">
                    pending
                </span>
                </td>
                <td class="v-align-middle">
                    2017-06-05 13:27:25
                </td>
                <td class="v-align-middle">
                    29 days
                </td>
                <td>
                    <div class="btn-group pull-right">

                        <jaimy-modal id="2"></jaimy-modal>

                    </div>
                </td>
            </tr>
            </tbody>
        </table>
    </div>
</template>

<script>
    import JaimyModal from './JaimyModal.vue'

    export default {

        components: { JaimyModal },

        props: [],

        mixins: [],

        data: function () {
            return {
                //
            }
        },

        computed: {
            computed_variable() {
                return '';
            }
        },

        created() {
            //
        },

        mounted() {
            //
        },

        methods: {
            //
        },

        watch: {
            //
        }
    }
</script>

请注意<jaimy-modal id="1"></jaimy-modal>行。您可能希望使用v-for自动生成所有<tr>行:)确保id=对应于数据库中的ID。

现在所有魔法发生的JaimyModal.vue

<template>
    <div>
        <a href="#" class="btn btn-default" data-toggle="modal" :data-target="'#inviteDetailsModal' + id" @click="fetchData()">
            <i class="fa fa-eye"></i>
        </a>

        <div class="modal fade slide-up" :id="'inviteDetailsModal' + id" tabindex="-1" role="dialog">
            <div class="modal-dialog">
                <div class="modal-content-wrapper">


                    <div class="modal-content" id="details">
                        <div class="modal-header clearfix text-left">
                            <button type="button" class="close" data-dismiss="modal" aria-hidden="true">
                                <i class="pg-close fs-14"></i>
                            </button>
                            <h5>
                                Invite details for <span class="semi-bold">{{ email }}</span>
                            </h5>
                            <p class="p-b-10">
                        <span data-tooltip="true" data-placement="bottom" title="token">
                            <em>{{ token }}</em>
                        </span>
                            </p>
                        </div>
                        <div class="modal-body">
                            <table class="table table-striped">
                                <thead>
                                <tr>
                                    <th>#</th>
                                    <th>Sent at</th>
                                    <th>Status</th>
                                </tr>
                                </thead>
                                <tbody>
                                <tr v-for="log in logs">
                                    <td>{{ log.number }}</td>
                                    <td>{{ log.sentAt }}</td>
                                    <td>{{ log.status }}</td>
                                </tr>
                                </tbody>
                            </table>
                        </div>
                        <div class="modal-footer text-center">
                            <span class="hint-text">
                                <em>expires in <strong>{{ expires }}</strong> days</em>
                            </span>
                        </div>
                    </div>


                </div>
            </div>
        </div>
    </div>
</template>

<script>
    export default {

        props: ['id'],

        data: function () {
            return {
                email: null,
                token: null,
                logs: [],
                expires: null,
                baseUrl: 'https://yourbaseurl.com',
            }
        },

        mounted: function () {
            //
        },

        methods: {
            update: function (data) {
                this.email = data['email'];
                this.token = data['token'];
                this.logs = data['logs'];
                this.expires = data['expires'];
            },
            fetchData: function () {
                console.log('data fetched');

                // Commented out for local purposes
//                this.$http.get(this.baseUrl + '/system/invites/' + this.email + '/details')
//                        .then(response => {
//                            this.update(response.body);
//                        }, response => {
//                            console.log('whoops something went wrong');
//                        });

                // Dummy data
                this.update({
                    email: 'test@test ' + this.id + '.com',
                    token: 'token123123asdsasdasdasd',
                    logs: [
                        {
                            number: 1,
                            sentAt: '2017-01-01',
                            status: 'Ok',
                        },
                        {
                            number: 2,
                            sentAt: '2017-02-01',
                            status: 'Failed',
                        },
                    ],
                    expires: '2017-10-01'
                });
            }
        },

    }
</script>

这里要注意的重要一点是按钮中的:data-target="'#inviteDetailsModal' + id"部分,其中数字对应于道具的ID。通过使用:,您可以将其作为表达式,并将其解析为唯一引用。

正如您所看到的,设置与以前完全不同。模态是表行的嵌套组件。一旦您开始将组件视为外观和功能的重复部分,但其中包含唯一数据,则会快速单击。把它想象成Laravel中的模型。

经过很长一段时间被告知你需要分离设计(CSS),标记(HTML)和功能(JS)之后,将它们全部放在1个文件中是很奇怪的。但拥抱它,你会爱上VueJS:D

让Vuex看看!第二个你得到多个使用和操作相同数据集的组件,它是一个上帝发送!

噢,最后:第二个你开始考虑使用像fn.trigger这样的东西,你正在接近VueJS错误。牢记这一点:)它拥有您使用该页面所需的所有工具,然后是一些!

快乐的编码!

答案 1 :(得分:0)

由于您正在使用一个模态组件并且正在尝试根据单击的表中的特定按钮更改其内容,因此mounted挂钩仅在最初安装组件时触发一次。

您想要的是每次显示模式时内容都会更新。

首先,您的组件看起来只需要一个email道具。将其余的道具移动到组件的data方法中,因为(我假设)它们没有被传递到组件中:

props: ['email'],
data: function() {
  return {
    token: null,
    logs: null,
    expires: null,
  }
}

然后,我会创建一个名为fetchData的新方法,将$http.get调用放入:

fetchData: function() {
  this.$http.get('http://localhost:2000/system/invites/' + this.email + '/details')
    .then(response => {
      this.update(response.body);
    }, response => {
      console.log('whoops something went wrong');
    });
}

在模态组件的mounted钩子中,使用jQuery向引导模式的show事件添加一个侦听器。并确保删除组件的beforeDestroy钩子中的侦听器:

mounted() {
  $(this.$el).on('shown.bs.modal', this.fetchData);
}, 
beforeDestroy() {
  $(this.$el).off('shown.bs.modal', this.fetchData);
}

现在,每次模态的show事件触发时,$http.get请求将根据组件的email属性的当前值触发。

Here's an example fiddle.