跳到主要内容

BUG FIX

· 阅读需 26 分钟

【已解决】关于cookie-universal-nuxt无法移除cookie的问题

2020-08-31 17:17:48

原因分析

大多数情况下,这是由于path不同导致的。

当调用this.$cookies.set()进行cookie设定,但未提供path参数时,将默认存储在当前所在路由下。

之后,若再次调用remove()函数,且未提供path参数,将默认移除首页/下的参数。

此时,问题就发生了。

解决方案

对于一些通用数据,比如user,建议存储时显式存储在/路径下,以免不必要的麻烦。

此外,cookie-universal里设定的removeAll()函数,默认只能清空/下的参数。

详情见cookie-universal的使用说明:

// note that removeAll does not currently allow you
// to remove cookies that have a
// path different from '/'

【部分解决】关于markdownheading导航异常的问题

原因分析

很有可能是因为在content中对markdown解析时,经过remark-parse后,markdown内的heading出现了tabindex=-1

于是,我特地去看了一下githubreadme内的heading导航。发现它是没有tabindex=-1且可以正常导航的。

我又测试了一下,在该heading上添加tabindex=-1,发现依旧可以正常导航。再联想之前在自己的网站上测试去除tabindex=-1依旧不能正常导航,基本确定不是tabindex=-1的问题。

测试过程

直接复制粘贴导航栏中有用的a代码可以正常跳转
只保留a标签的href属性(且是转以后的)可以正常跳转(谷歌浏览不可以)
只替换a标签的href属性(其他的arai-hidden等属性保持不变)仅第一次点击可正常跳转,之后的点击异常;
经过F12重启,确认href属性依旧是转义后的
只去除a标签的data-v属性无效
删除a标签的所有其他属性无效
删除a标签内部的子节点无效
只保留a标签的href属性(未转义)无效

测试结果:可能是heading的点击穿透问题。

解决方案

考虑到只有页面的侧边栏(TOC)有导航意义,因此直接禁用heading链接的点击即可。

经过一番搜索,只需要加上cursor-point: none的样式即可,在tailwindcss中为cursor-point-none

但这样,就无法直接在页面内导航了。

总结展望

也许有其他的解决方案,但我还没找到。

目前,是不支持页内heading导航了。

【已解决】关于tailwindcssul没有样式的问题

原因

是因为tawiwindcss定义了一个base.css,这里面对一些html的基本样式做了修改。

ol,
ul {
list-style: none;
margin: 0;
padding: 0;
}

在此基础上,我们可以覆写这些css样式,有基于css和基于plugin等多种方式,具体可以见:Adding Base Styles - Tailwind CSS

【已解决】关于Element-UI按需入的问题(重要)

现场

按照element-ui官方文档,我在.babelrc文件中配置了对element-ui的按需引入,如下。

{
"presets": [["es2015", { "modules": false }]],
"plugins": [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
],
"env": {
"test": {
"presets": [
[
"@babel/preset-env",
{
"targets": {
"node": "current"
}
}
]
]
}
}
}

然而,根据analyze显示,element-ui所占的体积大的惊人。

image-20200824201732382

解决方案

参考脚本之家_www.jb51.net这篇文章,给我的主要启发是:不能直接在.babelrc文件中配置,而是在nuxt.config.jsbuild选项中启用babel的配置

  build: {
analyze: true,
babel: {
plugins: [
[
'component',
{
libraryName: 'element-ui',
styleLibraryName: 'theme-chalk',
},
],
],
},
},

结果

目前的页面分析结果如下,可以看到,element-ui的体积大小,已经相较于之前好了很多,连同另外一个css框架一起只占一半的依赖包体积了。

image-20200824201157993

【已解决】关于移动端页面无法滚动的问题

找了一遍,果然是overflow的问题,出在了这里:

image-20200822222041677

这里原作其实是判断使用single page的,我把single部分删了,变成了这样。

我没有测试过原作的移动端显示,但现在的问题就是移动端无法滚动了。

因此删除overflow-y-hidden

【已解决】BUG:Element-UI 中的loading不居中的问题

参见:element-ui 局部区域 loading 效果

换个图标就可以了。

非正常显示效果(默认图标)

v-loading="loginLoading"
<!-- element-loading-spinner="el-icon-loading" -->
element-loading-text="正在努力奔跑……"

image-20200822022440891

image-20200822022026311

正常显示效果(换了图标后)

