我已经有了这个基于Codeigniter和jQuery的大型遗留网络应用。
我们的计划是逐步淘汰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>
主.ts
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");
我想在一个普通的phphtml视图中显示我的App.vue。
我现在也在做类似的事情,项目最初是用Thymeleaf和jQuery写的,现在我们要换成Vue。
vue组件和非vue组件之间可以通过几种方式进行通信,没有一种方式是 "漂亮 "的。
很简单
// 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处理事件的方式,而您的目标是让您的应用变得更加生动。
// 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中的,而那些遗留的通信东西都会妨碍你的工作。