如何将Vue中v-model的值绑定为Vuex的getter返回值?
现有代码核心问题排查
- computed属性重复声明
blogById:你先用mapGetters引入了Vuex的blogByIdgetter,又手动写了一个同名的computed属性,会把mapGetters的结果覆盖,导致取值逻辑异常。 - 直接将v-model绑定到getter返回的对象属性:Vuex的state默认不允许直接修改,v-model双向绑定会尝试直接修改
blogById.htmlCode,属于直接修改Vuex state,会触发报错。 - data初始化时取
this.blogPost.htmlCode:代码中没有定义blogPost属性,初始化阶段直接取值会报错。
实现方案(两种可选)
方案1:v-model绑定本地data变量(更推荐,适合实时预览场景)
修改逻辑:本地维护代码变量,切换资源条目时从Vuex取最新值同步到本地,代码修改后再同步回Vuex。
第一步:给Vuex添加修改state的mutation
Vuex要求必须通过mutation修改state,在你的store代码中添加如下配置:
import { createStore } from 'vuex'; export default createStore({ state: { // 原有state代码不变 }, getters: { // 原有getters代码不变 }, // 新增mutation mutations: { updateBlogCode(state, payload) { const targetBlog = state.cards.find(c => Number(c.index) === Number(payload.id)) if (targetBlog) { targetBlog[payload.codeType] = payload.value } } } });
第二步:修改组件代码
import { mapGetters, mapMutations } from "vuex"; export default { name: "CodeEditor", data() { return { htmlCode: "", cssCode: "", jsCode: "", styleBegin: "<style>", styleEnd: "</style>", scriptBegin: "<script>", scriptEnd: "</" + "script>", }; }, methods: { ...mapMutations(['updateBlogCode']), writeCode() { var doc = document.getElementById("myframe").contentWindow.document; doc.open(); doc.write( this.htmlCode + this.styleBegin + this.cssCode + this.styleEnd + this.scriptBegin + this.jsCode + this.scriptEnd ); doc.close(); }, // 代码修改时同步到Vuex并更新预览 handleCodeChange(codeType) { this.updateBlogCode({ id: this.id, codeType: codeType, value: this[codeType] }) this.writeCode() } }, mounted() { this.writeCode(); }, props: { id: { required: true, }, }, computed: { ...mapGetters({ getBlogById: "blogById", }), currentBlog() { return this.getBlogById(this.id); }, }, watch: { // 监听资源id变化,切换条目时自动同步最新代码到本地 id: { immediate: true, handler() { if (!this.currentBlog) return this.htmlCode = this.currentBlog.htmlCode this.cssCode = this.currentBlog.cssCode this.jsCode = this.currentBlog.jsCode this.writeCode() } } } };
第三步:修改textarea绑定逻辑
<!-- HTML代码编辑框 --> <textarea v-model="htmlCode" @input="handleCodeChange('htmlCode')" cols="30" rows="10" spellcheck="false" ></textarea> <!-- CSS代码编辑框 --> <textarea v-model="cssCode" @input="handleCodeChange('cssCode')" cols="30" rows="10" spellcheck="false" ></textarea> <!-- JS代码编辑框 --> <textarea v-model="jsCode" @input="handleCodeChange('jsCode')" cols="30" rows="10" spellcheck="false" ></textarea>
方案2:v-model直接绑定computed属性
不需要本地维护data变量,通过computed的get/set语法直接对接Vuex的getter和mutation。
第一步:先添加方案1中提到的Vuex mutation
第二步:修改组件computed配置
computed: { ...mapGetters({ getBlogById: "blogById", }), currentBlog() { return this.getBlogById(this.id); }, htmlCode: { get() { return this.currentBlog?.htmlCode || '' }, set(val) { this.updateBlogCode({id: this.id, codeType: 'htmlCode', value: val}) this.writeCode() } }, cssCode: { get() { return this.currentBlog?.cssCode || '' }, set(val) { this.updateBlogCode({id: this.id, codeType: 'cssCode', value: val}) this.writeCode() } }, jsCode: { get() { return this.currentBlog?.jsCode || '' }, set(val) { this.updateBlogCode({id: this.id, codeType: 'jsCode', value: val}) this.writeCode() } } },
第三步:textarea直接绑定computed属性即可
<textarea v-model="htmlCode" cols="30" rows="10" spellcheck="false" ></textarea> <!-- CSS、JS编辑框同理绑定对应computed属性即可 -->
内容的提问来源于stack exchange,提问作者EmielV
相关产品推荐
相关产品推荐

