vue3+vite2动态绑定图片优雅解决方案

这篇具有很好参考价值的文章主要介绍了vue3+vite2动态绑定图片优雅解决方案。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

优雅解决方案在最下面,小伙伴们儿可以直接前往 😊

背景

在vue3+vite2项目中,我们有时候想要动态绑定资源,比如像下面的代码这样:

<template>
    <div>
	    <!-- 动态绑定图片资源 -->
        <img :src="img_src">
    </div>
</template>

<script setup>
import { ref } from 'vue';
// 静态图片资源
const img_src = ref('./1.jpg');
</script>

实际效果是这样:

vue3+vite2动态绑定图片优雅解决方案

原因分析

我们注意到,控制台的报错信息GET http://127.0.0.1:5173/1.jpg 404 (Not Found)

  • GET:表示向服务器请求资源的方式。
  • http://127.0.0.1:5173:表示主机为项目开启的服务器地址以及端口号
  • http://127.0.0.1:5173/1.jpg:表示存放在服务器中的图片资源地址。
  • 404 (Not Found):状态码,404表示找不到资源。

问题就出在http://127.0.0.1:5173/1.jpg 这里,项目文件的路径是src/App.vue ,图片的路径是src/1.jpg ,因此,图片在服务器上的存放路径实际应该是http://127.0.0.1:5173/src/1.jpg ,我们直接在浏览器中访问这个地址。

vue3+vite2动态绑定图片优雅解决方案

可以看到,成功获取了图片资源。

由于vite打包的机制,造成了路径错误的问题(类似于vue2 + vue-cli项目的动态绑定图片问题)。

解决

目前网上的解决方案有很多,这里列出其中一种受众的,以及笔者在此基础上进一步加强的解决方案。

普遍的解决方案

话不多说,直接列出代码:

<template>
    <div>
	    <!-- 动态绑定图片资源 -->
        <img :src="img_src">
    </div>
</template>

<script setup>
import { ref } from 'vue';
// 静态图片资源
const img_src = ref('./1.jpg');

// 主要代码,利用 new URL().href 进行相对路径的拼接
function getAssetImage(imgSrc) {
  return new URL(imgSrc, import.meta.url).href;
}

// 当然你也可以这样简写,这里用到es6箭头函数
// const getAssetImage = imgSrc => new URL(imgSrc, import.meta.url).href;
</script>

这段代码的重点是new URL().href 和 es6的 import.meta.url

  • new URL(url, baseUrl).href:路径拼接。比如url是./1.jpg,baseUrl是http://127.0.0.1:5173/src/App.vue ,那么拼接出来就是http://127.0.0.1:5173/src/1.jpg
  • import.meta.url:获取当前模块的路径,比如在src/App.vue中,就是http://127.0.0.1:5173/src/App.vue

所以最后的new URL().href 就是真正的图片资源地址,自己打印一下new URL(url, baseUrl)import.meta.url 就容易明白了。

这里给大伙儿画张图,便于理解。

vue3+vite2动态绑定图片优雅解决方案

优雅的解决方案

上面的方案可行,但不够优雅。试想,如果有很多文件都需要动态绑定静态图片资源,那岂不是每个.vue文件都要封装一次getAssetImage() 函数?所以下面介绍一种优雅的封装方案。

封装的主要问题是如何自动获取.vue文件的import.meta.url ,就可以不必每次调用都携带import.meta.url

核心思路是通过抛出错误获取函数调用栈,从而获得函数调用者文件(或者说模块)的路径,再通过正则表达式提取出路径信息,把import.meta.url替换掉,就能实现,只传图片相对路径这一个参数,得到图片的完整路径的效果

直接上代码:

  • JavaScript版本
// src/utils/common.js

export default {
    getAssetImage(imgSrc, baseUrl) {
        // console.log('baseUrl', baseUrl);
        // console.log('new URL(imgSrc, baseUrl).href', new URL(imgSrc, baseUrl).href);
        // console.log('import.meta.url', import.meta.url);
        // console.log('new URL(imgSrc, import.meta.url).href', new URL(imgSrc, import.meta.url).href);

        // 正则匹配函数调用者文件的路径
        const regExp1 = /at Proxy.getAssetImage \((.+)\)/g;
        // 正则命中目标
        let target;
        try {
            // 抛出错误,获取函数调用栈信息
            throw new Error();
        } catch (err) {
            // 匹配函数调用者文件的路径
            target = regExp1.exec(err?.stack);
            // console.log('err.stack', err?.stack);
            // console.log(target?.[1]);
        }

        if (target?.[1]) {
            // 用户没有传入第二个参数,就使用自动获取的路径
            baseUrl = baseUrl || target?.[1];
        }

        if (!baseUrl) {
            // 用户没有传入第二个参数,且获取函数调用者文件的路径失败
            throw new Error('请传入第二个参数 import.meta.url');
        }
        // 返回处理后的资源路径
        return new URL(imgSrc, baseUrl).href;
    }
}
  • TypeScript版本
// src/utils/common.ts

export default {
    getAssetImage(imgSrc: string, baseUrl: string) {
        // console.log('baseUrl', baseUrl);
        // console.log('new URL(imgSrc, baseUrl).href', new URL(imgSrc, baseUrl).href);
        // console.log('import.meta.url', import.meta.url);
        // console.log('new URL(imgSrc, import.meta.url).href', new URL(imgSrc, import.meta.url).href);

        // 正则匹配函数调用者文件的路径
        const regExp1 = /at Proxy.getAssetImage \((.+)\)/g;
        // 正则命中目标
        let target: RegExpExecArray | null;
        try {
            // 抛出错误,获取函数调用栈信息
            throw new Error();
        } catch (err) {
            // 匹配函数调用者文件的路径
            target = regExp1.exec(err?.stack);
            // console.log('err.stack', err?.stack);
            // console.log(target?.[1]);
        }

        if (target?.[1]) {
            // 用户没有传入第二个参数,就使用自动获取的路径
            baseUrl = baseUrl || target?.[1];
        }

        if (!baseUrl) {
            // 用户没有传入第二个参数,且获取函数调用者文件的路径失败
            throw new Error('请传入第二个参数 import.meta.url');
        }
        // 返回处理后的资源路径
        return new URL(imgSrc, baseUrl).href;
    }
}
  • 在.vue文件中使用
