多种方式解决 Windows CMD 中 vue-cli-service 不是内部或外部命令

前提

已安装 Vue 脚手架

1
npm install -g @vue/cli

现象

找不到 vue-cli-service 命令

1
'vue-cli-service' is not recognized as an internal or external command, operable program or batch file.

经过搜索,发现这个问题只在 Windows 下存在。

装了脚手架应该会在 node 目录产生 vue-cli-service.cmd 的文件,实际没有产生,不过在全局 node_modules 下是有的。

有说清理 node_modules 重新安装可以解决的,试了不管用,全局卸载脚手架重新安装也不管用,就算管用也比较麻烦,于是我找到了几个间接使用方法——

阅读更多

Vue Router 向 URL query 添加、删除参数

添加一个参数

当前 URL:http://localhost/home?keyword=example

1
this.$router.replace({ query: { ...this.$route.query, code: '1' } })

最终 URL:http://localhost/home?keyword=example&code=1

删除一个参数

我所使用的 Vue Router 版本为 3.0.3,删除参数比较麻烦。

当前 URL:http://localhost/home?keyword=example&code=1

无效方法
1
2
delete this.$route.query.code
this.$router.replace({ query: this.$route.query }) // 地址栏无反应
有效方法
1
2
3
4
let newQuery = JSON.parse(JSON.stringify(this.$route.query)) // 深拷贝
delete newQuery.code
// 如果有引入 lodash, 可以写成: let newQuery = _.omit(this.$route.query, 'code')
this.$router.replace({ query: newQuery })

最终 URL:http://localhost/home?keyword=example

阅读更多

如何给 Icarus 增加夜间模式

Preview

Live Preview

https://www.imaegoo.com/

Attention

This extension is NOT FULLY TESTED, so it may not fully cover the theme styles, if you find something wrong (such as bright things in night mode), please report it in this issue, do not open new issue.

Usage

  1. Merge night branch from imaegoo/hexo-theme-icarus into your icarus theme folder, or dowmload zip.
  2. If you configured an image logo, you should prepare a logo for night mode, then apply them in themes/icarus/_config.yml.
    1
    2
    3
    logo:
    light: /images/logo.png
    dark: /images/logo-dark.png

Modify

If you want to customize your theme, you can modify night mode part in themes/icarus/source/css/style.styl.

Thanks

Universe background from https://github.com/fan-lv/Fan

van-list 一直触发加载问题的排查

移动端分页一般都是向下滑动加载更多,Vant 组件库提供了 van-list 来实现这一功能。

List 组件通过loadingfinished两个变量控制加载状态,当组件滚动到底部时,会触发load事件并将loading设置成true。此时可以发起异步操作并更新数据,数据更新完毕后,将loading设置成false即可。若数据已全部加载完毕,则直接将finished设置成true即可。

实际应用中发现,即使内部元素已经填满一整屏,仍然会触发加载,直到我模拟的20多页全部加载完才停下来。

我没有给这个问题写专门的 CodePen demo,比较麻烦,碰到的人也不一定多。

结论

van-list 会在内容之后增加一个 placeholder,通过 placeholder 的位置判断内容是否已填充满屏。
van-list 本身为 flex 布局时,flex-direction 必须是 column(或 column-reverse)。

过程

首先我的用法是这样的:

template
1
2
3
4
5
6
7
<van-list> <!-- flex -->
<van-grid>
<van-grid-item />
<van-grid-item />
<van-grid-item />
</van-grid>
</van-list>

首先看文档,英文文档没有提到,但中文文档有以下一段话:

使用 float 布局后一直触发加载?
若 List 的内容使用了 float 布局,可以在容器上添加van-clearfix类名来清除浮动,使得 List 能正确判断元素位置

检查了一下,我没有在使用 float 布局呀。

阅读更多

Icarus 夜间模式(实验中)

更新了 Icarus 主题代码,右上角增加了夜间模式切换按钮,是实验中的功能,欢迎体验。

通过向 body 添加名为 night 的 class 实现,状态记在浏览器 localstorage 中。

已知问题:

  1. 样式可能没有全面覆盖。
  2. 夜间模式在低性能浏览器上导致页面响应缓慢,需要优化性能。

