javascript - Bootstrap 模式不使用 vue js v2 双向绑定(bind)更新

标签 javascript jquery twitter-bootstrap laravel vue.js

我是 vue js 的新手,并尝试将它与 Bootstrap 模式一起使用以查看更多数据。我的场景是一个包含多条记录的表和一个按钮,用于在 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'
    });
});

Bootstrap 模式:

<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>

最佳答案

好吧,我深入挖掘以使其正常工作并付出了额外的努力,因为你提到你是 VueJS 的新手。我在你的代码中认出了我以前的自己,你以 JQuery 的心态进入 VueJS ;-)

在删除完整代码之前的几个快速注释:

  • 使用表数据库行的整数 ID 在任何地方引用用户。 这样,当电子邮件更新时,您仍然知道它在 前端。通过检查代码,我发现电子邮件可以更改 (因为它是一个可更新的 data 属性,但它也用于 你的GET请求:baseUrl + '/system/invites/' + email + '/details'

  • 随后,您可以使用此 ID 轻松生成唯一实例 你的模式 :-) 这就是你想要使用 VueJS 的方式!

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

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

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

  • 如果您还没有安装 VueJS 调试器: https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd , 它将帮助您“看到”幕后情况。

好了,现在开始写代码了!首先,将此行添加到您的 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"按钮中的部分,其中数字对应于 prop 的 id。通过使用 :您将其设为一个表达式,它解析为一个唯一引用。

如您所见,设置与之前完全不同。模态是表格行的嵌套组件。一旦您开始将组件视为外观和功能的重复部分,但其中包含独特的数据,事情就会很快点击。将其视为 Laravel 中的模型。

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

然后看看 Vuex!第二个你得到多个使用和操作同一个数据集的组件,这是天赐之物!

哦,最后:当你开始考虑使用 fn.trigger 之类的东西时,你就错误地接近了 VueJS。请记住这一点 :) 它具有您使用该页面所需的所有工具,而且还有一些!

编码愉快!

关于javascript - Bootstrap 模式不使用 vue js v2 双向绑定(bind)更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44371290/

相关文章:

html - 单独加载 Bootstrap 组件

javascript - 将 reangular 和 anglestrap 放在一起

javascript - jQuery 将类添加到图像链接而不会在链接传递变量时弄乱

javascript - 我该怎么做才能避免同步 AJAX 请求

javascript - jQuery 禁用悬停效果 onClick

打造漂亮界面的 JQuery 代码片段

javascript - 检查下一个元素是否是特定元素

html - Bootstrap,选择选项占位符仅在首次提交后显示

javascript - $watch 不适用于 angularjs 中的指令属性

javascript - 如何从 Laravel 的 if 语句调用 javascript 函数?