Teleport传送组件bug记录
1:自定义传送位置 支持 class id等 选择器
报错runtime-core.esm-bundler.js:47 [Vue warn]: Failed to locate Teleport target with selector “#app1”. Note the target element must exist before the component is mounted - i.e. the target cannot be rendered by the component itself, and ideally should be outside of the entire Vue component tree.
报错解释: 组件允许将组件的子节点传送到DOM中的一个不同位置。报错信息表明,组件试图寻找一个具有".modal"类的目标元素(即一个具有选择器".modal"的DOM节点),但是没有找到
报错代码
- 定义的class和id和Teleport组件在同一个vue文件
<template> <div class="hello"> <div id="app1"></div> <div class="modal1"></div> <Teleport to="#app1"> <div class="modal2"> <p>appModal </p> </div> </Teleport> <Teleport to=".modal1"> <div class="modal1"> <p>modal </p> </div> </Teleport> </div> </template>
- 解决方法:
确保目标元素存在于DOM中,并且具有正确的类名".modal"。
确保组件在DOM树中的位置正确,确保它在目标元素之后被渲染。
如果使用了Vue的单文件组件,请确保的父组件已经被正确渲染。
如果目标元素是动态创建的,请确保在查找目标元素之前,该元素已经被创建。
注:确保".modal"元素在组件被渲染之前存在于DOM中。如果是动态内容,可能需要在正确的生命周期钩子或者响应式数据变化时创建或者显示该元素。<!-- 确保有一个具有.modal类的元素在某处 --> <div class="modal"> <!-- 这里的内容将会被Teleport传送进来 --> </div> <!-- Vue组件中使用Teleport --> <Teleport to=".modal"> <!-- 这里是你想要传送的内容 --> </Teleport>
package.json版本号前边的波浪线
package.json版本号前边的波浪线
在package.json文件中,版本号前的波浪线(~)、插入符(^)和正斜杠(/)都有特殊的语义。
-
~ 允许更新到当前最新的次要版本。比如,如果你的版本是1.2.3,那么~1.2.3允许更新到1.2.x的最新版本,但不允许到1.3.0。
-
^ 类似于~,但是允许更新到主要版本。比如,^1.2.3允许更新到1.x.x的任何版本,但不允许到2.0.0。
-
/ 用于指定一个版本范围。比如1.2.3 - 2.3.4表示版本范围从1.2.3到2.3.4。
这些符号通常用于package.json中的dependencies和devDependencies部分,以指示npm在安装、更新时应遵循的版本兼容性规则。例如,如果你想要安装一个库的特定版本,你可以直接写出版本号,如下所示:
"dependencies": { "example-lib": "1.2.3" }
如果你想要允许小更新,可以这样写:
"dependencies": { "example-lib": "^1.2.3" }
或者,如果你想要一个版本范围:
"dependencies": { "example-lib": "1.2.3 - 2.3.4" }
这些语法规则应用于所有的npm包管理操作,比如npm install、npm update和npm outdated
postcss-px-to-viewport实现移动端的兼容
postcss-px-to-viewport就是这样一款优秀的插件,它将 px 转换成视口单位 vw。众所周知,vw本质上还是一种百分比单位,100vw即等于100%,即 window.innerWidth。
- vw 视口的最大宽度,1vw等于视口宽度的百分之一
- vh 视口的最大高度,1vh等于视口高度的百分之一
-
安装 postcss-px-to-viewport 插件
pnpm i postcss-px-to-viewport
-
vite.config.ts设置
注:Vite 中已经内联了 postcss,所以并不需要额外的创建 postcss.config.js文件。import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import vueJsx from '@vitejs/plugin-vue-jsx' import pxtovw from "postcss-px-to-viewport" const loader_pxtovw = pxtovw({ unitToConvert: 'px', // 要转化的单位 viewportWidth: 750, // UI设计稿的宽度 unitPrecision: 6, // 转换后的精度,即小数点位数 propList: ['*'], // 指定转换的css属性的单位,*代表全部css属性的单位都进行转换 viewportUnit: 'vw', // 指定需要转换成的视窗单位,默认vw fontViewportUnit: 'vw', // 指定字体需要转换成的视窗单位,默认vw selectorBlackList: ['ignore-'], // 指定不转换为视窗单位的类名, minPixelValue: 1, // 默认值1,小于或等于1px则不进行转换 mediaQuery: true, // 是否在媒体查询的css代码中也进行转换,默认false replace: true, // 是否转换后直接更换属性值 // exclude: [/node_modules/], // 设置忽略文件,用正则做目录名匹配 // include: [/vant/], // 如果设置了include,那将只有匹配到的文件才会被转换 landscape: false // 是否处理横屏情况 }) export default defineConfig({ plugins: [vue(), vueJsx()], css: { postcss: { plugins: [loader_pxtovw] } }, resolve: { alias: [ { find: 'vue-i18n', replacement: 'vue-i18n/dist/vue-i18n.cjs.js', }, // @/xxxx => src/xxxx { find: /\@\//, replacement: pathResolve('src') + '/', }, ], } })
-
propList: 当有些属性的单位我们不希望转换的时候,可以添加在数组后面,并在前面加上!号,如 propList: [“*”,“!letter-spacing”],这表示:所有css属性的属性的单位都进行转化,除了letter-spacing
-
selectorBlackList:转换的黑名单,在黑名单里面的我们可以写入字符串,只要类名包含有这个字符串,就不会被匹配。比如selectorBlackList: [‘wrap’],它表示形如wrap,my-wrap,wrapper这样的类名的单位,都不会被转换
-
-
使用 vant UI 库修改配置
使用了 vant UI库,所以根据官方设定 viewportWidth: 375,修改 vue.config.js 配置如下:import { fileURLToPath, URL } from 'node:url' import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import vueJsx from '@vitejs/plugin-vue-jsx' // 适配移动端的插件 import pxtovw from "postcss-px-to-viewport" // 如果是其他的文件,我们就按照我们UI的宽度来设置viewportWidth,即750。 const loder_pxtovw = pxtovw({ viewportWidth: 750, viewportUnit: 'vw', exclude: [/node_modules\/vant/i] }) // 如果读取的是vant相关的文件,viewportWidth就设为375。但是经过实践,vant部分组件需要兼容处理的地方比较多,这里先注释了 // 比如 <van-icon name="scan" class="sm"/> 组件不能通过文档提供的 size 属性配置大小,只能通过非行内的 css 显式 font-size 配置样式才能正常适配 // const vant_pxtovw = pxtovw({ // viewportWidth: 375, // viewportUnit: 'vw', // exclude: [/^(?!.*node_modules\/vant)/] //忽略除vant之外的 // }) // https://vitejs.dev/config/ export default defineConfig({ plugins: [vue(), vueJsx()], css: { postcss: { plugins: [ // vant_pxtovw, loder_pxtovw ] } }, resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) } } })
-
Webpack
如果是 Webpack ,则需要在项目根目录下添加.postcssrc.js 文件进行如下配置:const path = require('path'); module.exports = ({ webpack }) => { // 如果读取的是vant相关的文件,viewportWidth就设为375,如果是其他的文件,我们就按照我们UI的宽度来设置viewportWidth,即750。 const designWidth = webpack.resourcePath.includes(path.join('node_modules', 'vant')) ? 375 : 750; return { plugins: { autoprefixer: {}, "postcss-px-to-viewport": { unitToConvert: "px", viewportWidth: designWidth, unitPrecision: 6, propList: ["*"], viewportUnit: "vw", fontViewportUnit: "vw", selectorBlackList: [], minPixelValue: 1, mediaQuery: true, // 我们引入一些第三方库的时候,比如 vant,上面配置的 exclude 去掉(注释也可),表示全部内容进行 vw 转换 exclude: [], landscape: false } } } }
-
vant团队的是根据375px的设计稿去做的,理想视口宽度为375px。所以做了如上判断
-
这里使用 path.join(‘node_modules’, ‘vant’) 是因为适应不同的操作系统:在 mac 下结果为 node_modules/vant,而在 windows下结果为 node_modules\vant。
vant 官方适配提醒截图: