Vue-multiselect 不一致的反应选项
Vue-multiselect inconsistent reactive options
所以我正在使用 Laravel Spark 构建一个应用程序,因此我借此机会学习了一些 Vue.js。
我花的时间比我希望的要长,但我几乎让 Vue-multiselect 为一组选项工作,通过 get 请求检索所选选项,然后更新.
到目前为止,我所采用的方法可能远非最佳,所以请耐心等待,但它似乎只有约 60% 的时间加载选定的选项。要清楚 - 控制台中从来没有任何 warnings/errors 记录,如果我检查网络选项卡,获取导师仪器的请求总是成功返回相同的结果...
我已经声明了一个全局数组就绪:
var vm = new Vue({
data: {
tutorinstruments: []
}
});
然后我的主要组件发出请求并更新变量:
getTutor() {
this.$http.get('/get/tutor')
.then(response => {
this.tutor = response.data;
this.updateTutor();
});
},
updateTutor() {
this.updateTutorProfileForm.profile = this.tutor.profile;
vm.tutorinstruments = this.tutor.instruments;
},
然后我从 Vue-multiselect 中自定义的多选工具获取所有可用的工具并更新可用的工具,以及那些被选中的工具:
getInstruments() {
this.$http.get('/get/instruments')
.then(response => {
this.instruments = response.data;
this.updateInstruments();
});
},
updateInstruments() {
this.options = this.instruments;
this.selected = vm.tutorinstruments;
},
可用的选项总是。
Here's a YouTube link to how it looks if you refresh the page over and over
我乐于接受任何建议,欢迎提供帮助!
您的全局数组 var vm = new Vue({...})
是一个单独的 Vue 实例,它位于处理用户界面的主 Vue 实例之外。
这就是您在组件中同时使用 this
和 vm
的原因。在您的方法中,this
指向处理用户界面的 Vue 实例,而 vm
指向您在 Vue 实例外部初始化的全局数组。
请再次查看此指南页面:https://vuejs.org/v2/guide/instance.html
如果您查看初始化所有 Vue 功能的生命周期图,您会注意到它在很多地方都提到了 Vue 实例。这些功能(反应性、数据绑定等)旨在在 Vue 实例内运行,而不是跨多个实例运行。它可能会在适当的时候偶尔起作用,但不能保证一定起作用。
要解决此问题,您可以重新设计您的应用,使其具有 单个 Vue 实例 来处理用户界面和数据。
理想情况下,我希望您的 tutorinstruments
被加载到初始化您的应用程序的代码中(在根组件中使用 mounted
挂钩),并存储在 Vuex 中状态。在 Vuex 状态 中拥有数据后,所有组件都可以访问它。
Vuex 参考:https://vuex.vuejs.org/en/intro.html
希望对您有所帮助!我知道我没有为您的问题提供直接的解决方案。如果您无法将您的应用重组为单个 Vue 实例,也许我们可以等待更直接的答案。
Mani 写的是 100% 正确的,我要插话的原因是因为我刚刚用 PHP 和 Vue 构建了一个非常大的项目,我觉得我在一个很好的位置,可以给你一些建议/我在构建 PHP(服务器端)网站的过程中学到的东西,但将 Vue(客户端)添加到前端模板的组合中。
这可能比您的多选问题的范围要大一些,但我也会为您提供一个坚实的开端。
首先,您需要确定他们中的哪一个将在您的网络应用程序中执行路由(当用户访问处理流量的页面时),因为这将决定您要使用的方式看。假设为了讨论起见,您决定使用 PHP 进行身份验证(如果您有登录),但您打算在前端使用 Vue 处理路由。在这种情况下,您肯定想要一个主要的 Vue 实例,并且或多或少地设置类似于 Vue Router 中的示例的东西,假装 HTML 文件是您的 PHP index.php 在网络根目录中,这最终应该是唯一的 .php 文件,就模板而言,我需要它处理所有页眉元和页脚版权内容,在正文中你基本上只是想要一个带有 ID 应用程序的 div。
然后你只需使用 vue 路由器和路由来为你的所有页面加载你的 vue 组件(每个页面或页面类别一个很容易工作)。如果您在主要 app.vue 中查找并使用动态组件根据路由在页面组件中进行延迟加载,从而使您的包保持较小,则可获得加分。
*提示你还需要一个带有 babel 的 polyfill 来做到这一点
模板
<Component :is="dynamicComponent"/>
脚本
components: {
Account: () => import('./Account/Account.vue'),
FourOhFour: () => import('../FourOhFour.vue')
},
computed: {
dynamicComponent() {
return this.$route.name;
}
},
现在我们可以处理您的多选问题(这基本上也将帮助您了解一种简单的方法来将您在网上找到的任何 Vue 组件加载到您的站点中)。在有人访问路由时加载的页面组件之一让我们说/tutor(我还通过本地化然后使用道具,元字段和路由器守卫将我的身份验证信息从 PHP 传递到我的路由中,它所有内容都在该文档中,所以如果您想探索,我会把它留给您)在 tutor.vue 上,我们将称您的页面组件是您要在多选中调用的位置。同样在这一点上,我们仍然连接到我们的主要 Vue 实例,所以如果你想从 tutor.vue 引用它或你的路由器,你可以使用 Vue API 几乎任何替换 Vue 或 vm 的东西.但是巧妙的是在你的主 JS 文件/模块中你在 Vue 之外添加到它你仍然可以使用 API 在你加载主实例之后用 Vue 引用你的主 Vue 实例并做任何你想做的事情就像你或多或少在一个组件中。
这就是我处理添加外部组件的方式,将它们包装在您控制的另一个组件中,并使它们成为页面组件的 child。这是一个非常简单的多选示例,假设 parent 是 tutor.vue.
我还有一个全局事件总线 运行,我想你可能会喜欢这个主意
https://alligator.io/vuejs/global-event-bus/
tutor.vue
<template>
<div
id="user-profile"
class="account-content container m-top m-bottom"
>
<select-input
:saved-value="musicPreviouslySelected"
:options="musicTypeOptions"
:placeholder="'Choose an your music thing...'"
@selected="musicThingChanged($event)"
/>
</div>
</template>
<script>
import SelectInput from './SelectInput';
import EventBus from './lib/eventBus';
export default {
components: {
SelectInput
},
data() {
return {
profileLoading: true,
isFullPage: false,
isModalActive: false,
slackId: null,
isActive: false,
isAdmin: false,
rep: {
id: null,
status: '',
started: '',
email: '',
first_name: '',
},
musicTypeOptions: []
};
},
created() {
if (org.admin) {
this.isAdmin = true;
}
this.rep.id = parseInt(this.$route.params.id);
this.fetchData();
},
mounted() {
EventBus.$on('profile-changed', () => {
// Do something because something happened somewhere else client side.
});
},
methods: {
fetchData() {
// use axios or whatever to fetch some data from the server and PHP to
// load into the page component so say we are getting the musicTypeOptions
// which will be in our selectbox.
},
musicThingChanged(event) {
// We have our new selection "event" from multiselect so do something
}
}
};
</script>
这是我们的 child 多选包装器 SelectInput.vue
<template>
<multiselect
v-model="value"
:options="options"
:placeholder="placeholder"
label="label"
track-by="value"
@input="inputChanged" />
</template>
<script>
import Multiselect from 'vue-multiselect';
export default {
components: { Multiselect },
props: {
options: {
type: [Array],
default() {
return [];
}
},
savedValue: {
type: [Array],
default() {
return [];
}
},
placeholder: {
type: [String],
default: 'Select Option...'
}
},
data() {
return {
value: null
};
},
mounted() {
this.value = this.savedValue;
},
methods: {
inputChanged(selected) {
this.$emit('selected', selected.value);
}
}
};
</script>
<style scoped>
@import '../../../../../node_modules/vue-multiselect/dist/vue-multiselect.min.css';
</style>
现在您可以确保管理页面的生命周期以及您拥有的数据,您可以等到获得 musicTypeOptions,然后将其传递给 SelectInput 组件,该组件将依次设置 Multiselect 或任何其他组件然后处理通过 this.$emit('hihiwhatever') 传回的数据,该数据由模板中组件上的@hihiwhatever 获取,该组件回调函数,现在您可以对新选择并将不同的数据传递给 SelectInput 和 MultiSelect 将始终保持同步。
现在根据经验给出我最后的建议。抵制诱惑,因为你每天阅读它 650 次,在这样的设置中使用 Vuex 似乎是正确的做法。你已经有了 PHP 和一个数据库,使用它就像使用 Vuex 一样,如果你在 Node.js 中制作,你不是你有一个非常棒的 PHP 服务器端存储,尝试在前端的 Vuex 中管理数据,同时让 PHP 和数据库服务器端管理数据,一旦您开始让多个用户登录并弄乱 Vuex 数据,就会以灾难告终,从 PHP 服务器端你将无法保持单一的事实。如果你没有服务器端数据库,是的,Vuex 吧,但不要让自己头疼,等到你使用 Node.js 100%.
后再试试吧
如果您想管理比页面视图生命周期更长的客户端数据,请使用类似 https://github.com/gruns/ImmortalDB 的方法,它对我很有帮助。
抱歉,这变成了一个博客 post 哈哈,但我希望它能帮助人们节省几周的时间。
所以我正在使用 Laravel Spark 构建一个应用程序,因此我借此机会学习了一些 Vue.js。
我花的时间比我希望的要长,但我几乎让 Vue-multiselect 为一组选项工作,通过 get 请求检索所选选项,然后更新.
到目前为止,我所采用的方法可能远非最佳,所以请耐心等待,但它似乎只有约 60% 的时间加载选定的选项。要清楚 - 控制台中从来没有任何 warnings/errors 记录,如果我检查网络选项卡,获取导师仪器的请求总是成功返回相同的结果...
我已经声明了一个全局数组就绪:
var vm = new Vue({
data: {
tutorinstruments: []
}
});
然后我的主要组件发出请求并更新变量:
getTutor() {
this.$http.get('/get/tutor')
.then(response => {
this.tutor = response.data;
this.updateTutor();
});
},
updateTutor() {
this.updateTutorProfileForm.profile = this.tutor.profile;
vm.tutorinstruments = this.tutor.instruments;
},
然后我从 Vue-multiselect 中自定义的多选工具获取所有可用的工具并更新可用的工具,以及那些被选中的工具:
getInstruments() {
this.$http.get('/get/instruments')
.then(response => {
this.instruments = response.data;
this.updateInstruments();
});
},
updateInstruments() {
this.options = this.instruments;
this.selected = vm.tutorinstruments;
},
可用的选项总是。
Here's a YouTube link to how it looks if you refresh the page over and over
我乐于接受任何建议,欢迎提供帮助!
您的全局数组 var vm = new Vue({...})
是一个单独的 Vue 实例,它位于处理用户界面的主 Vue 实例之外。
这就是您在组件中同时使用 this
和 vm
的原因。在您的方法中,this
指向处理用户界面的 Vue 实例,而 vm
指向您在 Vue 实例外部初始化的全局数组。
请再次查看此指南页面:https://vuejs.org/v2/guide/instance.html
如果您查看初始化所有 Vue 功能的生命周期图,您会注意到它在很多地方都提到了 Vue 实例。这些功能(反应性、数据绑定等)旨在在 Vue 实例内运行,而不是跨多个实例运行。它可能会在适当的时候偶尔起作用,但不能保证一定起作用。
要解决此问题,您可以重新设计您的应用,使其具有 单个 Vue 实例 来处理用户界面和数据。
理想情况下,我希望您的 tutorinstruments
被加载到初始化您的应用程序的代码中(在根组件中使用 mounted
挂钩),并存储在 Vuex 中状态。在 Vuex 状态 中拥有数据后,所有组件都可以访问它。
Vuex 参考:https://vuex.vuejs.org/en/intro.html
希望对您有所帮助!我知道我没有为您的问题提供直接的解决方案。如果您无法将您的应用重组为单个 Vue 实例,也许我们可以等待更直接的答案。
Mani 写的是 100% 正确的,我要插话的原因是因为我刚刚用 PHP 和 Vue 构建了一个非常大的项目,我觉得我在一个很好的位置,可以给你一些建议/我在构建 PHP(服务器端)网站的过程中学到的东西,但将 Vue(客户端)添加到前端模板的组合中。
这可能比您的多选问题的范围要大一些,但我也会为您提供一个坚实的开端。
首先,您需要确定他们中的哪一个将在您的网络应用程序中执行路由(当用户访问处理流量的页面时),因为这将决定您要使用的方式看。假设为了讨论起见,您决定使用 PHP 进行身份验证(如果您有登录),但您打算在前端使用 Vue 处理路由。在这种情况下,您肯定想要一个主要的 Vue 实例,并且或多或少地设置类似于 Vue Router 中的示例的东西,假装 HTML 文件是您的 PHP index.php 在网络根目录中,这最终应该是唯一的 .php 文件,就模板而言,我需要它处理所有页眉元和页脚版权内容,在正文中你基本上只是想要一个带有 ID 应用程序的 div。
然后你只需使用 vue 路由器和路由来为你的所有页面加载你的 vue 组件(每个页面或页面类别一个很容易工作)。如果您在主要 app.vue 中查找并使用动态组件根据路由在页面组件中进行延迟加载,从而使您的包保持较小,则可获得加分。
*提示你还需要一个带有 babel 的 polyfill 来做到这一点 模板
<Component :is="dynamicComponent"/>
脚本
components: {
Account: () => import('./Account/Account.vue'),
FourOhFour: () => import('../FourOhFour.vue')
},
computed: {
dynamicComponent() {
return this.$route.name;
}
},
现在我们可以处理您的多选问题(这基本上也将帮助您了解一种简单的方法来将您在网上找到的任何 Vue 组件加载到您的站点中)。在有人访问路由时加载的页面组件之一让我们说/tutor(我还通过本地化然后使用道具,元字段和路由器守卫将我的身份验证信息从 PHP 传递到我的路由中,它所有内容都在该文档中,所以如果您想探索,我会把它留给您)在 tutor.vue 上,我们将称您的页面组件是您要在多选中调用的位置。同样在这一点上,我们仍然连接到我们的主要 Vue 实例,所以如果你想从 tutor.vue 引用它或你的路由器,你可以使用 Vue API 几乎任何替换 Vue 或 vm 的东西.但是巧妙的是在你的主 JS 文件/模块中你在 Vue 之外添加到它你仍然可以使用 API 在你加载主实例之后用 Vue 引用你的主 Vue 实例并做任何你想做的事情就像你或多或少在一个组件中。
这就是我处理添加外部组件的方式,将它们包装在您控制的另一个组件中,并使它们成为页面组件的 child。这是一个非常简单的多选示例,假设 parent 是 tutor.vue.
我还有一个全局事件总线 运行,我想你可能会喜欢这个主意 https://alligator.io/vuejs/global-event-bus/
tutor.vue
<template>
<div
id="user-profile"
class="account-content container m-top m-bottom"
>
<select-input
:saved-value="musicPreviouslySelected"
:options="musicTypeOptions"
:placeholder="'Choose an your music thing...'"
@selected="musicThingChanged($event)"
/>
</div>
</template>
<script>
import SelectInput from './SelectInput';
import EventBus from './lib/eventBus';
export default {
components: {
SelectInput
},
data() {
return {
profileLoading: true,
isFullPage: false,
isModalActive: false,
slackId: null,
isActive: false,
isAdmin: false,
rep: {
id: null,
status: '',
started: '',
email: '',
first_name: '',
},
musicTypeOptions: []
};
},
created() {
if (org.admin) {
this.isAdmin = true;
}
this.rep.id = parseInt(this.$route.params.id);
this.fetchData();
},
mounted() {
EventBus.$on('profile-changed', () => {
// Do something because something happened somewhere else client side.
});
},
methods: {
fetchData() {
// use axios or whatever to fetch some data from the server and PHP to
// load into the page component so say we are getting the musicTypeOptions
// which will be in our selectbox.
},
musicThingChanged(event) {
// We have our new selection "event" from multiselect so do something
}
}
};
</script>
这是我们的 child 多选包装器 SelectInput.vue
<template>
<multiselect
v-model="value"
:options="options"
:placeholder="placeholder"
label="label"
track-by="value"
@input="inputChanged" />
</template>
<script>
import Multiselect from 'vue-multiselect';
export default {
components: { Multiselect },
props: {
options: {
type: [Array],
default() {
return [];
}
},
savedValue: {
type: [Array],
default() {
return [];
}
},
placeholder: {
type: [String],
default: 'Select Option...'
}
},
data() {
return {
value: null
};
},
mounted() {
this.value = this.savedValue;
},
methods: {
inputChanged(selected) {
this.$emit('selected', selected.value);
}
}
};
</script>
<style scoped>
@import '../../../../../node_modules/vue-multiselect/dist/vue-multiselect.min.css';
</style>
现在您可以确保管理页面的生命周期以及您拥有的数据,您可以等到获得 musicTypeOptions,然后将其传递给 SelectInput 组件,该组件将依次设置 Multiselect 或任何其他组件然后处理通过 this.$emit('hihiwhatever') 传回的数据,该数据由模板中组件上的@hihiwhatever 获取,该组件回调函数,现在您可以对新选择并将不同的数据传递给 SelectInput 和 MultiSelect 将始终保持同步。
现在根据经验给出我最后的建议。抵制诱惑,因为你每天阅读它 650 次,在这样的设置中使用 Vuex 似乎是正确的做法。你已经有了 PHP 和一个数据库,使用它就像使用 Vuex 一样,如果你在 Node.js 中制作,你不是你有一个非常棒的 PHP 服务器端存储,尝试在前端的 Vuex 中管理数据,同时让 PHP 和数据库服务器端管理数据,一旦您开始让多个用户登录并弄乱 Vuex 数据,就会以灾难告终,从 PHP 服务器端你将无法保持单一的事实。如果你没有服务器端数据库,是的,Vuex 吧,但不要让自己头疼,等到你使用 Node.js 100%.
后再试试吧如果您想管理比页面视图生命周期更长的客户端数据,请使用类似 https://github.com/gruns/ImmortalDB 的方法,它对我很有帮助。
抱歉,这变成了一个博客 post 哈哈,但我希望它能帮助人们节省几周的时间。