vue3项目使用指令方式修改img标签的src地址

大家好,我是1024小神,技术群 / 私活群 / 股票群 或 交朋友 都可以私信我。 如果你觉得本文有用,一键三连 (点赞、评论、关注),就是对我最大的支持~

因为项目要添加一个新的功能,就是在pad上的网页需要打开摄像头扫码的能力,而且是在局域网访问的,所以就需要后端地址启动在https的地址上,这个时候所有的静态资源都变成了https链接,这个时候一个unity同事在游戏中访问图片地址的时候就访问不了,有解决方案,但是要修改的地方有点多,但是扫码又必须使用https的链接,所以备选方案就是后端启动两个服务,一个http转为给游戏提供http的图片链接,https转为pad提供扫码能力。

但是这个时候问题就来了:pad + server + game 三者之间的通讯是使用proto协议传输的,其中就包含图片地址,这个图片地址是只有http链接字段的,不想再添加一个https的字段,会很麻烦,添加的话大家所有人都要修改代码,这个就只有我这个前端自己来解决了,那就是将所有图片链接中http替换为https,并将端口9091替换为9090,那全局那么多img标签呢,怎么做?

方案1:全局组件替换

创建一个全局的图片组建,然后将项目中的所有img标签改成这个全局组件,不推荐:因为要创建函数和全局组件,还要修改项目中所有的img标签,麻烦

javascript 复制代码
<!-- components/SecureImg.vue -->
<template>
  <img :src="secureSrc" v-bind="$attrs">
</template>

<script setup>
import { computed } from 'vue'

const props = defineProps({
  src: String
})

const secureSrc = computed(() => {
  if (!props.src) return ''
  return props.src.replace(/^http:\/\//i, 'https://')
})
</script>

然后在项目中全局注册:

javascript 复制代码
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import SecureImg from './components/SecureImg.vue'

const app = createApp(App)
app.component('Img', SecureImg)
app.mount('#app')

方案2:使用Vue指令

创建一个指令,然后将所有img标签的src属性改为使用指令的方式。这个时候要改的就简单了,就是全局搜索<img src= 然后替换为 <img v-secure-src=即可实现。

javascript 复制代码
// directives/secureSrc.js
export const secureSrc = {
  beforeMount(el, binding) {
    if (binding.value && typeof binding.value === 'string') {
      el.src = binding.value.replace(/^http:\/\//i, 'https://')
    }
  },
  updated(el, binding) {
    if (binding.value && typeof binding.value === 'string') {
      el.src = binding.value.replace(/^http:\/\//i, 'https://')
    }
  }
}

// main.js
import { createApp } from 'vue'
import App from './App.vue'
import { secureSrc } from './directives/secureSrc'

const app = createApp(App)
app.directive('secure-src', secureSrc)
app.mount('#app')

如果img的src跟的是变量,直接使用指令跟上变量就可以了:

javascript 复制代码
<template>
  <div>
    <!-- 静态字符串 -->
    <img v-secure-src="'http://example.com/image1.jpg'" alt="image1">
    
    <!-- 动态变量 -->
    <img v-secure-src="imageUrl" alt="dynamic image">
    
    <!-- 响应式数据 -->
    <img v-secure-src="user.avatar" alt="user avatar">
  </div>
</template>

<script setup>
import { ref, reactive } from 'vue'

// 响应式数据
const imageUrl = ref('http://example.com/image2.jpg')
const user = reactive({
  avatar: 'http://example.com/avatar.jpg'
})

// 可以动态更新
setTimeout(() => {
  imageUrl.value = 'http://another-domain.com/new-image.jpg'
}, 3000)
</script>

方案3:使用指令参数

可以通过参数的形式,将url地址传递到指令里面,然后在指令里面修改:

javascript 复制代码
// directives/secureSrc.js
export const secureSrc = {
  beforeMount(el, binding) {
    if (binding.arg === 'url') {
      updateSrc(el, binding.value)
    }
  },
  updated(el, binding) {
    if (binding.arg === 'url') {
      updateSrc(el, binding.value)
    }
  }
}

function updateSrc(el, src) {
  if (src && typeof src === 'string') {
    el.src = src.replace(/^http:\/\//i, 'https://')
  } else {
    el.src = src || ''
  }
}

使用方式:

javascript 复制代码
<template>
  <div>
    <!-- 使用指令参数 -->
    <img v-secure-src:url="dynamicImageUrl" alt="dynamic image">
    <img v-secure-src:url="staticImageUrl" alt="static image">
  </div>
</template>

<script setup>
import { ref } from 'vue'

const dynamicImageUrl = ref('http://example.com/dynamic.jpg')
const staticImageUrl = 'http://example.com/static.jpg'
</script>

方法4:支持修饰符的指令

javascript 复制代码
// directives/secureSrc.js
export const secureSrc = {
  beforeMount(el, binding) {
    processSrc(el, binding)
  },
  updated(el, binding) {
    processSrc(el, binding)
  }
}

function processSrc(el, binding) {
  const src = binding.value
  let processedSrc = src
  
  if (src && typeof src === 'string') {
    // 强制HTTPS修饰符
    if (binding.modifiers.https) {
      processedSrc = src.replace(/^http:\/\//i, 'https://')
    }
    
    // 添加时间戳修饰符(避免缓存)
    if (binding.modifiers.nocache) {
      const separator = processedSrc.includes('?') ? '&' : '?'
      processedSrc += `${separator}_t=${Date.now()}`
    }
  }
  
  el.src = processedSrc || ''
}

使用方式:

javascript 复制代码
<template>
  <div>
    <!-- 只启用HTTPS转换 -->
    <img v-secure-src.https="imageUrl" alt="https only">
    
    <!-- 同时启用HTTPS和去缓存 -->
    <img v-secure-src.https.nocache="dynamicImage" alt="https and nocache">
  </div>
</template>

<script setup>
import { ref } from 'vue'

const imageUrl = ref('http://example.com/image.jpg')
const dynamicImage = ref('http://example.com/dynamic.jpg')
</script>

推荐方案

使用方法3(指令参数) 最为清晰,因为:

语义明确:v-secure-src:url 清楚地表示这是处理URL的

避免冲突:不会影响其他属性的处理

易于扩展:可以添加其他参数处理不同场景

这样无论src是静态字符串还是动态变量,都能正确工作,并且在数据更新时自动响应变化。
大家好,我是1024小神,技术群 / 私活群 / 股票群 或 交朋友 都可以私信我。 如果你觉得本文有用,一键三连 (点赞、评论、关注),就是对我最大的支持~

相关推荐
练习前端两年半3 小时前
🚀 Vue3按钮组件Loading状态最佳实践:优雅的通用解决方案
前端·vue.js·element
sujiu3 小时前
CommonJS 原理与实现:手写一个极简的模块系统
前端
用户51681661458413 小时前
使用全能电子地图下载器MapTileDownloader 制作瓦片图层详细过程
前端·后端
拉不动的猪3 小时前
从底层逻辑和实用性来分析ref中的值为什么不能直接引用
前端·javascript·面试
1024小神3 小时前
tauri项目编译的时候,最后一步的时候内存溢出了?
前端
ONE_Gua3 小时前
Wireshark常用过滤规则
前端·后端·数据挖掘
通往曙光的路上4 小时前
vue啊哈哈哈哈哈哈哈哈
前端·javascript·vue.js
fouryears_234174 小时前
如何将Vue 项目转换为 Android App(使用Capacitor)
android·前端·vue.js
葡萄城技术团队4 小时前
在线Excel新突破:SpreadJS如何完美驾驭中国式复杂报表
前端