v-loading="loginLoading" element-loading-spinner="el-icon-loading"
element-loading-text="正在努力奔跑……"

image-20200822022337209

image-20200822021931120

原因

默认使用svg图片占位,而父级元素.el-loading-mark只有一个text-align: center的居中设定(而非display: flex; justify-content: center)。

所以默认的那个圈圈不会居中,换成<i class="icon-xxx"></i>就可以解决了,因为它支持text级别的居中。

关于 asyncData 的用法

不可以在子组件中使用。

具体可以参见vue.js - Nuxt 子组件内可以使用 asyncData 吗? - SegmentFault 思否

害,费了老长时间测这个问题了。

【已解决】BUG:关于无法在 IDE 中移动、删除或重命名文件(夹)的问题

现场

我想重命名CS文件夹为coding文件夹,然而出现了IOException

image-20200821012423773

很明显,这是因为文件夹被占用,但我并不清楚是谁在占用,我的 IDE 也不够强大到为我分析出是哪个程序或者子程序。

我尝试关闭了我正在运行的 IDE 内的程序,但并没有解决问题,说明是来自外部的。

我尝试又关闭了一些外部程序,比如typora,因为当它打开了这个文件夹下的某个文件后,IDE 将无法对该文件或该文件所在的文件夹进行一些敏感操作。

但这一切都未能奏效。

这是十分令人恼火而绝望的,因为你并不知道那个程序对该文件将持续占用控制到什么时候。

在我以前的经历中,我经常做的一件事就是重启 IDE,这是往往有效的,但,这实在代价太大了。

于是,这一次,我打算深入研究一下这个问题,我把目光投向了我的搜索引擎。

行动

我从“文件被占用”这一情景出发,进行搜索。

我之所以知道这样的一种术语,是因为我曾经使用过 360 安全卫士的“解除文件占用”功能,偶尔还是有效的。但更多的时候并不有效。

我很快找到了这篇文章win10 文件被占用无法删除如何解决-系统城,跟着它的指导,我输入了文件夹名结果跳出一堆候选结果。凭借经验,我重新输入了文件夹的绝对路径,顺利地找到了始作俑者——“TgitCache.exe”。

image-20200821013210368

这个结果意料之外,但情理之中。因为在之前,我也遇到过因为 git 的占用,导致文件系统无法操作的情况,那个时候我直接杀死了任务管理器中的无数个 git 子进程,不想再次尝试。

但我实在不清楚 TgitCache 具体是个什么东西,我再次搜索,在这个帖子中发现有人有和我一样的问题:如何停止并启动 TGitCache.exe? - 问答 - 云+社区 - 腾讯云

一些大佬留言只要关闭TortoiseGitStatus Cache就可以了。

image-20200821013827496

但我如此设置之后,返回 IDE,依旧未能解决问题。

我决定重启一下TortoiseGit

但我并不知道怎么重启这玩意,然后右键在文件夹内点击了Bisect reset,获得一个 error 之后,发现刚刚输入的文章内容全无了,我简直欲哭无泪。不过还好文章在 IDE 中同步打开了,调用local history成功找回了原来的内容,我真是太爱这个功能了! :::

我通过任务管理器杀死TortoiseGit

image-20200821014739527

但我懵逼了,IDE 中依旧不能重命名。。。

解决方案

一顿操作猛如虎后,我最后还是选择直接关闭 IDE,然后重启,这下终于成功了。

人生大抵如此,兜兜转转,还是要回到原点~

【已解决】BUG: 在 markdown 文件中引用 vue 组件,props 不能成功传入的问题

现场

这是因为在读取 markdown 文件过程中,变量名自动取成了小写,导致原先定义的驼峰式 prop 变量无法正常赋值。

具体而言就是,在 markdown 中:wordList会变成:wordlist,而原先的 vue 组件中则会保持wordList的 prop 不变,这导致了 vue 组件多了一个wordlist属性,而wordList则为空。

解决方案

【部分解决】BUG: content-theme-docs 中关于 index.md 的路由问题

现场

image-20200818171926502

解决方案

使用index.vue等 page 页面去定义这些路由即可。

【已解决】BUG: 关于 frontmatter 中未定义 fullScreen 字段,导致全屏切换组件无效的问题

现场

我封装了一个点击切换全屏的组件,它依赖于父组件(即nuxt-content页面的document.fullScreen属性)。

