sourcecode

웹 확장의 공유 vuex 상태(데드 개체 문제)

copyscript 2022. 8. 27. 10:10
반응형

웹 확장의 공유 vuex 상태(데드 개체 문제)

웹 확장에서 공유 vue.js 상태를 사용하려고 합니다.

상태는 백그라운드스크립트의 DOM에 저장되어 팝업페이지에 표시됩니다.

첫 번째 시도

첫 번째 시도는 vuex가 없는 단순한 스토어를 사용하는 것이었습니다.

background.displays(배경).

var store = {
  count: 0
};

poppup.displaces

browser.runtime.getBackgroundPage().then(bg => {
    var store = bg.store;

    var vue = new Vue({
        el: '#app',
        data: {
            state: store
        },
    })
})

poppup.displaces

<div id="app">
  <p>{{ state.count }}</p>
  <p>
    <button @click="state.count++">+</button>
  </p>
</div>
<script src="vue.js"></script>
<script src="popup.js"></script>

이것은 팝업이 처음 열렸을 때 기능하지만(카운터를 늘릴 수 있고 값이 갱신됩니다), 팝업이 두 번째로 열리면 렌더링에 실패합니다.[Vue warn]: Error in render: "TypeError: can't access dead object"이는 첫 번째 팝업에서 vue.js 인스턴스가 변경된 것이 원인인 것 같습니다.store자체 getter/setters를 설정함으로써 첫 번째 팝업이 닫힌 후 삭제되어 공유 상태를 사용할 수 없게 됩니다.어쩔 수 없을 것 같아서 Vuex를 시도해 보기로 했어요.

두 번째 시도

background.displays(배경).

var store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment: state => state.count++,
  }
})

poppup.displaces

browser.runtime.getBackgroundPage().then(bg => {
    var store = bg.store;

    var vue = new Vue({
        el: '#app',
        computed: {
            count () {
                return store.state.count
            }
        },
        methods: {
            increment () {
                store.commit('increment')
            },
        }
    });
})

poppup.displaces

<div id="app">
  <p>{{ count }}</p>
  <p>
    <button @click="increment">+</button>
  </p>
</div>
<script src="vue.js"></script>
<script src="popup.js"></script>

아쉽게도 이것도 안 돼요.팝업을 열고 현재 카운터 값을 볼 수 있지만, 이 값을 늘린다고 해서 보기가 업데이트되지는 않습니다(팝업을 다시 열어야 새 값이 표시됩니다).

popup.js에서 스토어를 선언한 경우 코드는 정상적으로 동작하기 때문에 동작합니다만, 어떠한 이유로 동작하지 않습니다.

질문:

  • vue.js는 이 사용 사례를 전혀 처리할 수 없습니까?
  • 그렇다면 다른 프레임워크(각도, 반응 등)는 여기서 작동합니까?

vue 인스턴스가 백그라운드 및 팝업에서 동일하지 않기 때문에 작동하지 않습니다.따라서 백그라운드에서 상태를 가져오면 해당 상태의 워쳐가 팝업 보기가 아닌 백그라운드 페이지 내에서 Vue를 반응시킵니다.백그라운드 및 팝업에서 동일한 저장소를 사용하고 둘 사이의 상태를 동기화하면 이 작업을 수행할 수 있습니다.상태를 동기화하려면 localStorage를 사용하여 상점의 여러 인스턴스를 통해 돌연변이를 전파하는 우수한 플러그인 vuex-shared-mutations를 사용할 수 있습니다.스토어에서 추가

import createMutationsSharer from 'vuex-shared-mutations'
//...
export default new Vuex.Store({
   //...
   plugins: [createMutationsSharer({ predicate: ['increment'] })],
});

이제 팝업이 버튼에 반응하고 배경이 증가합니다.팝업을 다시 열면 새 저장소를 만들었기 때문에 카운트가 0이 됩니다.팝업이 초기화되면 초기 상태를 로드해야 합니다.

store.syslog:

export default new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment: state => state.count++,
    setCount (state, count) {
      state.count = count
    },
  },
  plugins: [createMutationsSharer({ predicate: ['increment'] })],
  actions: {
    getCount ({ commit }) {
      browser.runtime.sendMessage({type: "storeinit", key: "count"}).then(count => {
        commit('setCount', count)
      })
    }
  }
});

background.displays(배경).

import store from './store';
browser.runtime.onMessage.addListener((message, sender) => {
    if (message.type === 'storeinit') {
        return Promise.resolve(store.state[message.key]);
    }
});

poppup.displaces

import store from '../store';
var vue = new Vue({
  //...
  created () {
    this.$store.dispatch('getCount')
  }
});

이러한 문제는 관련이 없습니다.리액트 사용자는 프록시를 사용하여 브라우저 확장으로 상태를 전파합니다.react-chrome-redux

지연되어 죄송합니다. 노드 모듈을 만듭니다.

https://github.com/MitsuhaKitsune/vuex-webextensions

모듈은 webextensions 메시징 API를 사용하여 webextension의 모든 스토어 인스턴스를 동기화합니다.

설치는 다른 vuex 플러그인과 같으므로 Readme에서 확인할 수 있습니다.

질문이나 피드백이 있으시면 여기 또는 github 문제에 대해 말씀해 주십시오.

언급URL : https://stackoverflow.com/questions/49341734/shared-vuex-state-in-a-web-extension-dead-object-issues

반응형