Vue复选框:checked绑定函数返回值后状态不更新问题
Hey, let's break down why your checkbox isn't updating when you toggle it, and how to fix it!
The Root Cause
Your current setup uses a one-way :checked binding to the isChecked() function. It works on initial render because Vue runs isChecked() to set the state. But when you click the checkbox, the browser natively flips the DOM's checked state—and Vue won't overwrite that manual change. Even if your $route.query updates later, Vue won't re-run isChecked() to sync the checkbox, since it prioritizes user-initiated DOM changes over one-way bindings.
Solution 1: Use a Computed Property with v-model (Recommended)
This approach creates a two-way binding between your route query and the checkbox, keeping them in sync automatically. We'll use a computed property to handle getting the state from the route and setting it when the checkbox is toggled.
Update the Template
Replace the :checked and @change with v-model:
<label> <input type="checkbox" name="facet.name" :value="term.term" v-model="facetChecked" > {{ term.term }} <span class="facet-count">({{ term.count }})</span> </label>
Add the Computed Property
Assuming this is inside a loop over facets/terms, add this computed property to your component:
computed: { facetChecked: { get() { // Check if the facet exists in the route query return this.$route.query.hasOwnProperty(this.facet.name); }, set(isChecked) { // Trigger the filter update when the checkbox is toggled this.updateFilter(isChecked, this.facet.name); } } }
Update the Filter Logic
Replace your filerChange method with one that updates the route query properly:
updateFilter(isChecked, facetName) { // Make a copy of the current query to avoid mutating it directly const updatedQuery = { ...this.$route.query }; if (isChecked) { // Add the facet to the query updatedQuery[facetName] = true; } else { // Remove the facet from the query delete updatedQuery[facetName]; } // Update the route without reloading the page this.$router.push({ query: updatedQuery }); }
Solution 2: Block Native Behavior & Manually Sync
If you prefer to keep the :checked binding, you can prevent the browser from natively toggling the checkbox, then update the route and let Vue re-calculate the state.
Update the Template
Keep your existing template, we'll modify the handler:
<label> <input type="checkbox" name="facet.name" :value="term.term" :checked="isChecked(facet.name)" @change="filterChange($event, facet.name)" > {{ term.term }} <span class="facet-count">({{ term.count }})</span> </label>
Modify the Filter Change Handler
Add event.preventDefault() to block the native checkbox toggle, then update the route:
filterChange(event, facetName) { // Stop the browser from flipping the checkbox state event.preventDefault(); // Calculate the new desired state const newCheckedState = !this.isChecked(facetName); const updatedQuery = { ...this.$route.query }; if (newCheckedState) { updatedQuery[facetName] = true; } else { delete updatedQuery[facetName]; } this.$router.push({ query: updatedQuery }); }
Now when you click the checkbox, the browser won't change the DOM state—instead, we update the route, and Vue will re-run isChecked(facet.name) to set the correct checkbox state.
内容的提问来源于stack exchange,提问作者HMR

