This is a guide to one of the many ways to migrate from AngularJS to Vue.js. It comes down to moving your AngularJS project to your Vue.js public folder, moving components/controllers one by one from AngularJS to Vue.js and keeping track of state changes via events.

Moving your static AngularJS project to a Vue CLI project

Setup a new Vue.js CLI project.

project tree

Then move the complete AngularJS project into the public folder.

project tree after adding angularjs

Add <div id="app"></div> above the ui-view (if used) to the public/index.html file of the AngularJS part of the project.

At this point, your project should already work. Simply run npm run serve and check if everything is okay.

Routing and component injecting

Now that the base of the project is set up, you will notice that when creating components the components will not be positioned yet where you want them, since the Vue.js context is not aware of the AngularJS context. To get components to be placed where we want them, we need to mount them in the correct location.

Let's take a route as an example. Vue router can be used together with AngularJS' ui-router. If you want to move an AngularJS component or controller to Vue.js then make sure that the route exists in both AngularJS and Vue.js.

AngularJS:

angularjs route

Vue.js:

vue.js route

Then create the component mounting service. You will be able to use this service for every component that needs to be inserted somewhere.

component mounting service

In the example vue.js component, mount the component to the right place in the AngularJS application.

    async mounted () {
        await ComponentMountingService.inject(this, `vue-component-error-log`);
    }

You'll now see that this component is loaded and shown whenever that route is loaded.

Tracking state changes

It might be necessary to share part of the state between Vue.js and AngularJS. One way to do this is by sending events between the two.

Sending and receiving data in Vue.js. This also sets it in the Vuex store.

    setPageTitle (title) {
        store.dispatch(SET_PAGE_TITLE, title);
        document.dispatchEvent(new CustomEvent("set-page-title", { detail: title }));
    }
    document.addEventListener("set-page-title", (event) => {
        store.dispatch(SET_PAGE_TITLE, event.detail);
    });

Sending and receiving data in AngularJS. This also sets it in the Vuex store.

    $scope.$watch("pageTitle", () => {
        document.dispatchEvent(new CustomEvent('set-page-title', { detail: $scope.pageTitle }));
    });
    document.addEventListener("set-page-title", (event) => {
        $scope.pageTitle = event.detail;
    });

This will only work one way though, since you might get into event loops.