我在测试的过程中发现了问题,原因是我的一些页面没有初始化fullScreenfrontmatter ,而我的切换逻辑仅仅是简单的取反,即document.fullScreen=!document.fullScreen

我修改这个逻辑,希望它变得更加稳健,即document.fullScreen=!(document.fullScreen || false)

然而,并不奏效,我忽视了我靠切换fullScreen属性以改变网页展示的行为,依赖于 vue 对 data 元素的监听。

由于我们的 markdown 文件事先并没有写入fullScreen,因此导致 vue 并没有监听到该键,所以之后的操控行为并非响应式的。

解决方案

第一种解决方案就是修改原来的 markdown 文件,使之包含一个默认的初始值,比如fullScreen: false

第二种解决方案,则是修改一下生成frontmatter或者解析frontmatter步骤的代码,使frontmatter或者document 有着合理的默认值。此外,对于不规范的 markdown 文档,还应在 console 中进行 warning 提示。

【已解决】BUG: content-theme-docs 中关于 index 键重复的问题

BUG 初见面

我在使用nuxt-content官方的content-theme-docs主题时,遇到了浏览器警告,提示我index键重复。

image-20200818163726511

这样的报错,我是大概知道什么原因的。

这是因为我刚刚从vuepress框架迁移到nuxt框架上来,vuepress需要每个文件夹下有一个index.md文件用以渲染该文件夹路径,而当访问这些没有index.md的文件夹路径时,将失败。由于这些文件夹路径大多又和导航栏、侧边栏相绑定,耦合很高,极易出现意想不到的 bug。

nuxt-content虽然也是基于文件路径,但是给出了更加灵活的路由方案,因此不需要如此大费周章。

基于此,我直接删除或者重命名了博客文件夹下所有(除首页)的index.md文件

于是,报错不再发生了。

BUG 再见面

尽管如此,意外还是继续发生了。

同上,如果我直接访问一个没有inedx.md的文件夹路径,nuxt-content也会报出page not found的问题,只不过,由于content-theme-docs主题里的侧边栏设计的比较巧妙,即文件夹路径默认不可点击,因此发觉不了这样的问题。

但是,现在有一项新的需求:没有 index.md 文件将无法实现面包屑导航的功能

即当从AAA/xxx.md文件导航回AAA文件夹时,由于该文件夹下没有index.md文件,将导致导航失败。

基于此认识,如果我们想让自己的文件导航系统更加稳健,我们还是应当采取vuepress的管理方案,每个文件夹下必须有一个index.md文件用于导航占位,或者,在程序中设置对应的路由选项,比如为其设定一个默认的页面展示。

我认为,两者可以结合使用,使程序具有更强的扩展性与兼容性。

于是,我再次新建了一些index.md文件,并再次触发了index key 重复的报错

摸索历程

源代码检查

查看源代码,原来是content-theme-docs的作者,在遍历文章列表(以生成侧边栏)时,将文章的slug作为了键索引。

slug是什么鬼呢?在gatsby框架里slug就是文件的路径,即域名后面的一串path

但在nuxt中我检查出以下的结果。

首先是marked包中有slug的生成方式,如下。

image-20200818165256663

有点复杂,主要是我并不知道这里面的e是什么,是文件名?还是文件路径?不得而知。

接着在content-theme-docs中有一个slug的赋值操作。

export default (userConfig) => {
const config = defu.arrayFn(userConfig, defaultConfig);

config.hooks['content:file:beforeInsert'] = (document) => {
const regexp = new RegExp(
`^/(${config.i18n.locales.map((locale) => locale.code).join('|')})`,
'gi',
);
const dir = document.dir.replace(regexp, '');
const slug = document.slug.replace(/^index/, '');

document.to = `${dir}/${slug}`;
};

return config;
};

可以看到,这里的slug主要是从文档的slug属性中,替换掉index,并生成文档的路由地址,但貌似也不是我们想要的答案。

再接着,我们查到了content-theme-docs中关于导航栏生成的代码。

<li
v-for="(docs, category, index) in categories"
:key="category"
class="mb-4"
:class="{ 'lg:mb-0': index === Object.keys(categories).length - 1 }">
<h3
class="mb-2 text-gray-500 uppercase tracking-wider font-bold text-sm lg:text-xs">
{{ category }}
</h3>
<ul>
<li
v-for="doc of docs"
:key="doc.slug"
class="text-gray-700 dark:text-gray-300"></li>
</ul>
</li>

