首页 > 解决方案 > 更新列表时更新模块即时更改

问题描述

抱歉,这篇文章很长,但我尝试尽可能详细地解释事情。

因此,当我更深入地研究 JavaScript 并开始越来越多地了解 AJAX 请求和其他组件时,我偶然发现了一些我似乎无法弄清楚的东西。

所以下面,我将解释我在做什么以及我想做什么,看看是否有人对我有一些指导。

所以这是我的Vue.js应用程序:

new Vue({
    name: 'o365-edit-modal',
    el: '#o365-modal-edit',
    data: function() {
        return {
            list: {},
        }
    },
    created() {
        this.fetchApplicationsMenu();
    },
    methods: {
        fetchApplicationsMenu() {
            var self = this;
            wp.apiRequest( {
                path: 'fh/v1/menus/applications',
                method: 'GET',
            }).then(menu => self.list = menu.data);
        },
        changed() {
            const selected = this.$data.list.selected;
            function get_ids(list, field) {
                const output = [];
                for (let i=0; i < list.length ; ++i)
                    output.push(list[i][field]);
                return output;
            }
            const result = get_ids(selected, "id");
            wp.apiRequest( {
                path: 'fh/v1/menus/applications',
                method: 'PUT',
                data: {
                    ids: result,
                },
            }).then((post) => {
                return post;
            },
            (error) => {
                console.log(error);
            });
        },
        add(x) {
            this.$data.list.selected.push(...this.$data.list.available.splice(x, 1));
            this.changed();
        },
        remove(x) {
            this.$data.list.available.push(...this.$data.list.selected.splice(x, 1));
            this.changed();
        },
    },
});

然后是我用来呈现两列的 HTML 部分:

<div class="column is-half-desktop is-full-mobile buttons">
    <nav class="level is-mobile mb-0">
        <div class="level-left">
            <div class="level-item is-size-5 has-text-left">Selected</div>
        </div>
        <div class="level-right">
            <div class="level-item">
                <i class="fas fa-sort-alpha-up is-clickable"></i>
            </div>
        </div>
    </nav>
    <hr class="mt-1 mb-3">
    <draggable class="list-group"
               v-model="list.selected"
               v-bind="dragOptions"
               :list="list.selected"
               :move="onMove"
               @change="changed">
        <button class="button is-fullwidth is-flex list-group-item o365_app_handle level is-mobile" v-for="(app, index) in list.selected" :key="app.id">
            <div class="level-left">
                    <span class="icon" aria-hidden="true">
                        <img :src="app.icon_url" />
                    </span>
                <span>{{app.name}}</span>
            </div>
            <div class="level-right">
                <span class="icon has-text-danger is-clickable" @click="remove(index)">
                  <i class="fas fa-times"></i>
                </span>
            </div>
        </button>
    </draggable>
</div>
<div class="column is-half-desktop is-full-mobile buttons">
    <div class="is-size-5 has-text-left">Available</div>
    <hr class="mt-1 mb-3">
    <draggable class="list-group"
               v-model="list.available"
               v-bind="dragOptions"
               :list="list.available"
               :move="onMove">
        <button class="button is-fullwidth is-flex list-group-item o365_app_handle level is-mobile" v-for="(app, index) in list.available" :key="app.id">
            <div class="level-left">
                <span class="icon" aria-hidden="true">
                    <img :src="app.icon_url" />
                </span>
                <span>{{app.name}}</span>
            </div>
            <div class="level-right">
                <span class="icon has-text-primary is-clickable" @click="add(index)">
                  <i class="fas fa-plus"></i>
                </span>
            </div>
        </button>
    </draggable>
</div>

输出以下项目,一切都很好。请参阅下面的视频显示,每个组件根据需要工作。这一切都很好!我正在调用changed()add 和 remove 方法,该方法获取所有 ID 并通过端点将它们存储在数据库中。

在此处输入图像描述


问题

现在我有以下下拉菜单,它取决于fh/v1/menus/applications端点来拉入所有项目,如下所示:

在此处输入图像描述

正如您在下面看到的,当我打开下拉菜单时,它有三个应用程序,当我打开齿轮并删除其中一个应用程序并保存它但下拉菜单不会自动更新时,我必须刷新页面并然后我会看到更新。

有谁知道如何在不刷新的情况下获取新项目?

这是下拉片段的 HTML 和 JS:

