使用对象数组触发Vuex存储中的React性

vuktfyat  于 2022-12-14  发布在  Vue.js
关注(0)|答案(2)|浏览(96)

我有以下store.jsvuex文件

import { createStore } from 'vuex'
import { Vue } from 'vue'

export default createStore({
    
    state: {
        sidebarHidden: false,
        route: {},
        loggedIn: false,
        loggedInEmail: '?',
        accountID: '??',
        loggedInFirstName: '???',
        // licenses: [],
        licenses:[
            {
                "id": 1,
                "name": "xxx@gmail.com",
                "key": "XXXXX-YYDLA-XXXXX-YDD4A",
                "product": "Some Product",
                "product_code": "1",
                "purchase_date": "2022-12-04T13:40:15.000Z",
                "stripe_productID": "prod_123",
                "active": false,
                "createdAt": "2022-12-04T13:40:15.000Z",
                "updatedAt": "2022-12-04T13:40:15.000Z",
                "user_id": 1,
                "subscriptions": [
                    {
                        "id": 16,
                        "stripe_subscriptionID": "fake_stripe_subscriptionID",
                        "stripe_productID": "prod_123",
                        "current_period_end": "2022-07-16T12:00:00.000Z",
                        "current_period_start": "2022-12-16T12:00:00.000Z",
                        "current_period_end_timestamp": 1670097600,
                        "current_period_start_timestamp": 1671220800,
                        "retry_count": 0,
                        "createdAt": "2022-12-05T00:36:56.000Z",
                        "updatedAt": "2022-12-05T00:36:56.000Z",
                        "user_id": 1,
                        "license_id": 1
                    }
                ]
            },
            {
                "id": 2,
                "name": "xxx@gmail.com",
                "key": "123456$",
                "product": "Autobot Assembler",
                "product_code": "2",
                "purchase_date": "2022-12-01T16:26:53.000Z",
                "stripe_productID": "garbage_product_id",
                "active": true,
                "createdAt": "2022-12-05T00:26:53.000Z",
                "updatedAt": "2022-12-05T00:26:53.000Z",
                "user_id": 1,
                "subscriptions": [
                    {
                        "id": 17,
                        "stripe_subscriptionID": "garbage_day",
                        "stripe_productID": "garbage_product_id",
                        "current_period_end": "2022-11-01T12:00:00.000Z",
                        "current_period_start": "2022-12-30T12:00:00.000Z",
                        "current_period_end_timestamp": 1667329200,
                        "current_period_start_timestamp": 1672430400,
                        "retry_count": 0,
                        "createdAt": "2022-12-05T00:42:57.000Z",
                        "updatedAt": "2022-12-05T00:42:57.000Z",
                        "user_id": 1,
                        "license_id": 2
                    }
                ]
            }
        ]
    },
    getters: {
        
    },
    mutations: {
        setSidebarHidden(state, value){
            console.log(`setSideBarhidden=${value}`);
            state.sidebarHidden = value;
        },
        SET_ROUTE(state, route) {
            console.log(`setting route to:${route}`);
            state.route = route;
        },
        setLoggedIn(state, value){
            console.log(`setLoggedIn=${value}`);
            state.loggedIn = value;
        },
        setLoggedInEmail(state, value){
            console.log(`setLoggedInEmail=${value}`);
            state.loggedInEmail = value;
        },
        setAccountID(state, value){
            console.log(`setAccountID=${value}`);
            state.accountID = value;
        },
        setLoggedInFirstName(state, value){
            console.log(`setLoggedInFirstName=${value}`);
            state.loggedInFirstName = value;
        },
        setLicenses(state, value){
            console.log(`setLicenses={value below}`);
            state.licenses = [];
            state.licenses.push(value);
            Vue.set(state,'licenses',value);
        }

    },
    actions: {
        getSession: async function(context) {
            return new Promise((resolve,reject) => {
                try{
                    (async() =>{
                        console.log("Getting session info if available...");
                        const url = `https://${document.location.hostname}/api/login/info`;

                        // const cookie = getCookie('sid');
                        // console.log('cookie below');
                        // console.log(cookie);

                        const options = {
                            method: "POST",
                            headers: {
                                'Content-Type': 'application/x-www-form-urlencoded',
                            },
                            credentials: 'include'
                        };
                        try{
                            var response = await fetch(url,options);
                            
                            const json_response = await response.json();
                            console.log("Showing json response below");
                            console.log(json_response);

                            if(response.ok){
                                console.log("Got login session info successfully!");
                                context.commit('setLoggedIn', true);
                                context.commit('setLoggedInEmail',json_response.email);
                                context.commit('setAccountID',json_response.account_id);
                                context.commit('setLoggedInFirstName',json_response.first_name);
                                context.commit('setLicenses',json_response.licenses);
                                resolve("Session Found");
                            }else{
                                console.log("Error getting session details.  Not logged in?");
                                context.commit('setLoggedIn', false);
                                reject('No Session Detected');
                            }
                        }catch(error){
                            // this.conf_err = true;
                            // this.conf_err_msg = "Too many attempts.  Please try again later.";
                            console.error(error);
                            reject(error);
                        }
                    })()
                }catch(error){
                    reject(error);
                }
            });
        }
    },
    modules: {}
})

我的 Jmeter 板页面在我使用它的模板部分中有类似这样的内容。

<a :href="buyurl" target="_blank" :class="{hidden:new_buyer==false}">
                        <div id="new_buyer">
                            <font-awesome-icon icon="fa-solid fa-dollar-sign" />
                            <div class="alerts" :class="{hidden:alerts_buy==''}">{{ alerts_buy }}</div>
                            <div class="item_desc"><div v-html="buy_inner_html"></div></div>
                        </div>
                    </a>

