vue $forceUpdate() 強制重新渲染及四種方案對比


v-for里面數據層次太多,或者套的組件層級太多, 數據變了,頁面沒有重新渲染,需手動強制刷新。

解決方法:運用 this.$forceUpdate()強制刷新

迫使 Vue 實例重新渲染。注意它僅僅影響實例本身和插入插槽內容的子組件,而不是所有子組件。

 

-------------------------------------------------------------------------------------------------------------------------------------

vue強制重新渲染四種方案對比

 

前言

Vue的雙向綁定屬於自動檔;在特定的情況下,需要手動觸發“刷新”操作,目前有四種方案可以選擇:

  1. 刷新整個頁面(最low的,可以借助route機制,不推薦)
  2. 使用v-if標記(比較low的,有時候不生效,不推薦)
  3. 使用內置的forceUpdate方法(較好的)
  4. 使用key-changing優化組件(最好的)

 


一、刷新整個頁面

this.$router.go(0)

 

二、使用v-if標記

如果是刷新某個子組件,則可以通過v-if指令實現。我們知道,當v-if的值發生變化時,組件都會被重新渲染一遍。因此,利用v-if指令的特性,可以達到強制刷新組件的目的。

<template>
    <comp v-if="refresh"></comp>
    <button @click="refreshComp()">刷新comp組件</button>
</template>
<script>
import comp from '@/views/comp.vue'
export default {
    name: 'parentComp',
    data() {
        return {
            refresh: true
        }
    },
    methods: {
        refreshComp() {
            // 移除組件
            this.refresh = false
            // 在組件移除后,重新渲染組件
            // this.$nextTick可實現在DOM 狀態更新后,執行傳入的方法。
            this.$nextTick(() => {
                this.refresh = true
            })
        }
    }
}
</script>

三、forceUpdate

 

組件內置$forceUpdate方法,如果不能強制刷新,嘗試使用前在配置中啟用。

import Vue from 'vue' Vue.forceUpdate()
<template>
  <div>
    <button @click="handleUpdateClick()">Refresh當前組件</button>
  </div>
</template>
export default {
  methods: {
    handleUpdateClick() {
      // built-in
      this.$forceUpdate()
    }
  }
}

四、key-changing

原理很簡單,vue使用key標記組件身份,當key改變時就是釋放原始組件,重新加載新的組件。

<template>
  <div>
    <span :key="key"></span>
  </div>
</template>
<script>
  export default {
    data() {
      return {
        key: 0
      }
    },
    methods: {
      handleUpdateClick() {
        this.key += 1 // 或者 this.key = new Date();
      }
    }
  }
</script>

五、應用場景

vue具有緩存的頁面的強制刷新

有些列表頁面需要進入詳情返回時有緩存功能,但是每次進入列表頁面又需要刷新列表,這種時候就需要手動刷新頁面

const routerConfig = {
      path: "/List",
      query: {
          time: new Date().getTime(),
      }
};
this.goPath(routerConfig);
List.vue

created () {
    this.initData();
    this.preTime = Number(this.$route.query.time);
},
activated () {
    const curTime = Number(this.$route.query.time);
    if(this.preTime !== curTime) {
        document.documentElement.scrollTop = 0;
        this.preTime = curTime;
        this.listInfo = {
            pageSize: 10,
            pageContext: '',
            hasMore: false,
            list: [],
        };
        this.initData();
    }
},

goPath是vue跳轉的一個封裝

main.js
/**
 * 根據前端路由跳轉到webview
 * @param config
 * @param type inPage: 利用h5路由跳轉
 */
Vue.prototype.goPath = function (routerConfig, type = 'web') {
    const config = routerConfig;
    // 統一添加參數
    if (this.$route.query.isSelfManage === '1') {
        config.query.isSelfManage = 1;
    }
    console.log(config);
    if (window.__wxjs_environment === 'miniprogram') {
        if (window.wx) {
            const params = this.$router.resolve(config).href;
            // 添加參數,兼容跳轉問題
            const toUrl = `${location.protocol}//${location.host}${location.pathname}${location.search}${params}`;
            if (type === 'web') {
                window.wx.miniProgram.navigateTo({
                    url: `/pages/webview/index?url=${encodeURIComponent(toUrl)}`,
                });
            } else if (type === 'inPage') {
                this.$router.push(config);
                if (!config.replace) {
                    this.$router.push(config);
                } else {
                    this.$router.replace(config);
                }
            } else {
                window.wx.miniProgram.navigateTo(config);
            }
        }
    } else {
        if (!config.replace) {
            this.$router.push(config);
        } else {
            this.$router.replace(config);
        }
    }
};

例如:進入頁面輸入框自動聚焦

一般情況下,加上以下代碼就可以聚焦

<template>
  <div>
    <input
        placeholder="大家都在搜"
        type="text"
        maxlength="500"
        v-model="inputInfo.msg"
        @blur="resizeView"
        v-focus
     >
  </div>
</template>
<script>
  export default {
    data() {
      return {
        inputInfo: { // 輸入框對象
            num: 0, // 字數
            msg: '' // 內容
        },
      }
    },
    watch: {
        [`options.msg`] () {
            let length = utils.fancyCount2(this.inputInfo.msg);
            this.$set(this.inputInfo, 'num', length);
        }
    },
    directives: {
        focus: {
            // 指令的定義
            inserted: function(el) {
                el.focus();
            }
        }
    },
    methods: {
      /**
         * input元素失去焦點時觸發
         */
        resizeView () {
            document.body.scrollIntoView(true);
        },
    }
  }
</script>

但是在有緩存的頁面,一般就只有第一次會聚焦,后面進入都不會聚焦,辦法就是用第四種強制刷新輸入框來聚焦

<template>
  <div>
    <input
        placeholder="大家都在搜"
        type="text"
        maxlength="500"
        v-model="inputInfo.msg"
        @blur="resizeView"
        v-focus
        :key="inputInfo.focus"
     >
     <button @click="handleUpdateClick()">Refresh當前組件</button>
  </div>
</template>
<script>
  export default {
    data() {
      return {
        inputInfo: { // 輸入框對象
            num: 0, // 字數
            msg: '', // 內容
            focus: '',
        },
      }
    },
    activated () {
        this.inputInfo.focus = new Date().getTime();
    },
    methods: {
    handleUpdateClick() {
      // built-in
      this.inputInfo.focus = new Date().getTime();
    }
  }
</script>

方案對比轉載自:(2條消息) Vue組件強制刷新(重新渲染)的四種方案對比_落花見流水的博客-CSDN博客


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM