background

In the process of project development, we often encounter the need to jump from the previous page to the next page, commonly known as drill-down. For example, if you need to view the details of the data on the overview page, click a chart or button to jump to the details page to view the details of the data.

So far, there is not a unified page jump method in our project, and the way to realize page jump varies from person to person. In addition, many existing projects can only jump back and forth between two pages, and there is basically no complete function to realize multiple pages jump to each other.

Associated page jump as a common function of the project, and the implementation is highly repetitive code logic, it is necessary to extract the relevant logic, encapsulated into easy to use public methods and common components.

purpose

Unify the associated jump method logic of each project and encapsulate it into a common component that is easy to use.

The project design

First of all, analyze the general logical steps of associated page jump:

  1. Go to page A.
  2. Switch from page A to page B.
  3. Go to page B.
  4. Return to page A;
  5. Go to page A, that is, go to Step 1.

Then, break down the above steps:

  1. Assuming step 1 is a normal page entry, there is no logic to deal with.
  2. Step 2 Run the following command fromA pageJump toPage BTo do this, you need to knowPage BThe routing address of theVueRouterJump toPage BThe routing address of. And if thePage BNeed some query data, to putPage BSave the data and wait until Step 3.
  3. After entering page B, if you want to get some query data from page A, you should first determine whether it is jumped from page A, if it is, from the place where the data is saved to get the data from page A;
  4. fromPage BreturnA page, you need to knowA pageThe routing address of theVueRouterJump toA pageThe routing address of. You can obtain the route address only after saving it before going to Step 2.
  5. Can be found that steps 1 and 5 are entering the page A, but perform logic is different, so the page if you want to restore to jump to page B before some of the data, to determine first whether to jump from the page B come back, if it is, is from the place where save the data to obtain A jump before page data; The data before the jump can be retrieved only after being saved before the jump in Step 2.

Next, to implement the logic above, let’s determine the method to save the data for pages A and B, in this case VUEX. Review the above logical steps and draw a flow chart.

The flow chart

The source page

The target page

The specific implementation

The source page is displayed

The logic of this step is written in VUEX. You can directly tune the corresponding method in VUEX each time you need to perform this step. The implementation logic is to add the identifiers of the source page and destination page to the route parameters (to distinguish the current page from the returned source page), save the data of the source page and destination page, and then redirect the route.

Add the following two variables to store.js:

tgtPageParams: {}, // Associate the target page data with the jump (only one item is reserved)
srcPageParams: [].// Jump to the source page data (array type, keep multiple pages of data, can be returned in multiple layers, until the original page)
Copy the code

Then add the following methods:

Vuex = Vuex; Vuex = Vuex; Vuex = Vuex; Vuex = Vuex
goTargetPage(state, options) {
    // Add the tgtPageName tag to the query of the source page, remembering the target page
    options.srcParams.query = Object.assign({}, options.srcParams.query, { tgtPageName: options.tgtParams.name });
    // Add the srcPageName identifier to the query of the target page, remembering the source page
    options.tgtParams.query = Object.assign({}, options.tgtParams.query, { srcPageName: options.srcParams.name });

    state.srcPageParams.push(options.srcParams); // Save source page data
    state.tgtPageParams = options.tgtParams; // Save the target page data

    router.push({ name: options.tgtParams.name, query: options.tgtParams.query }); // Jump to the target page
},
Copy the code

Destination page returns to source page

The logic of this step is written in VUEX. You can directly tune the corresponding method in VUEX each time you need to perform this step. The specific implementation logic is to get the data (including the routing address and parameters) of the source page from state.srcPageParams, and then jump the route.

Add the following methods to VUEX:

// Redirect to the source page
goSourcePage(state, vm) {
    let obj = state.srcPageParams.slice(-1) [0]; // Take the last item of the array
    // If Vuex has data from the previous page, go back to the previous page based on Vuex data
    if (obj && Object.keys(obj).length > 0) {
        router.push({ name: obj.name, query: obj.query }); // Jump
    }
    // If there is no previous page data in the Vuex, but there is a previous page mark on the route, the route will return to the previous page according to the route mark (this is to prevent the Vuex data loss during the refresh of the details page, and cannot return to the previous page).
    else if (vm && vm.$route.query.srcPageName) {
        router.push({ name: vm.$route.query.srcPageName }); }},Copy the code

Go to the target page. Use VUEX data or return to the source page to restore VUEX data

The logic of this step is to combine step 3 and Step 5 in the above scheme design and write it in the public function file. Every time you need to do this step operation, directly call the corresponding method in vue. prototype. The specific implementation logic is: determine whether the current page is the source page or the target page, if it is the target page, then use the data from the source page, if it is the source page, restore the data before the jump.

Add the following methods to the public function file utils.js and mount them to vue.prototype:

