项目中遇到的问题与报错

大纲链接 §

[toc]


轮子

初步完成的轮子


发布组件库时的 main 路径错误

package.json 错误的路径 "./dist/lib/vueel3.js",

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
{
  "name": "vue3-demo-ui-1",
  "version": "0.0.7",
  "author": "Xu Shuai",
  "license": "MIT",
  "files": [
    "dist/lib/*"
  ],
  "main": "./dist/lib/vueel3.js",
  "module": "./dist/lib/vueel3.js",
  "exports": {
    ".": {
      "import": "./dist/vueel3.js",
      "require": "./dist/vueel3.js"
    }
  },
}

package.json 正确的路径 "dist/lib/vueel3.js",

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18

{
  "name": "vue3-demo-ui-1",
  "version": "0.0.7",
  "author": "Xu Shuai",
  "license": "MIT",
  "files": [
    "dist/lib/*"
  ],
  "main": "dist/lib/vueel3.js",
  "module": "dist/lib/vueel3.js",
  "exports": {
    ".": {
      "import": "dist/lib/vueel3.js",
      "require": "dist/lib/vueel3.js"
    }
  },
}

rollup.config.js配置错误及运行rollup -c错误

  • 不使用rollup打包
  • 而直接使用vitelibrary-mode 库模式
  • vite.config.ts代替原来的rollup.config.js

rollup.config.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// 请先安装 rollup-plugin-esbuild rollup-plugin-vue rollup-plugin-scss sass rollup-plugin-terser
// rollup-plugin-esbuild
// rollup-plugin-vue
// rollup-plugin-scss
// sass
// rollup-plugin-terser
// import path from 'path'
import dartSass from 'sass'
import vuePlugin from 'rollup-plugin-vue'
import esbuildPlugin from 'rollup-plugin-esbuild'
import scssPlugin from 'rollup-plugin-scss'
import bundleSize from 'rollup-plugin-filesize'
// import alias from '@rollup/plugin-alias'
// import {nodeResolve} from '@rollup/plugin-node-resolve' // 告诉 Rollup 如何搜寻外部依赖
// import {terser} from 'rollup-plugin-terser' // 压缩 js 代码,包括 ES6 代码压缩
// import pkg from './package.json'

// const pathResolve = p => path.resolve(__dirname, p)

export default {
  input: 'src/lib/index.ts',
  external: ['vue', 'Vue'],
  output: {
    // exports: 'vueel3',
    globals: {
      vue: 'Vue' // 告诉rollup全局变量vue即是vue
    },
    name: 'vueel3-ui',
    file: 'dist/lib/vueel3.js',
    format: 'umd', // format: 'cjs',
    // plugins: [terser()],
  },
  plugins: [
    // nodeResolve({browser: true, preferBuiltins: true}),
    /*
    alias({
      '@': pathResolve('.')
    }),
    */
    // .vue -> .js
    vuePlugin({
      include: /\.vue$/,
      /*
      // 把单文件组件中的样式,插入到html中的style标签
      css: true,
      // 把组件转换成 render 函数
      compileTemplate: true,
      template: {
        isProduction: !process.env.ROLLUP_WATCH,
        compilerOptions: {preserveWhitespace: false}
      }
      */
    }),
    // .ts -> .js
    esbuildPlugin({
      include: /\.[jt]s$/,
      minify: process.env.NODE_ENV === 'production',
      target: 'es2015'
    }),
    // .scss -> css
    scssPlugin({include: /\.scss$/, sass: dartSass}),
    bundleSize(),
  ]
}

vite.config.ts开启build lib

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import vue from '@vitejs/plugin-vue';
import {defineConfig/*, PluginOption, UserConfig*/} from 'vite'; // const { defineConfig } = require('vite')
import Markdown from 'vite-plugin-md';
import ViteComponents/*, {Options}*/ from 'vite-plugin-components';
// vueCustomBlockTransforms
import {vueCompAddSourceCodeTitleFromCustomBlock} from './plugins/vueCompAddSourceCodeTitleFromCustomBlock';
import {terser} from 'rollup-plugin-terser' // 压缩 js 代码,包括 ES6 代码压缩
import esbuildPlugin from 'rollup-plugin-esbuild';
import bundleSize from 'rollup-plugin-filesize';

/*// ES6
import path from 'path';
import fs from 'fs';
import marked from 'marked';*/
// const path = require('path'); path.resolve(...)
// https://vitejs.dev/config/
const {resolve} = require('path');

