Vue.js图片src无响应:按时段切换图片需手动刷新
问题分析与解决方案
你的图片无法响应式切换的核心原因是没有定时更新schedule状态,Vue的响应式系统依赖数据变化触发视图更新,而当前代码只有在页面加载或手动刷新时才会计算一次时段,后续时间变化时schedule不会自动更新。另外还有几个代码实践上的问题需要修正:
核心问题点
schedule状态仅在getSchedule方法被调用时更新,但模板中调用getSchedule(currentHour())只会在组件初始化和重渲染时执行,不会定时触发,导致时段变化后状态未更新。- 计算属性
getSrc中直接修改data里的src,违反了计算属性的纯函数原则(计算属性不应产生副作用)。 - public文件夹的路径不需要包含
./public,Vue会将public目录作为静态资源根目录,直接使用/文件名即可访问。
修复步骤
1. 定时更新时段状态
在mounted钩子中添加定时器,定时(比如每分钟)检查当前小时并更新schedule,确保状态随时间变化自动更新:
mounted() { // 初始化加载XML和时段 this.loadScheduleConfig(); // 每分钟更新一次时段 this.interval = setInterval(() => { this.updateSchedule(); }, 60000); }, beforeUnmount() { // 组件销毁时清除定时器,避免内存泄漏 clearInterval(this.interval); }, methods: { // 提取加载XML的逻辑为单独方法 loadScheduleConfig() { axios.get("/screen-schedule-config.xml") .then(response => { let xmlobj = response.data; let domParser = new DOMParser(); let xmlDocument = domParser.parseFromString(xmlobj, "text/xml"); let imagePath = xmlDocument.getElementsByTagName("assets"); this.morningSrc = imagePath[0].querySelector("asset").getAttribute("path"); this.afternoonSrc = imagePath[0].querySelectorAll("asset")[1].getAttribute("path"); this.eveningSrc = imagePath[0].querySelectorAll("asset")[2].getAttribute("path"); }) }, currentHour() { return new Date().getHours(); }, // 更新时段状态的方法 updateSchedule() { const hour = this.currentHour(); if (hour >= 0 && hour < 12) { this.schedule = "s1"; } else if (hour >= 12 && hour < 19) { this.schedule = "s2"; } else { this.schedule = "s3"; } } }
2. 修改模板依赖响应式状态
模板中直接使用schedule状态判断,不再调用方法,确保响应式触发:
<template> <div class="mainDisplay"> <div class="imgContainer" v-if="schedule === 's1'"> <img class="banner" :src="getSrc" alt="Morning Cappucino"> </div> <div class="imgContainer" v-else-if="schedule === 's2'"> <img class="banner" :src="getSrc" alt="Afternoon Latte"> </div> <div class="imgContainer" v-else-if="schedule === 's3'"> <img class="banner" :src="getSrc" alt="Evening Hot Chocolate"> </div> </div> </template>
3. 修正计算属性为纯函数
计算属性getSrc直接返回对应时段的图片路径,不修改data中的src:
computed: { getSrc() { switch(this.schedule) { case 's1': return this.morningSrc; case 's2': return this.afternoonSrc; case 's3': return this.eveningSrc; default: return ''; } } }
4. 修正public资源路径
确保XML中配置的图片路径为根目录相对路径,比如/morning-banner.jpg,而不是./public/morning-banner.jpg,因为Vue会将public目录下的资源编译到根路径。
完整修正后的代码
<template> <div class="mainDisplay"> <div class="imgContainer" v-if="schedule === 's1'"> <img class="banner" :src="getSrc" alt="Morning Cappucino"> </div> <div class="imgContainer" v-else-if="schedule === 's2'"> <img class="banner" :src="getSrc" alt="Afternoon Latte"> </div> <div class="imgContainer" v-else-if="schedule === 's3'"> <img class="banner" :src="getSrc" alt="Evening Hot Chocolate"> </div> </div> </template> <script> import axios from 'axios'; export default { data() { return { morningCaption: " ", afternoonCaption: " ", eveningCaption: " ", morningSrc: "", afternoonSrc: "", eveningSrc: "", schedule: "", interval: null } }, mounted() { this.loadScheduleConfig(); this.updateSchedule(); this.interval = setInterval(() => { this.updateSchedule(); }, 60000); }, beforeUnmount() { clearInterval(this.interval); }, methods: { loadScheduleConfig() { axios.get("/screen-schedule-config.xml") .then(response => { let xmlobj = response.data; let domParser = new DOMParser(); let xmlDocument = domParser.parseFromString(xmlobj, "text/xml"); let imagePath = xmlDocument.getElementsByTagName("assets"); this.morningSrc = imagePath[0].querySelector("asset").getAttribute("path"); this.afternoonSrc = imagePath[0].querySelectorAll("asset")[1].getAttribute("path"); this.eveningSrc = imagePath[0].querySelectorAll("asset")[2].getAttribute("path"); }) }, currentHour() { return new Date().getHours(); }, updateSchedule() { const hour = this.currentHour(); if (hour >= 0 && hour < 12) { this.schedule = "s1"; } else if (hour >= 12 && hour < 19) { this.schedule = "s2"; } else { this.schedule = "s3"; } } }, computed: { getSrc() { switch(this.schedule) { case 's1': return this.morningSrc; case 's2': return this.afternoonSrc; case 's3': return this.eveningSrc; default: return ''; } } } } </script>
内容的提问来源于stack exchange,提问作者Daniel Rogerson
相关产品推荐
相关产品推荐