在这里,首先对所有的目录进行遍历,这些目录其实不是文件系统中的目录,而是定义在每篇文章里frontmatter中的字段category

categories() { return this.$store.state.categories[this.$i18n.locale] }

说到这儿,如果对content-theme-docs生成侧边栏的方式不满意,以及对于frontmatter中需要人为加入directory而非tags等设定不满意的话,可以重写一下AppNav.vue文件。(我自己目前还挺满意的,我并不想 hack 这个文件,以改变所有文章的筛选显示。我会采取\$content()的方法进行筛选。 :::

由于目录一般来说都是些不一样的文件名,而且categories已经是一个集合(应该是),不存在键重复的问题。

但最后一行,doc.slug就有问题了,因为这里的 slug,很有可能就是文档名,即对于任意文件夹下的index.md文件,其slug都等于index,由此引发了键冲突。

解决方案

由于vue中的遍历,键只是一种索引,比较随意,因此简单修改以上源代码,将键设置为其他字段就好了,比如本地文件系统的路径地址,这个肯定唯一。

实践结果显示,浏览器确实不再报错了,解决方案有效!

反思总结

尽管问题解决了,但是还有一些困惑存在。

1. content-theme-docs这个 slug 到底是怎么生成的,为什么只生成了文件名(而不是像其他框架一样生成了文件的相对路径)?

留待后续解决吧!

【已解决】BUG: element-ui 默认 drawer 不能滚动

需求

我需要实现一个点击菜单�� 弹出一个抽屉,显示可供选择的菜单项。

现场

我使用了el-drawer帮助我完成这样的需求。

在开发过程中,我尝试放入了一个较长的列表项,这直接导致抽屉中的内容高度超过 100%,并无法滚动。

问题是无法滚动,这不符合常识。

我搜索到这样的一篇帖子:[Bug Report] el-Drawer Rolling Problem Repair · Issue #17600 · ElemeFE/element,原来是drawer内部的 css 设定了overflow:hidden

了解到这样的信息后,我立即验证了一下,果然是这个问题。

image-20200818160242494

那么解决方案就很简单了,通过各种方式修改成overflow:auto即可。

解决方案

帖子中给出的方法是修改element-uiindex.css文件,我尽量避免这样的措施。

我选择的方法是对该组件进行css穿透设置,详情如下。

/deep/ .el-drawer {
overflow: auto !important;
}

可以看到,浏览器里已经成功覆写了内部overflow:hidden的设定,转而变成overflow:auto,满足了我们滚动的需求。

反思总结

有几点值得注意。

1. 为什么 element-ui 要屏蔽溢出

不得而知。

也许是他们认为打开的抽屉,不应有超出的内容,毕竟真实世界中抽屉是不可以装超过自身体积的东西的。

所以,也许有其设定的合理性。

在此共识上,我自己也尽量遵循这样的一种设定,我目前是开发阶段,所以直接装入了一个很长的列表,后续会把它们组合,尽量使之不超过整个容器体积。

但尽管如此,我还是倾向于可以竖向滚动,因此我还是在组件中使用了穿透的方式,以防万一。

2. 两种穿透方式

/* 方式一,使用/deep/,通用 */
/deep/ .el-drawer {
overflow: auto !important;
}

/* 方式二,使用 >>>,sass不支持 */
>>> .el-drawer {
overflow: auto !important;
}

3. 穿透设置要点

以下写法是不正确的,这意味着在el-drawer下的一些子级元素需要进行overflow:auto的设定。

.el-drawer /deep/ {
overflow: auto !important;
}

在这里的实际需求是el-drawer其本身需要进行overflow:auto的设定。

因此,顺序很重要。

【已解决】BUG: prettier 对 jsx 格式 style 分行后浏览器解析无法识别

现场

初始代码,一行 jsx,定义了多个 css 属性。

image-20200818132729397

经过prettier美化后,变成了多行。

image-20200818133051185

然而,在浏览器里渲染出来,却多了换行符导致css无效。

image-20200818133210747

解决方案

使用正则替换一下。

const styleReplace = (s) => {
const s2 = s
.trim()
.replace(/\s*(\S*): (\S*);\s*/g, "'$1': '$2',")
.replace(/style="(.*?)"/m, ':style = "{$1}"');
console.log(s2);
return s2;
};

反思总结

待更。