该文件的javascript部分如下所示,其中buy_inner_html*computed属性 * 将使用 vuex 描述其显示方式:

<script>
    import { mapState } from 'vuex'
    import moment from 'moment';

    export default {
        methods: {
            handleUpdates: function(){
                //@JA - Read session state to determine if buy disabled is true.
                //@JA - It's determined to be true IF a license is found for the user.
                console.log("Printing Licenses from dashboard.vue...");
                console.log(this.licenses);
                var filteredLicenses = this.licenses.filter(function (el){
                    return el.product_code == '1'
                });
                try {
                    var filteredLicense = filteredLicenses[0];
                    this.license_info = filteredLicense;
                    console.log('Filtered License Below:');
                    console.log(filteredLicense);
                    if(filteredLicense.active == true){
                        let license_expiration_date = moment.unix(this.license_info.subscriptions[0].current_period_end_timestamp);
                        let current_date = moment();
                        this.new_buyer = false;
                        this.billing_disabled = false;
                        if(current_date.isAfter(license_expiration_date)){
                            this.license_state = 'expired';
                        }else{
                            this.license_state = 'active';
                        }
                        
                    }else{
                        this.new_buyer = false;
                        this.billing_disabled = false;
                        this.license_state = 'deactivated';
                    }
                } catch (error) {
                    this.new_buyer = true;
                    this.billing_disabled = true;
                    console.error(error);
                }
            }
        },
        computed: {
            ...mapState(['loggedInEmail','accountID','licenses']),
            billingurl: function(){
                return process.env.VUE_APP_BILLING_URL+'?prefilled_email='+this.loggedInEmail
            },
            buyurl: function(){
                return process.env.VUE_APP_BUY_URL+'?prefilled_email='+this.loggedInEmail+'&client_reference_id='+this.accountID
            },
            buy_inner_html() {
                if(this.new_buyer==false){
                    if(this.license_state=="active"){
                        return `
                            <div>Thank you</div>
                            <div style="font-size:10px;padding-top:4px;">Expires: ${moment.unix(this.license_info.subscriptions[0].current_period_end_timestamp).format("MMMM Do, YYYY")}</div>`;
                    }
                    if(this.license_state=="expired"){
                        return `
                            <div>Expired</div>
                            <div style="font-size:10px;padding-top:4px;">${moment.unix(this.license_info.subscriptions[0].current_period_end_timestamp).format("MMMM Do, YYYY")}</div>`;
                    }
                    if(this.license_state=="deactivated"){
                        return `
                            <div>Inactive</div>
                            <div style="font-size:10px;padding-top:4px;">Please Renew Your Subscription</div>`
                    }
                    return `<div style="color:#F00">Error</div>`;
                }else{
                    return `<div>Buy Now!</div>`;
                }
            },
        },
        data: () => ({
            alerts_license_keys:'',
            alerts_security:'',
            alerts_account:'',
            alerts_products:'',
            alerts_videos:'',
            alerts_discord:'',
            alerts_youtube:'',
            alerts_billing:'',
            alerts_buy:'',
            billing_disabled:false,
            new_buyer:false,
            license_state:'expired',
            license_info:{subscriptions:[{"current_end_period_timestamp":"123456789"}]}
        }),
        mounted(){
            this.handleUpdates();
        }
    }
</script>
<style scoped>

许可证状态变量在会话抓取期间通过 AJAX 调用进行更新,并更改程序的其余部分可以使用的vuex状态变量licenses
问题是,当我更新许可证时,我似乎无法让页面对我的buy_inner_html自定义计算属性函数中使用vuex变量的位置做出React。
特别是if(this.license_state==“活动”)
如果我尝试在vuex开发工具中更改此变量的值,它不会像其他变量那样立即做出React/更改?

我读到vue不能处理数组或对象的React。所以考虑到这一点,我尝试使用vue.set,我读到它应该解决这个问题,但它仍然没有工作。

当我在vue开发工具中更改vue存储许可证时(或者当我通过任意 AJAX 调用或在其他时间更改它时),我可以做些什么来让vue对我的vuex存储许可证做出React

(Note,我知道我的代码工作,因为如果我在vuex中手动更改许可证活动状态,然后刷新页面,我可以让我的页面正确显示在活动状态。只有当它在刷新后从 AJAX 调用更改或我尝试在vue dev工具中更改时,它才不工作)
编辑:显然vue.set在vue 3中不再工作了,我没有意识到它不工作,但是当用vue开发工具测试时,问题仍然存在。

xiozqbni

xiozqbni1#

计算的buy_inner_html仅取决于(可能)在组件mount事件中更改的组件数据。
在此mount事件之后,您可能会遇到状态发生更改的情况。
watch用于状态更改并调用handleUpdates方法,或者使计算直接依赖于状态(通过将组件数据移动到状态,即

jobtbby3

jobtbby32#

Vue 3不再支持vue.set,也不需要它。
我的setLicenses变元只需要是这个。

setLicenses(state, value){         
  state.licenses = value;
}

真实的的技巧是,我需要一种方法来更新UI时,这个值改变。
在我的模板文件中,关键是添加

watch: {
     deep: true,
     licenses: {
        handler(newValue, oldValue) {
           console.log("License vuex change detected");
           this.handleUpdates(newValue,oldValue);
        },
     }
},

这使得它可以在对变量的React性更改上拾取。这并不完美,因为vuex dev工具中的更改仍然不起作用,但至少在调用setLicenses mutator时它起作用了!
不要忘记添加

<script>
    import { mapState } from 'vuex'

computed: {                   
    ...mapState(['loggedInEmail','accountID','licenses']),
}

相关问题