export default defineConfig({
  base: './',
  plugins: [
    vue({
      include: [/\.vue$/, /\.md$/],
    }),
    Markdown(),
    ViteComponents({
      dirs: ['src/markdown'],
      // allow auto load markdown components under `./src/components/`
      extensions: ['vue', 'md'],

      // allow auto import and register components used in markdown
      customLoaderMatcher: (path: string) => path.endsWith('.md'),
    }),
    vueCompAddSourceCodeTitleFromCustomBlock('demo')
  ],
  resolve: {
    alias: [
      {
        find: '@',
        replacement: resolve('./src')
      },
      {find: /^~@/, replacement: resolve(__dirname, 'src')},
    ]
  },
  build: {
    outDir: 'dist/lib',
    lib: {
      entry: resolve(__dirname, 'src/lib/index.ts'),
      name: 'vueel3-ui',
      formats: [/*'es', */'umd'],
      fileName: (/*format*/) => `vueel3-ui.js`  // `vueel3-ui.${format}.js`
    },
    minify: 'esbuild',
    rollupOptions: {
      // 确保外部化处理那些你不想打包进库的依赖
      external: ['vue'],
      output: {
        // 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
        globals: {
          vue: 'Vue'
        },
        name: 'vueel3',
        // file: 'dist/lib/vueel3.js',
        format: 'umd',
        plugins: [terser()],
      },
      plugins: [
        /*
        // .vue -> .js
        vuePlugin({
          include: /\.vue$/
        }),
        */
        // .ts -> .js
        esbuildPlugin({
          include: /\.[jt]s$/,
          minify: process.env.NODE_ENV === 'production',
          target: 'es2015'
        }),
        // .scss -> css
        // scssPlugin({include: /\.scss$/, sass: dartSass}),
        bundleSize(),
      ]

    }
  }
});

抽出base配制

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import vue from '@vitejs/plugin-vue';
import {defineConfig/*, PluginOption, UserConfig*/} from 'vite'; // const { defineConfig } = require('vite')
import Markdown from 'vite-plugin-md';
import ViteComponents/*, {Options}*/ from 'vite-plugin-components';
// vueCustomBlockTransforms
import {vueCompAddSourceCodeTitleFromCustomBlock} from './plugins/vueCompAddSourceCodeTitleFromCustomBlock';
import {terser} from 'rollup-plugin-terser' // 压缩 js 代码,包括 ES6 代码压缩
import esbuildPlugin from 'rollup-plugin-esbuild';
import bundleSize from 'rollup-plugin-filesize';

/*// ES6
import path from 'path';
import fs from 'fs';
import marked from 'marked';*/
// const path = require('path'); path.resolve(...)
// https://vitejs.dev/config/
const {resolve} = require('path');

export default defineConfig({
  base: './',
  plugins: [
    vue({
      include: [/\.vue$/, /\.md$/],
    }),
    Markdown(),
    ViteComponents({
      dirs: ['src/markdown'],
      // allow auto load markdown components under `./src/components/`
      extensions: ['vue', 'md'],

      // allow auto import and register components used in markdown
      customLoaderMatcher: (path: string) => path.endsWith('.md'),
    }),
    vueCompAddSourceCodeTitleFromCustomBlock('demo')
  ],
  resolve: {
    alias: [
      {
        find: '@',
        replacement: resolve('./src')
      },
      {find: /^~@/, replacement: resolve(__dirname, 'src')},
    ]
  },
  /*
  build: {
    outDir: 'dist/lib',
    lib: {
      entry: resolve(__dirname, 'src/lib/index.ts'),
      name: 'vueel3-ui',
      formats: [/!*'es', *!/'umd'],
      fileName: (/!*format*!/) => `vueel3-ui.js`  // `vueel3-ui.${format}.js`
    },
    minify: 'esbuild',
    rollupOptions: {
      // 确保外部化处理那些你不想打包进库的依赖
      external: ['vue'],
      output: {
        // 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
        globals: {
          vue: 'Vue'
        },
        name: 'vueel3',
        // file: 'dist/lib/vueel3.js',
        format: 'umd',
        plugins: [terser()],
      },
      plugins: [
        /!*
        // .vue -> .js
        vuePlugin({
          include: /\.vue$/
        }),
        *!/
        // .ts -> .js
        esbuildPlugin({
          include: /\.[jt]s$/,
          minify: process.env.NODE_ENV === 'production',
          target: 'es2015'
        }),
        // .scss -> css
        // scssPlugin({include: /\.scss$/, sass: dartSass}),
        bundleSize(),
      ]

    }
  }
  */
});

vue-tsc && vite build

  • 运行yarn build报错
  • 实际运行vue-tsc && vite build
  • 直接运行vite build不报错
  • TS代码编译不通过
    • throw 'emit mode is not yet support';

build 之后加载 .md 文件报错

bug 重现

  • 打包yarn build 或者vite build 得到dist目录下所有文件
  • 使用http server运行服务hs dist -c-1
  • 查看介绍文档,发现空白