目前还没有做成插件,仅在自己的博客使用,后期如果有时间的话,会考虑做成 extension。

粘性布局之粘底效果(position sticky, bottom 0)

粘性布局之粘底效果(position sticky, bottom 0)

经常在查资料时访问各种 CSDN 博客会发现,当 屏幕高度 < 左边栏的高度 < 内容的高度 时,滚动屏幕,左边栏会随着内容一同滚动,当滚动到左边栏底部时,左边栏会停止滚动,而内容会继续滚动。

这种设计的优势在于,用户既能够滚动左边栏,又不会在左边栏不够长时,造成页面左侧大片空白的尴尬,这种布局模式,叫做 粘性布局(sticky)

粘性布局在元素满足显示条件时,表现与普通布局没什么不同,但当元素随着页面滚动而无法显示时,会转为 fixed 布局效果,主流浏览器已经全部支持粘性布局(IE不支持)。

通俗一点讲,类似于 Excel 中的“冻结窗格”。

绝大多数网上的教程材料都用 position: sticky; top: 0; 这样的组合来举例,但为了实现 CSDN 左边栏效果,position: sticky; bottom: 0; 似乎不能和想象一样的起作用。

先说结论吧

  1. sticky 的确是无法直接粘底的……
  2. CSDN 使用 JS 动态计算实现,当计算到左边栏底部即将滚上屏幕时,立即对左边栏添加 position: fixed; bottom: 0; 样式,把左边栏定死,延时较为明显,快速上下滚动时能看到闪烁
  3. 我使用 position: sticky; 实现,通过 JS 计算 屏幕高度 - 左边栏高度 得到 top 的值,快速滚动时没有闪烁
阅读更多

Chrome 78 地址栏显示完整地址(https 和 www,Steady-State URL)

注意:该方法在 Chrome 79 及之后版本中已失效!

打开 chrome://flags/,78版本已经找不到 omnibox-ui-hide-steady-state-url-schemeomnibox-ui-hide-steady-state-url-trivial-subdomains 了。
按 F12 打开 Console,执行以下命令,然后重启 Chrome。

Console
1
2
3
4
5
6
7
[
'omnibox-ui-hide-steady-state-url-path-query-and-ref',
'omnibox-ui-hide-steady-state-url-scheme',
'omnibox-ui-hide-steady-state-url-trivial-subdomains'
].forEach((f) => {
chrome.send('enableExperimentalFeature', [`${f}@2`, 'true']);
})

代码中 @2 对应的是 Disabled。@0@1 分别对应 Default 和 Enabled。

测试有效的版本:78.0.3904.97
方法来源:ysc3839(https://www.v2ex.com/t/613776

JS 原生对象与数组拷贝

浅拷贝单层对象

1
2
let obj = { id: 1, title: "1" }
let copyOfObj = Object.assign({}, obj)

深拷贝多层对象

1
2
3
4
5
6
7
let obj = {
id: 1,
title: "1",
tag: ['js', 'javascript'],
category: { id: 1001, title: 'frontend' }
}
let copyOfObj = JSON.parse(JSON.stringify(obj))

浅拷贝简单类型数组

1
2
let arr = [1, 2, 3]
let copyOfArr = [...arr]

深拷贝单层对象组成的数组

1
2
3
4
5
6
7
let arr = [
{ id: 1, title: "1" },
{ id: 2, title: "2" },
{ id: 3, title: "3" }
]
let copyOfArr1 = arr.map((item) => Object.assign({}, item))
let copyOfArr2 = JSON.parse(JSON.stringify(arr))

深拷贝多层对象组成的数组

1
2
3
4
5
6
7
let arr = [
{ id: 1, title: "1", subObj: { name: 'subObj1' } },
{ id: 2, title: "2", subObj: { name: 'subObj2' } },
{ id: 3, title: "3", subObj: { name: 'subObj3' } }
]
let copyOfArr1 = arr.map((item) => JSON.parse(JSON.stringify(item)))
let copyOfArr2 = JSON.parse(JSON.stringify(arr))

总结

不考虑性能的情况下,JSON.parse(JSON.stringify(value))是最简最万能的拷贝。