// src/App.vue

<template>
    <div>
        <!-- 测试 -->
        <img :src="getAssetImage(img_src)">
        <!-- 可以试试在嵌套组件中使用^_^ -->
    </div>
</template>

<script lang="ts" setup>
import { ref } from 'vue';
import common from '@/utils/common.ts';

const img_src = ref('./1.jpg');

// const getAssetImage = img_src => common.getAssetImage(img_src, import.meta.url);
// 可以省略第二个参数import.meta.url,函数内部会自动获取函数的调用路径。
const getAssetImage = img_src => common.getAssetImage(img_src);

// 常规写法
// function getAssetImage(img_src) {
//   return common.getAssetImage(img_src);
// }
</script>

the End……文章来源地址https://www.toymoban.com/news/detail-666872.html

到了这里,关于vue3+vite2动态绑定图片优雅解决方案的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • VITE+VUE3动态导入组件

    通常的动态组件导入方式   vue中又是时候我们会使用到动态组件导入,比如路由组件的动态导入,一般类似路由组件的动态导入的方式: ()=import(path); ()=defineAsyncComponent(()=import(path)) vite中使用的错误 但是这写方式进行动态导入组件的时候在vite+vue3项目下都是不行的,开发

    2024年02月14日
    浏览(43)
  • Vue3动态路由(Vite+Vue3+TS+Mock)

    Vue通过路由进行页面管理,不同的路由绑定到不同的页面。一般来说,前端直接写好的路由为静态路由,在不修改代码的情况下,路由表是不会改变的。对于不需要动态改变路由表的网站,静态路由就已经足够了,但是当页面需要与权限进行绑定时,不同用户允许浏览的页面

    2024年02月02日
    浏览(123)
  • Soybean Admin - 基于 Vue3 / vite3 等最新前端技术栈构建的中后台模板,免费开源、清新优雅,主题丰富

    一款专业好看、完成度很高的 admin 开源项目,无论是用于生产还是学习,都非常值得尝试。 关于 Soybean Admin Soybean Admin 是一个基于 Vue3 / Vite3 / TypeScript / NaiveUI / Pinia 和 UnoCSS 的中后台模版,它使用了最新流行的前端技术栈,内置丰富的主题配置,有着极高的代码规范,基于文

    2024年02月11日
    浏览(59)
  • 【vue3】数据绑定,动态渲染class与style

    数据绑定的一个常见需求场景是操纵元素的 CSS class 列表和内联样式(style)。因为 class 和 style 都是 attribute,我们可以和其他 attribute 一样使用 v-bind 将它们和动态的字符串绑定。但是,在处理比较 复杂的绑定 时,通过拼接生成字符串是麻烦且易出错的。因此,Vue 专门为

    2024年02月13日
    浏览(42)
  • 【Vue3】Vite打包发布错误若干问题解决方案,新手遇到的问题都在这里。

    npm run build 在vite.config.js 中加入下面的代码 vite.config.js 完整代码

    2024年02月11日
    浏览(50)
  • VUE3+vite项目中动态引入组件和异步组件

    1. 把项目中所有vue文件注册成异步组件。 2. 获取组件 在setup函数获取组件 3. 参考如下 Glob 导入 Vite 支持使用特殊的 import.meta.glob 函数从文件系统导入多个模块: 以上将会被转译为下面的样子: 你可以遍历 modules 对象的 key 值来访问相应的模块: 匹配到的文件默认是懒加载的

    2024年02月10日
    浏览(105)
  • 使用模板创建【vite+vue3+ts】项目出现 “找不到模块‘vue‘或其相应的类型声明” 的解决方案

    项目前台需要使用Vue3+Ts来写一个H5应用,然后我用模板创建 创建完后进入 HelloWorld.vue ,两眼一黑 然后在 tsconfig.json 的 \\\"compilerOptions\\\" 中添加 修改 \\\"moduleResolution\\\" 值为 \\\"node\\\"

    2024年02月17日
    浏览(65)
  • vue3和vite项目在scss中因为本地图片,不用加~

    看了很多文章说要加~,真的好坑哦,我的加了~反而出不来了: 304 Not Modified 所以需要去掉~: 直接引入就好:

    2024年01月25日
    浏览(59)
  • vue3项目vite.config.js配置“代理”、“端口”、“打包名”、“图片压缩”

    前言 我们在搭建vue3项目的时候不可避免的会遇到“代理”、“端口”、“打包名”、“图片压缩”等配置问题,本文逐一讲述该怎么样在vite.config.js中去配置。 一、配置代理端口和代理转发 vite.config.ts添加如下代码 ts.config.json添加如下代码 图片压缩先要引入vite-plugin-imagem

    2024年02月07日
    浏览(82)
  • Vue3中动态绑定:disabled element-plus使用方法

    @change=\\\"whetherFlag($event)\\\"  根据value值判断是否禁用 :disabled=\\\"isShow\\\" 初始值为禁用状态 const isShow = refboolean(true);  根据value的值判断是否禁用  

    2024年01月25日
    浏览(60)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包