解决方法

  • 由于在路由中使用了动态加载const md = filename => h(Markdown, {path: `../markdown/%{filename}.md`, key: filename})
  • vite 打包时使用的是rollup
    • rollup不支持import()时动态拼接字符串(只有当运行函数md时,即md(intro),才能知道filename是什么)
    • rollup只是做代码的静态分析,否则运行代价太大,得不偿失
  • 解决方法是将运行时的动态改为静态加载
    • 将拼接字符串../markdown/%{filename}.md改为事先引入模块
    • import intro from './markdown/intro.md'
    • import getStarted from './markdown/get-started.md'
    • import install from './markdown/install.md'
  • 直接将引入的模块作为md函数的参数
    • md(intro)
    • md(getStarted)
    • md(install)
  • 并且修改md函数
    • const md = mdString => h(Markdown, {content: mdString, key: mdString})
  • 并且修改Markdown.vue组件
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<template>
<article class="markdown-body" v-html="content">
</article>
</template>

<script lang="ts">
import {
  ref
} from 'vue'
export default {
  props: {
    content: {
      type: String,
      required: true
    }
  }
}
</script>

Prismajs 不显示代码行数

https://prismjs.com/plugins/line-highlight/ | Line highlight ▲ Prism plugins https://prismjs.com/plugins/line-numbers/ | Line Numbers ▲ Prism plugins https://blog.xqopen.com/code-highlight-in-ghost/ | 几行代码就可以让你家Ghost支持代码高亮 https://juejin.cn/post/7023910122770399269?utm_source=gold_browser_extension | 尤雨溪推荐神器 ni ,能替代 npm/yarn/pnpm ?简单好用!源码揭秘! - 掘金 https://www.google.com/search?q=%22vue3%22+Prismjs+line+number&sa=X&ved=2ahUKEwi2zrbv2-zzAhXizDgGHTdyDgkQ5t4CegQIChAB&biw=867&bih=881&dpr=1 | “vue3” Prismjs line number - Google 搜索 https://morioh.com/p/ff92e45cadd6 | Highlight Code Using Prism.js and Vue Component https://blog.csdn.net/bigbear00007/article/details/109182369 | prism.js让页面代码变漂亮_HELLO WORLD-CSDN博客_prismjs https://www.cnblogs.com/pellime/p/9949843.html | prism.js——让网页中的代码更好看 - pellime - 博客园 https://www.jianshu.com/p/1619c91f73c2 | 代码美化JS–prismjs - 简书 https://www.cnblogs.com/geekgx/p/8134426.html | prism.js使页面代码变得漂亮 - GeekGx - 博客园 https://www.orchome.com/1374 | Prism.js介绍 - OrcHome https://hexingxing.cn/beautiful-code-highlighting-tool/ | PrismJS,一款漂亮的代码高亮工具 – 何星星


提问:

  • 1.代码链接为 https://github.com/xmasuhai/vueel3-demo-1/tree/06d4fbb59ce8b40d1ddbc6c7e6e9312c792b3ec9
  • 2.运行步骤为:
    • 安装依赖 yarn install;
    • 展示页面 yarn dev;
  • 3.复现步骤为:
    • 进入http://localhost:3000/
    • 点击开始按钮
    • 点击 Switch组件
    • 点击 查看代码 按钮
    • 显示的代码没有行数显示
    • 点击浏览器刷新按钮或F5 重新加载页面
    • 点击 查看代码 按钮
    • 显示的代码有行数显示
    • 点击 Button 组件(切换了路由)
    • 点击 查看代码 按钮
    • 显示的代码没有行数显示
  • 4.期待结果为:一进入任意组件或者切换组件对应的路由时,点击 查看代码,就可以显示代码行数
  • 使用的是Prismjs的插件line-numbers,估计出问题的文件为src/components/Demo.vue里引用的import 'prismjs/plugins/line-numbers/prism-line-numbers.min.js';,是一个立即执行函数

引入的样式没有生效或报错

提示:假如script标签内的import ‘prismjs/themes/prism.css’没有生效或报错, 请尝试:单独建一个没有scoped的style标签,然后在其中引入,具体代码如下:

1
2
3
4
5
6
7
8
9
//原来写的样式
<style lang="scss" scoped>
...
</style>

// 加上下面这一段
<style lang="scss">
  @import 'prismjs/themes/prism.css';
</style>