/** * select * from Vuex; /** * from Vuex; 3. After the data on the source page is recovered, delete the corresponding backup data in the Vuex and delete the target page identifier * saved on the route@param Vm {object} Specifies the current Vue component instance */
$changeVueData: (vm) = > {
    let tgtParams = store.state.tgtPageParams;
    let srcParams = vm.$store.state.srcPageParams.slice(-1) [0) | | {};// Take the last element
    let name = vm.$route.name;
    let query = vm.$deepCopyJSON(vm.$route.query); // Deep copy because $route.query needs to be updated

    // Determine whether the current page is the target page or the source page
    // Check whether the route name is consistent, and then check whether the attribute value of the specified query is consistent
    let isTgtPage = tgtParams.name === name &&
        (tgtParams.checkKeys ? tgtParams.checkKeys.every(key= > tgtParams.query[key] === query[key]) : true);
    let isSrcPage = srcParams.name === name &&
        (srcParams.checkKeys ? srcParams.checkKeys.every(key= > srcParams.query[key] === query[key]) : true);

    // If the current page is the target page
    if (isTgtPage) {
        Object.assign(vm.$data, tgtParams.data || {}); // Update the data from the source page to the current page's data() for the page to query
    }
    // If the current page is the source page
    if (isSrcPage) {
        Object.assign(vm.$data, srcParams.data || {}); // The data saved before the jump is updated to the current page's data() so that the page can be restored
        store.commit('popSourcePage'); // Delete the last item of srcPageParams
        // After the source page forward association logic is complete, the target page ID on the route of the current page is cleared to prevent page refresh problems
        deletequery.tgtPageName; vm.$router.push({ name, query }); }},Copy the code

Returns to the previous button

To facilitate the use of the link function, the button to return to the previous page is encapsulated as a component, and the specific implementation code is as follows:

// back-button.vue
<template>
    <button class="primary-btn return-btn" v-if="showBackBtn" @click="backFn">
        <i class="return-icon"></i>{{ backText }}
    </button>
</template>
<script>
export default {
    name: 'back-button'.props: {
        // Returns the text on the previous page
        backText: {
            type: String.default: () = > 'Previous step'
        },
        // Return the function on the previous page
        backFn: {
            type: Function.default: () = >{}}},data() {
        return {
            showBackBtn: false}; },mounted() {
        this.setBackBtnShow();
    },
    activated() {
        this.setBackBtnShow();
    },
    methods: {
        // Update returns the status of the previous button
        setBackBtnShow() {
            this.$nextTick(() = > {
                let srcPage = this.$store.state.srcPageParams.slice(-1) [0];
                this.showBackBtn = Boolean(srcPage && Object.keys(srcPage).length > 0); }); ,}}};</script>
<style scoped lang="scss">
</style>
Copy the code

Fault tolerant part

Considering that users may suddenly interrupt or refresh the page or other abnormal operations during the associated jump, a partial fault tolerance mechanism is designed:

// Root component app.vue
/ *... Omitted code... * /
watch: {
    // Listen when the route changes
    $route(to, from) {
        // If it is neither the source page nor the target page, clear the data saved in Vuex
        // Avoid changing menus or performing other operations during a Vuex association, which may cause residual data in the PREVIOUS Vuex association
        if(! to.query.srcPageName && ! to.query.tgtPageName) {this.$store.commit('clearTargetPage');
            this.$store.commit('clearSourcePage'); }}},/ *... Omitted code... * /
Copy the code

Use the sample

According to the steps of the design part of the scheme above: Step 1 and Step 5, enter page A, the logic is on the same page, the code is as follows:

/ / page Dr. Ue
/ *... Omitted code... * /
mounted() {
    vm = this;
    vm.$changeVueData(vm); $changeVueData ($changeVueData); $changeVueData ($changeVueData)

    vm.ready();
},
/ *... Omitted code... * /
Copy the code

Step 2 Switch from page A to page B. The code is as follows:

/ / page Dr. Ue
/ *... Omitted code... * /
methods: {
	// Go to page B
	goUserSituation: function (name) {
		let srcParams = {
			name: vm.$route.name,
			query: vm.$route.query
		};
		let tgtParams = {
			name: 'user-situation'.data: {
				checkedSystem: name } }; vm.$goTargetPage(srcParams, tgtParams); }},/ *... Omitted code... * /
Copy the code

Step 3 enter page B, and the code is as follows:

/ / page B.v ue
/ *... Omitted code... * /
mounted() {
    vm = this;
    vm.$changeVueData(vm); $changeVueData ($changeVueData); $changeVueData ($changeVueData)

    vm.ready();
},
/ *... Omitted code... * /
Copy the code

Step 4, return to page A with the following code:

/ / page B.v ue
/ *... Omitted code... * /
<template>
	<div>
        <backButton :backFn="$goSourcePage"></backButton>/ *... Omitted code... * /</div>
</template>
/ *... Omitted code... * /
Copy the code

conclusion

This article introduced the related page multistage jump page (under) the realization of the function, the core thought is through VUEX global state management, save the associated jump data source and the target page, before the jump, the need of data stored, jump to the target page, of data obtained from the VUEX target page needs, When switching back to the source page, data on the source page is recovered from the VUEX.

These key actions are encapsulated into general methods and components, which unify the associated page jump mode of each project, improve the quality of the code, and is more conducive to later maintenance. In addition, the fault tolerance part of the article, only part of the written, if the subsequent need to continue to improve the function, you can improve the fault tolerance part.

Finally, thank you for your reading. I hope it will be helpful to you. If you have different ideas and suggestions, please feel free to give them.