我有以下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开发工具测试时,问题仍然存在。
2条答案
按热度按时间xiozqbni1#
计算的
buy_inner_html
仅取决于(可能)在组件mount
事件中更改的组件数据。在此
mount
事件之后,您可能会遇到状态发生更改的情况。watch
用于状态更改并调用handleUpdates
方法,或者使计算直接依赖于状态(通过将组件数据移动到状态,即jobtbby32#
Vue 3不再支持vue.set,也不需要它。
我的setLicenses变元只需要是这个。
真实的的技巧是,我需要一种方法来更新UI时,这个值改变。
在我的模板文件中,关键是添加
这使得它可以在对变量的React性更改上拾取。这并不完美,因为vuex dev工具中的更改仍然不起作用,但至少在调用setLicenses mutator时它起作用了!
不要忘记添加
和