我有这个基于Codeigniter和jQuery的大型遗留Web应用程序。
计划是逐步淘汰jQuery并开始使用Vuejs。我们正在逐步更换网站的某些部分。
我刚刚安装了Nuxtjs,并在遗留项目中获得了我喜欢的文件结构。
现在进入问题。如何从我的一个遗留 JavaScript 文件访问 Vue 组件?
App.vue
<template>
<div id="app">
<HelloWorld msg="Welcome to Your Vue.js + TypeScript App" />
</div>
</template>
<script lang="ts">
import Vue from "vue";
import HelloWorld from "./components/HelloWorld.vue";
export default Vue.extend({
name: "App",
components: {
HelloWorld
}
});
</script>
主目录
import Vue from "vue";
import App from "./App.vue";
import store from "./store";
Vue.config.productionTip = false;
new Vue({
store,
render: h => h(App)
}).$mount("#app");
我想在普通的 php/html 视图中显示我的 App.vue。
我现在正在做类似的事情,该项目最初是使用 Thymeleaf 和 jQuery 编写的,现在我们正在切换到 Vue。
你可以用几种方式在 vue 组件和非 vue 组件之间进行通信,它们都不是"漂亮的"。
通信
经典 JavaScript 事件
非常简单
// legacy code
document.dispatchEvent(new CustomEvent('legacy-vue.something-happened', { detail: payload }))
// vue component
created () {
document.addEventListener('legacy-vue.something-happened', this.onSomethingHappened)
},
destroyed () { // don't forget to remove the listener!
document.removeEventListener('legacy-vue.something-happened', this.onSomethingHappened)
}
公开事件中心
与前一个类似,但您使用的是 vue 事件。这是我推荐的,因为这是 Vue 处理事件的方式,你的目标是让你的应用程序 vuetized。
// initialization
const hub = new Vue()
Vue.prototype.$eventHub = hub
window.$vueEventHub = hub
// legacy code
$vueEventHub.$emit('something-happened', payload)
// vue component
created () {
this.$eventHub.$on('something-happened', this.onSomethingHappened)
},
destroyed () {
this.$eventHub.$off('something-happened', this.onSomethingHappened)
}
公开整个组件
最灵活的方式,但很难看到哪里发生了什么。在我看来,基于事件的接近较小的邪恶(跟踪事件很容易(。
// vue component
created () {
window.vueTableComponent = this
}
// legacy component
vueTableComponent.fetchNextPage()
vueTableComponent.registerOnPageFetchedCallback(callback);
总结
无论您选择哪种方法,我都建议您执行以下操作:
假设你有 TableComponent。TableComponent很少有像apiUrl这样的道具,发出row-clicked
事件等。最好在不考虑遗留代码的情况下设计组件,然后创建它的遗留包装器,因为一度它将与仅 vue 屏幕和混合屏幕(包含遗留组件和 vue 组件(一起使用。举个例子:
LegacyTableComponentWrapper.vue
<template>
<table-component
:api-path="apiPath"
@row-clicked="onRowClicked"
ref="table-component"
/>
</template>
export default {
data: () => ({
apiPath: null
}),
methods: {
onRowClicked (row) {
this.$eventHub.$emit('table-row-clicked', row) // notify legacy code
},
onApiPathDefined (payload) {
this.apiPath = payload
}
},
mounted () {
// legacy code might require the TableComponent to act differently
// and if you don't want the TableComponent to know whenever it's legacy or not
// you can always override one or more of it's methods.
this.$refs['table-component'] = this.overriddenImplementationOfXYZ
},
created () {
this.$eventHub.$on('define-api-path', this.onApiPathDefined)
},
destroyed () {
this.$eventHub.$off('define-api-path', this.onApiPathDefined)
}
}
一开始肯定会有更多的工作,但以后会让你头疼,当你将处理你的第一个视图时,它完全在 vue 中,所有遗留的通信内容都在路上。