vite 插件 rollup 文档的 命名误导 id

  • 处理自定义标签<demo></demo>
  • vite 1.x 迁移 自定义块转换
  • transform(code, id)中的id其实所解析到的文件的 url
  • 使用正则匹配/vue&type=demo/.test(id)
  • 去除多余的查询参数得到该文件路径
    • const path = id.replace(`?vue&type=demo&index=0&lang.demo`,'');
  • 按路径读取文件内容const fileString = fs.readFileSync(path).toString();
  • 找出<demo></demo>标签节点,并且得到文本
    • const parsed = baseParse(fileString).children.find(n => n.tag === 'demo');
    • const title = parsed.children[0].content;
  • 得到代码主体const main = fileString.split(parsed.loc.source).join('').trim();
  • 给组件附加属性
    • Component.__sourceCode = ${JSON.stringify(main)}
    • Component.__sourceCodeTitle = ${JSON.stringify(title)}
  • 在模板字符串中返回 方法
    • return `export default function (Component) { Component.__sourceCode = ${JSON.stringify(main)} Component.__sourceCodeTitle = ${JSON.stringify(title)} }`.trim();

解构出的 props 数据在 script setup 中失去数据响应性

  • 需要用 toRefs(props) 重新赋予其数据响应
  • destructured prop visible is Value (integer for e.g.) which cannot be reactive by itself
  • 解构出来的visible为简单类型,不再具有数据响应性
  • 需要调用 toRefs(props) 赋予数据响应性
  • Destructuring the props will cause the value to lose reactivity

参考


CSS @importwebstorm中报错

https://juejin.cn/post/6974584590836957221 | vite 中动态引入图片路径 - 掘金 https://juejin.cn/post/6980141344131923999 | Vite 的好与坏 - 掘金 https://juejin.cn/post/6861501624993447950 | CSS八种让人眼前一亮的HOVER效果 - 掘金 https://juejin.cn/post/6918672538646102029 | Vue3+Ts+Vite购物车实战 - 掘金 https://juejin.cn/post/6976558626425028645 | 按需加载更优雅的解决方案——vite-plugin-components - 掘金 https://juejin.cn/post/6844904031513477128 | 请收下这72个炫酷的CSS技巧 - 掘金 https://juejin.cn/post/6926822933721513998 | 2021必知必会的vite+vue3项目最佳实践 - 掘金 https://juejin.cn/post/6984033527520051208 | 来一个vitepress版的博客主题吧(简约版) - 掘金 https://juejin.cn/post/6988704825450397709 | [Vite 总结] 帅小伙花了一个月时间总结的 Vite 知识点和迁移方案 - 掘金 https://juejin.cn/post/7009519892139507749 | vue2 配个vite,让开发速度翻倍⚡️ - 掘金


<component></component>必须加上:key="currentTab"属性

显示被选中的内容,失败

  • 官方不推荐v-ifv-for一起使用
  • 不循环渲染<component></component>,使用获取当前选中的标签传给<component :is="currentTab"></component>
  • 使用计算属性,实时响应currnetTab的变化
  • <component :is="currentTab" :key="currentTab" class="vue-tabs-content-item"></component>
    • 必须加上:key="currentTab"属性
    • component传递相同类型的vnode时,编译是竞态的,见 vuejs/vue-next issue#2013

警告[Vue warn]: Extraneous non-props attributes (title) were passed to component but could not be automatically inherited because component renders fragment or text root nodes.

  • 使用了文本节点作为组件的根节点

解决hover影响移动端样式

PC端原本hover样式是鼠标悬浮显示,不悬浮就消失的样式在移动端显示时,点击后才显示hover样式,此后如果不做处理,那么hover样式就一直存在

  • 判断当前设备是什么设备
  • 通过设备宽度来判断,用 @media screen and(...) 来设置移动端和pc的样式。
  • 但这个来处理hover并不好,因为pc端网页窗口也能缩小到500px,移动端的窗口大小也是不定的

媒体特性

  • 通过查阅媒体特性可知,any-hover是用来查看设备是否支持hover事件的
1
2
3
4
@media (any-hover: hover){
	// 在这写hover样式
}

使用touchstart 在body上绑定一个空的touchstart事件

1
document.body.addEventListener('touchstart', function(){ });

消除在移动端中浏览器自带的一个点击高亮效果,可以通过给a标签或者body,html加如下CSS代码:

1
-webkit-tap-highlight-color: transparent;

使用 script setup 语法糖 无法获取context

  • 官方文档不建议使用getCurrentInstance当作在组合式 API 中获取 this 的替代方案来使用
  • 大部分情况下无需用到 context
    • ...context.slots
    • ...context.slots.default()
    • ...context.slots.default()[0]
  • Vue 直接暴露了其他接口,替代原来需要用context.*访问的接口,比如
    • defineProps({})
    • defineEmits([])
    • defineExpose({})
    • useSlots()
    • useAttrs()
  • 响应式属性、导入的方法和组件会被直接暴露给模板

:deep(selector) 代替Vue2.xSCSS过时的写法

  • Vue2.x中写scss的深入组件的选择器的写法::v-deepVue3.x中改为:deep(selector)


参考文章

相关文章


  • 作者: Joel
  • 文章链接:
  • 版权声明
  • 非自由转载-非商用-非衍生-保持署名