HTML:正如您在其中看到的,我将data-source="applications"其中的项目拉入其中,init_menu如 JS 所示。

<div class="dropdown-menu" id="dropdown-o365" role="menu">
    <div class="dropdown-content">
        <div class="container is-fluid px-4 pb-4">
            <?php if ($application = Applications::init()): ?>
            <div class="columns">
                <div class="dropdown-item column is-full has-text-centered is-size-6">
                    <div class="level is-mobile">
                        <div class="level-left">
                            <?= $application->get_name() ?>
                        </div>
                        <div class="level-right">
                            <a class="navbar-item modal-element icon" id="o365-apps-cogwheel" data-target="o365-modal-edit" aria-haspopup="true">
                                <i class="fa fa-cog"></i>
                            </a>
                        </div>
                    </div>
                </div>
            </div>
            <div class="columns is-multiline" data-source="applications"></div>
            <?php else: ?>
            <div class="columns">
                <div class="column is-full">
                    No applications present.
                </div>
            </div>
            <?php endif; ?>
        </div>
    </div>
</div>

然后是 JavaScript。我使用以下方法初始化内部DOMContentLoaded方法init_menu('applications');

function init_menu(paths)
{
    paths.forEach(path => {
        const target = document.querySelector('[data-source=' + path + ']');
        if (target) {
            wp.api.loadPromise.done(function () {
                const Menus = wp.api.models.Post.extend({
                    url: wpApiSettings.root + 'fh/v1/menus/' + path,
                });
                const menus = new Menus();
                menus.fetch().then(posts => {

                    // This returns the data object.
                    const data = posts.data;
                    let post_list;

                    // Check if it's an array and see if selected is empty otherwise show available.
                    if (Array.isArray(data.selected) && data.selected.length !== 0) {
                        post_list = data.selected;
                    } else {
                        post_list = data.available;
                    }
                    post_list.forEach(function (post) {
                        switch(path) {
                            case 'applications':
                                target.appendChild(create_apps_dom_tree(post));
                                break;
                            default:
                                console.log('Path route is invalid.');
                                break;
                        }
                    })
                })
            })
        }
    });
}

function create_apps_dom_tree(post) {
    const {
        icon_url,
        url,
        name,
    } = post
    const container = document.createElement('div');
    container.className = 'column is-one-third is-flex py-0';
    const anchor = document.createElement('a');
    anchor.href = url;
    anchor.className = 'dropdown-item px-2 is-flex is-align-items-center';
    const figure = document.createElement('figure');
    figure.className = 'image is-32x32 is-flex';
    const img = document.createElement('img');
    img.src = icon_url;
    const span = document.createElement('span');
    span.className = 'pl-2';
    span.textContent = name;
    figure.appendChild(img);
    anchor.append(figure, span);
    container.appendChild(anchor);
    return container;
}

如果有人对如何从数据库中即时提取实时数据有一些指导或答案,那将是惊人的。

基本上,我需要data-source:在发送我的 vue/db 请求时自动抓取项目,这样我就不必刷新页面。

在我的 Vue 应用程序中,我有以下方法:

fetchApplicationsMenu() {
    var self = this;
    wp.apiRequest( {
        path: 'fh/v1/menus/applications',
        method: 'GET',
    }).then(menu => self.list = menu.data);
},

它调用 GET 请求,然后将数据存储在return { list: {} }.

标签: javascriptjquerywordpressvue.jsvuejs2

解决方案


一个快速的解决方法可能是init_menu()从组件的beforeDestroy()hook中调用,在对话框关闭时调用。changed()如果在此对话框打开的情况下仍可访问下拉菜单,则您可以选择执行此操作。

new Vue({
  // option 1:
  beforeDestroy() {
    init_menu('applications');
  },

  // option 2:
  methods: {
    changed() {
      init_menu('applications');
    }
  }
})

备选方案:您已经知道最终应用程序列表在什么中changed(),因此您可以使用该方法中的新列表更新下拉列表。

function update_menu(path, post_list) {
  const target = document.querySelector('[data-source=' + path + ']');

  // remove all existing children
  Array.from(target.childNodes).forEach(x => x.remove());

  post_list.forEach(post => target.appendChild(create_apps_dom_tree(post)))
}

new Vue({
  methods: {
    changed() {
      update_menu('applications', this.$data.available);
    }
  }
})

推荐阅读