山山而川

山山而川 查看完整档案

北京编辑清华大学  |  计算机应用技术 编辑个人  |  web前端工程师 编辑填写个人主网站
编辑

_
| |__ __ _
| '_ | | | |/ _` |
| |_) | |_| | (_| |
|_.__/ \__,_|\__, |

         |___/  

个人动态

山山而川 收藏了文章 · 2020-11-10

极力收藏最近Vue3+或Vue-CLI3+非常热门的十几篇文章

Vue3+ & Vue-CLI3+ 开发生态圈资讯

该推荐文章列表的最新资讯会第一时间发布到Github上,欢迎Star:
Find the latest breaking √vue3 & vue-cli 3 News

🚀欢迎Star,后续会不断更新。
🇨🇳最后更新日期:2️⃣0️⃣2️⃣0️⃣/0️⃣6️⃣/0️⃣6️⃣

【2020】 ≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡------------------------ 【2021】

除了单独Vue3资讯,欢迎查看更多vue.js资讯:【【🔥Vue.js资讯📚】目前web前端开发非常火爆的框架;定时更新,欢迎 Star 一下。

目录

🐣 关于旧版本

Vue CLI 的包名称由 vue-cli 改成了 @vue/cli。 如果你已经全局安装了旧版本的 vue-cli (1.x 或 2.x),你需要先通过 npm uninstall vue-cli -g 或 yarn global remove vue-cli 卸载它。

🐥Node 版本要求

Vue CLI 需要 Node.js 8.9 或更高版本 (推荐 8.11.0+)。你可以使用 nvm 或 nvm-windows 在同一台电脑中管理多个 Node 版本。

🐓Vue 3.0 源代码

当大多数国人还在庆祝国庆节的时候,尤雨溪大大在昨天凌晨发布了 Vue 3.0 源代码,源码地址:https://github.com/vuejs/vue-... 。虽然目前还 处于 Pre-Alpha 版本,但是可以预见后面的 Alpha、Beta 等版本应该不会太遥远。
之前,就有预言,除了性能优化、脚手架和新功能外,TypeScript绝对是一个重点,因此,在Vue 3.0源代码版本中,98%代码由Typescript编写,相信后面会是100%。
通过本次发布的源代码可以了解到针对 Vue 3 计划并已实现的主要架构改进和新功能。
Vue 3 中最主要的新特性:组合式 API,已经可以借助 https://github.com/vuejs/comp... (在 Vue 2 项目中作为插件使用)体验到。

v3.0.0-beta.14(2020-05-19)
@github-actions github-actions released this 19/5 · 14 commits to master since this release
Please refer to CHANGELOG.md for details.

...

v3.0.0-beta.2
released this 6 days ago · 29 commits to master since this release
release: v3.0.0-beta.2

v3.0.0-beta.1
released this 7 days ago · 40 commits to master since this release
release: v3.0.0-beta.1

🔥🐔2020前端面试秘籍

【吐血整理清单一】前端面试全攻略,为您保驾护航,金三银四
【吐血整理清单二】前端面试全攻略,为您保驾护航,金三银四
【吐血整理清单三】前端面试全攻略,为您保驾护航,金三银四

秘籍在手,天下我有; 只要你想进,那么世界就是你的。

🐔前端整理之道

【整理】前端优化得有个好手段,比如看这个清单🍑🍒🍓🍆🌽
【整理】前端学习笔记总结清单,应有尽有🍇🍈🍉🍊🍋

🦃关于TypeScript

【2020-Q1-News】TypeScript新鲜一波流,自己品尝?
【最新】TypeScript梳理知识点列表,可否一战?
【必会】都已经9102年底了,你必须会TypeScript。

为什么要学习它?
因为:

  • 按需输出 JavaScript 版本
  • 代码标准化利于团队开发
  • 主流框架及最新特性的支持
  • 便于重构和主流IDE支持
  • 更多友好特性和检测

...

哈哈哈,并不是,是因为都已经2020了,大公司和你们都在用。

Vue3-CheatSheet

由 Vue Mastery 网站归纳的 Vue 3 Cheat Sheet, 直观地概况了其主要特性。

下半年撸vue3的姿势

霸气姿势观望 vue3 核心技术ing

  • Proxy:不只是解决了 defineProperty 的局限性。
  • Performance:性能更比Vue 2.0强。
  • Tree shaking support:可以将无用模块“剪辑”,仅打包需要的。
  • Composition API:组合API。
  • Fragment, Teleport, Suspense:“碎片”,Teleport即Protal传送门,“悬念”。
  • Better TypeScript support:更优秀的Ts支持。
  • Custom Renderer API:暴露了自定义渲染API。

TODOLIST:

What you will love in Vue 3
Prepare yourself for what to expect in Vue 3 with Alex Kyriakidis' presentation from the Vue.js Amsterdam conference.

GitHub - vuejs/vite: Make Web Dev Fast Again
Vite is an opinionated web dev build tool that serves your code via native ES Module imports during dev and bundles it with Rollup for production.

Vue.js 3 Course - Composition API, TypeScript, Testing
Vue.js 3 introduces some changes to the Async Component API - find out the changes, and how you can use Async Components with Webpack 5's bundle splitting to make your apps load faster than ever.

The case for HOC vs The Composition API
In this article Abdelrahman compares Higher-Order Components (using scoped-slots) with the upcoming Composition API. I especially enjoyed the Vee-Validate v4 comparison. Check it out!

Vuetensils 0.6: Simpler Forms, Better Accessibility, & Useful Filters!
The latest version of Vuetensils has some really cool features: improvements to form authoring, accessibility updates, and new filters to make life easier.

[GitHub - vuejs/vitepress
](https://github.com/vuejs/vite...
[GitHub - Akryum/vue-mention
](https://github.com/Akryum/vue...
GitHub - alvarosaburido/vue-dynamic-forms

再谈vue3

尤大推出vue3 beta之后

🍁 🍄 🌾 💐 🌷 🌹 🥀 🌺 🌸 🌼 🌻
各位亲(づ ̄3 ̄)づ╭❤~,悠着点、悠着点。
🍁 🍄 🌾 💐 🌷 🌹 🥀 🌺 🌸 🌼 🌻

vue官方提供的尝鲜库:https://github.com/vuejs/comp...

迎接Vue3.0系列

👹 👺 💀 👻 👽 🤖

最新资讯-继续前进╰(°▽°)╯

天王盖地虎, 宝塔镇河妖

文章列表标题介绍
I_am_a_placeholder_placeholdernothing
为vue3学点typescript, 解读高级类型第一课, 体验typescript;
第二课, 基础类型和入门高级类型;
第三课, 泛型;
第四课, 解读高级类型;
第五课, 什么是命名空间(namespace);
Vue 3.0:更快、更小、让开发者更轻松在11月14日-16日于多伦多举办的 VueConf TO 2018 大会上,尤雨溪发表了名为 “ Vue 3.0 Updates ” 的主题演讲,对 Vue 3.0 的更新计划、方向进行了详细阐述。
Vue 3.0 前瞻,体验 Vue Function API最近 Vue 官方公布了 Vue 3.0 最重要的RFC:Function-based component API,并发布了兼容 Vue 2.0 版本的 plugin:vue-function-api,可用于提前体验 Vue 3.0 版本的 Function-based component API。笔者出于学习的目的,提前在项目中尝试了vue-function-api。
Vue 3.0 之前你必须知道的 TypeScript 实战技巧很多人对TypeScript的使用还停留在基本操作上,其实TypeScript的特性非常强大,我们利用好这些特性可以有效地提高代码质量、加速开发效率,今天就介绍9个非常实用的TypeScript技巧或者特性.
Vue CLI 3.x 与 2.x的区别cli3新增模式概念,每个模式在项目中都有对应的配置文件,项目启动时,对应的文件就会加载,与环境变量不同,一个模式可以包括多个环境变量。
Vue 3.0 RFC API 的实现Vue3.0 的 RFC 已经发布了几个月了,Vue 底层几乎没有变动,还是沿用原来响应式的。所以一直在思考能不能使用现在的版本,实现 RFC 中的 API,直到看到了 Vue Function API 这个库,这个库让开发者提前尝鲜到了RFC 中的 API,当然作为 RFC,所以最终 3.0 的 API 还是未知的,以及底层的实现也还未知。
Vue.js 3:面向未来编程(function-based API)如果你在使用 Vue.js,那么可能知道这个框架的第 3 版就要出来了(如果你是在本篇文章发布后的一段时间看到这段话的话,我希望我的说法还是中肯的😉)。新版本目前正在积极开发中,所以可能要加入的特性都可以在官方的 RFC(request for comments)仓库中看到:github.com/vuejs/rfcs 。其中有一个特性 function-api,将会在很大程度上影响我们未来 Vue 项目的编写方式。
来自 Vue 3.0 的 Composition API 尝鲜前段时间,Vue 官方释出了 Composition API RFC 的文档,我也在收到消息的第一时间上手尝鲜。虽然 Vue 3.0 尚未发布,但是其处于 RFC 阶段的 Composition API 已经可以通过插件 @vue/composition-api 进行体验了。接下来的内容我将以构建一个 TODO LIST 应用来体验 Composition API 的用法。
vue-cli 3.0脚手架,从入门到放弃(二)想写好代码,和用好一个工具是离不开的, 一般我们使用的工具有 HuilderX,sublimetext3,vscode,webstorm等,个人目前使用的是hb,和vscode,可以根据个人爱好各自选择,但一定要熟练。
vue-cli 3.0脚手架,从入门到放弃(三)来总结下流程, 从我们npm run serve 开始,打开 localhost:8080 端口,首先会加载index.html。然后去app.vue 里查找路由组件,这是会调动 router.js里的配置,选择首先要打开哪个文件,找到我们的那个 path:'/'的页面,浏览器显示。完成。

不要叫我达芬奇

2019.01-2019.07

十一月,天寒之时必封初冬

1、Vue CLI 3搭建vue+vuex 最全分析

介绍 Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统。有三个组件: CLI:@vue/cli 全局安装的 npm 包,提供了终端里的vue命令(如:vue create 、vue serve 、vue ui 等命令) CLI 服务:@vue/cli-service是一个开发环境依赖。

2、Vue.js 2 vs Vue.js 3的实现

vue.js核心团队已经讨论过将在Vue3实现的变化。虽然API不会改变,但是数据响应机制(译者注:对数据改变的监听和通知)发生了变化。这意味着什么呢,同时它对你意味着什么呢?

3、vue3.0快速创建项目

vue3.0使用了cli3快捷搭建的技巧和配搭

4、Vue.js 3.0 PPT(附部分中文翻译)

Evan You 刚刚发布了最新的 Vue 3 和他在 Vue Toronto 的演讲内容:

5、vue3.0初体验有哪些实用新功能

关于项目创建,除了命令创建3.x还增加了图形化界面创建以及管理vue项目
在创建新项目时还可以混合选用多种集成

6、Vue 3.0 的生命周期

ue 3.0 的生命周期多了哪些东西和其中又改变了什么

7、Vue-cli 3.0初体验

如今上Vue官网一看,脚手架都早已出3.0版了。唉,果然干这行一天不学习都感觉要落伍……

8、重磅!Vue CLI 3.0正式发布,带来多项重大更新

近日,Vue 的作者尤雨溪在 Medium 上宣布正式发布 Vue CLI 3.0,它也将为很多开发者带来期待已久的新特性。

9、译文:Vue.js 3.0 开发计划

在上周的 Vue.js 伦敦会议上我简短地透露了下个版本的 Vue 的新特性。这篇文章讲深入地阐述

10、Vue 下个版本的计划。Vue CLI 2&3 下的项目优化实践:CDN + Gzip + Prerender

这些优化方案适用于 Vue CLI 2 和 Vue CLI 3 , 文章主要基于 Vue CLI 2 进行介绍,关于如何在 Vue CLI 3 中进行相关的 webpack 调整,我已经放在了 vue-cli3-optimization 这个仓库下,并配有详细的注释,且额外添加方便 Sass 使用的 loader,使用 Sass 时无需再在每个需要引入变量和 mixin 的地方,每次都很麻烦的 @import。下面将详细介绍这些优化方案的实践方式和效果。

11、Vue CLI 3发布:精简配置,增加图形界面,还有这些新功能

不同的项目往往有不同的需求,所以webpack这种高可配的打包工具才会火起来,但同时也被骂太复杂了。所以很多人就想简化或者封装配置,例如facebook/create-react-app将所有的配置脚本封装为NPM软件包。

12、专访Vue作者尤雨溪:Vue CLI 3.0重构的原因

上个月,Vue CLI 3.0 正式发布,为很多开发者带来期待已久的新特性,尤雨溪也说 Vue CLI 3.0 经历了重构,旨在尽可能减少现代前端工具在配置上的烦恼,并尽可能在工具链中加入最佳实践,让其成为 Vue 应用程序的默认实践。为了获取更多细节,InfoQ 采访了尤雨溪,以下是对采访内容的整理。

13、重磅!尤雨溪发布Vue 3.0开发路线

在上周的 Vue.js 伦敦大会上,尤雨溪简要介绍了 Vue 下一个主要版本要发布的内容,9 月 30 日,尤雨溪在 medium 个人博客上发布了 Vue 3.0 的开发路线,全文如下

出处

Find the latest breaking √vue3 & vue-cli 3 News

查看原文

山山而川 关注了专栏 · 2020-11-02

进击的大前端

前端工程师,底层技术人。 思否2020年度“Top Writer”! 掘金“优秀作者”! 开源中国2020年度“优秀源创作者” 分享各种大前端进阶知识! 关注公众号【进击的大前端】第一时间获取高质量原创。 更多文章和示例源码请看:https://github.com/dennis-jiang/Front-End-Knowledges

关注 13740

山山而川 赞了文章 · 2020-10-19

10个必须知道的Chrome开发工具和技巧

作者:FelDev
译者:前端小智
来源:medium
点赞再看,微信搜索 【大迁世界】 关注这个没有大厂背景,但有着一股向上积极心态人。本文 GitHubhttps://github.com/qq44924588... 上已经收录,文章的已分类,也整理了很多我的文档,和教程资料。

大家都说简历没项目写,我就帮大家找了一个项目,还附赠【搭建教程】

1. 模拟慢速网络和慢速设备

我们可能习惯了在城市的网速,那是杠杠的,并不意味网速在中国哪个都一样的,在一些偏远地方,网速依然慢的可怜,所以有时候我们所做的产品是需要考虑网速慢的情况的,那怎么模拟呢?

打开谷个浏览器的performance选项卡,然后单击右上角的齿轮图标就可以看到 NewworkCPU的模拟情况。

clipboard.png

2. 颜色选择器

单击表示颜色的小方块,弹出颜色选择器。

clipboard.png

clipboard.png

启用颜色选择器后,可以将网页悬停并使用颜色选择器来获取该像素的颜色。

clipboard.png

clipboard.png

弹出颜色选择器的小方块还有快捷键按住Shift并单击以更改颜色格式。

3. Audits

Audits(审计),这个功能其实一直存在,只不过在chrome 60之后,发生了翻天覆地的变化:引入了Google开源的另外一个项目:LightHouse

Audits主要从5个方面来给网页打分,最终会生成一个report:

4.Pretty Print(显示可读代码)

clipboard.png

我们知道许多网站都对Javascript代码进行了压缩,但这对开发者和学习者来说,读起来很费劲,谷歌提供一个功能给我们,可以更好查看压缩文件。

我们点击下方的大括号{}图标,即可使用Pretty Print功能了

clipboard.png

5.快速文件切换器

如果你知道文件名,则不必打开“Sources”选项卡。只需按cmd/ctrl + p,然后输入你想查找的文件名,接下按下回车就 ok 了。

6. 响应模式

我们在桌面和移动设备上开发网站,通常我们倾向于最初的桌面体验。 但是这与越来越多的用户使用移动设备访问网络的趋势相脱离。 为了提高网站的用户体验,我们需要准确地知道网站在移动设备上的效果。 Chrome 开发者工具包里加入了手机模拟器特性,帮助我们测试:

clipboard.png

对于大多数人而言,大多数时间只需要通过不同的屏幕尺寸和方向查看他们的网站即可。

clipboard.png

大家都说简历没项目写,我就帮大家找了一个项目,还附赠【搭建教程】

我和阿里云合作服务器,折扣价比较便宜:89/年,223/3年,比学生9.9每月还便宜,买了搭建个项目,熟悉技术栈比较香(老用户用家人账号买就好了,我用我妈的)推荐买三年的划算点,点击本条就可以查看。

Icomo

7.屏幕截图

1、F12

2、【ctrl+shift+p】

3、输入“capture”

4、选择以下任意

  1. capture full size screenshot”【整个网页】
  2. capture node screenshot”【节点网页】
  3. “capture screenshot”【当前屏幕】

8. Extensions

我们可以将扩展程序安装到Chrome开发者控制台。 许多框架都有自己的扩展名,以简化其技术(Vue,Angular,React等)的开发。 这是Featured DevTools扩展的列表

9. Coverage

Coverage 是chrome开发者工具的一个新功能,从字面意思上可以知道它是可以用来检测代码在网站运行时有哪些js和css是已经在运行,而哪些js和css是还没有用到的,如图,这是我在打开csdn网页时,所显示的已运行和尚未运行的代码情况。

clipboard.png

如何打开caverage 前提:chrome浏览器的版本必须是59或以上,在ctrl+shift+i快速打开devtools,点击右上角的... More tools 有个Coverage。

那这个新功能有什么作用呢?

如上图所示,最右边显示的是我们加载的css和js文件数量,红色区域表示已运行的代码,而青色表示已加载但未运行的代码。可用来发现页面中尚未用到的js 和 css代码,你可以为用户只提供必要的代码,这样就可以提升页面的性能。这对于找出可以进行拆分的脚本以及延迟加载非关键脚本来说非常有用。

10. 实时跟进新功能

Chrome 的开发工具会不断更新,它会在What's New In DevTools 上发布更新的视频,我们可以时不是去看看,了解一些新出来的功能,这样我们就能实时知道谷歌的一些好用的功能了。


代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug

来源:https://medium.com/better-pro...


交流

文章每周持续更新,可以微信搜索「 大迁世界 」第一时间阅读和催更(比博客早一到两篇哟),本文 GitHub https://github.com/qq449245884/xiaozhi 已经收录,整理了很多我的文档,欢迎Star和完善,大家面试可以参照考点复习,另外关注公众号,后台回复福利,即可看到福利,你懂的。

查看原文

赞 18 收藏 15 评论 0

山山而川 赞了回答 · 2020-09-09

axios中怎么传数组

经过实验,axios的get方法中使用params时对于js数组类型的参数的默认操作比较诡异,会使得参数名后带上'[]'字符串,不得不说是基本反非PHP系后端的直觉了 /手动斜眼

而使用JSON.stringify()处理也不是那么好,会将参数变成字符串类型,例如原数组id为[1,2,3],这样处理后后端接受的就变为'id=[1,2,3]'了,可以解析,但对于使用某些框架自带解析的来说这简直是崩坏画风。

究其原因是axios对params的序列化采用的是qs库

因此可以使用qs自带的 arrayFormat 参数配置解决这个问题,大致配置如下:


// qs库应该是axios安装时会自带的

const qs = require('qs');

axios.get(url, {
    params:{
        arr: [1,2,3]
    },
    paramsSerializer: function(params) {
        return Qs.stringify(params, {arrayFormat: 'repeat'})
    }
})

这样后端获得参数就比较正常了,为'id=1&id=2&id=3'

参考文档:

  1. 知乎-axios get的params怎么传入数组
  2. 看云-Axios 中文说明

关注 8 回答 4

山山而川 收藏了文章 · 2020-07-29

Vue项目中出现Loading chunk {n} failed问题的解决方法

最近有个Vue项目中会偶尔出现Loading chunk {n} failed的报错,报错来自于webpack进行code spilt之后某些bundle文件lazy loading失败。但是这个问题的根本原因没有被找到,因为这个问题出现的偶然性太高了,而且有的手机上会出现,有的不会,用模拟器不会出现,用真机又会出现,不知道是网络原因还是webpack的bug。在github、stackoverflow等各种地方也找不到原因和解决方案,这是github上关于这个问题的讨论: Loading chunk {n} failed #742,虽然最后还是不了了之,但是大家可以参考一下。

这个问题出现概率比较小但是一旦出现就会导致页面崩溃,所以还是得解决,下面就贴出我的解决方案:

我的思路是既然找不到报错的原因那么尝试去捕获这个错误并做容错处理,有两种实现,一是在服务端捕获这个错误,一个是在前端捕获。

服务端实现

报错的原因是某些js bundle没有被找到,所以在服务端接收到获取该js文件的请求时先判断该js文件是否存在,如果存在直接返回js文件,如果不存在则返回一个提示信息给前端,让前端处理。假设服务端用express作为静态文件服务器,代码如下:

app.all(/\.js$/, (req, res) => {
    const fileName = req.path.slice(req.path.lastIndexOf('/') + 1);
    const filePath = path.resolve(__dirname, './public/static/js/' + fileName);
    if (fs.existsSync(filePath)) {
        fs.sendFile(filePath);
    } else {
        res.setHeader('Content-Type', 'application/javascript; charset=UTF-8')
        res.setHeader('Accept-Ranges', 'bytes')
        res.setHeader('Vary', 'Accept-Encoding')
        res.setHeader('Transfer-Encoding', 'chunked')
        res.setHeader('Last-Modified', new Date().toUTCString())
        res.setHeader('Cache-Control', 'no-cache')
        res.send('window.serverRebuildHook && window.serverRebuildHook();')
    }
});

当js文件未找到时,通过res.send('window.serverRebuildHook && window.serverRebuildHook();')向前端返回一条消息,并执行前端定义的serverRebuildHook方法。

接着我们在前端实现serverRebuildHook方法:

window.serverRebuildHook = function () {
  alert('服务器版本已更新,正在刷新本地缓存,请稍后...');
  location.replace(location.href);
}

方法很简单,提示一下用户服务端更新然后重新刷新当前页面。

这种实现是参考 github上的回答, 相对比较繁琐,而且用户体验并不好,只能刷新当前页面,不能跳转到目标页。

前端实现

由于项目里面用到了vue-router,vue-router的错误处理函数 onError 是不是能够捕获该错误呢?我们来看一下官方文档的说明:

image

当在渲染一个路由的过程中,需要尝试解析一个异步组件时发生错误。 完全符合我们场景,所以在onError方法中我们实现如下代码:

router.onError((error) => {
  const pattern = /Loading chunk (\d)+ failed/g;
  const isChunkLoadFailed = error.message.match(pattern);
  const targetPath = router.history.pending.fullPath;
  if (isChunkLoadFailed) {
    router.replace(targetPath);
  }
});

当捕获到Loading chunk {n} failed的错误时我们重新渲染目标页面,这种实现明显更简单和友好。

后续如果发现了导致Loading chunk {n} failed的本质原因会再更新本文,欢迎关注!

感谢大家阅读,另外,在这边帮朋友推一个爱心众筹,希望大家能够奉献点爱心,朋友母亲,身患直肠癌,目前在北京武警总医院接收治疗,可留言留下您的联系方式,日后感激大家!

clipboard.png

查看原文

山山而川 赞了文章 · 2020-07-29

Vue项目中出现Loading chunk {n} failed问题的解决方法

最近有个Vue项目中会偶尔出现Loading chunk {n} failed的报错,报错来自于webpack进行code spilt之后某些bundle文件lazy loading失败。但是这个问题的根本原因没有被找到,因为这个问题出现的偶然性太高了,而且有的手机上会出现,有的不会,用模拟器不会出现,用真机又会出现,不知道是网络原因还是webpack的bug。在github、stackoverflow等各种地方也找不到原因和解决方案,这是github上关于这个问题的讨论: Loading chunk {n} failed #742,虽然最后还是不了了之,但是大家可以参考一下。

这个问题出现概率比较小但是一旦出现就会导致页面崩溃,所以还是得解决,下面就贴出我的解决方案:

我的思路是既然找不到报错的原因那么尝试去捕获这个错误并做容错处理,有两种实现,一是在服务端捕获这个错误,一个是在前端捕获。

服务端实现

报错的原因是某些js bundle没有被找到,所以在服务端接收到获取该js文件的请求时先判断该js文件是否存在,如果存在直接返回js文件,如果不存在则返回一个提示信息给前端,让前端处理。假设服务端用express作为静态文件服务器,代码如下:

app.all(/\.js$/, (req, res) => {
    const fileName = req.path.slice(req.path.lastIndexOf('/') + 1);
    const filePath = path.resolve(__dirname, './public/static/js/' + fileName);
    if (fs.existsSync(filePath)) {
        fs.sendFile(filePath);
    } else {
        res.setHeader('Content-Type', 'application/javascript; charset=UTF-8')
        res.setHeader('Accept-Ranges', 'bytes')
        res.setHeader('Vary', 'Accept-Encoding')
        res.setHeader('Transfer-Encoding', 'chunked')
        res.setHeader('Last-Modified', new Date().toUTCString())
        res.setHeader('Cache-Control', 'no-cache')
        res.send('window.serverRebuildHook && window.serverRebuildHook();')
    }
});

当js文件未找到时,通过res.send('window.serverRebuildHook && window.serverRebuildHook();')向前端返回一条消息,并执行前端定义的serverRebuildHook方法。

接着我们在前端实现serverRebuildHook方法:

window.serverRebuildHook = function () {
  alert('服务器版本已更新,正在刷新本地缓存,请稍后...');
  location.replace(location.href);
}

方法很简单,提示一下用户服务端更新然后重新刷新当前页面。

这种实现是参考 github上的回答, 相对比较繁琐,而且用户体验并不好,只能刷新当前页面,不能跳转到目标页。

前端实现

由于项目里面用到了vue-router,vue-router的错误处理函数 onError 是不是能够捕获该错误呢?我们来看一下官方文档的说明:

image

当在渲染一个路由的过程中,需要尝试解析一个异步组件时发生错误。 完全符合我们场景,所以在onError方法中我们实现如下代码:

router.onError((error) => {
  const pattern = /Loading chunk (\d)+ failed/g;
  const isChunkLoadFailed = error.message.match(pattern);
  const targetPath = router.history.pending.fullPath;
  if (isChunkLoadFailed) {
    router.replace(targetPath);
  }
});

当捕获到Loading chunk {n} failed的错误时我们重新渲染目标页面,这种实现明显更简单和友好。

后续如果发现了导致Loading chunk {n} failed的本质原因会再更新本文,欢迎关注!

感谢大家阅读,另外,在这边帮朋友推一个爱心众筹,希望大家能够奉献点爱心,朋友母亲,身患直肠癌,目前在北京武警总医院接收治疗,可留言留下您的联系方式,日后感激大家!

clipboard.png

查看原文

赞 29 收藏 22 评论 30

山山而川 回答了问题 · 2020-07-24

解决vuecli3 使用externals 外部扩展后,运行有效果,可命令行报错找不到引入的模板?

问题已变通解决,没有引入模块,直接用window调用
image.png

关注 6 回答 6

山山而川 赞了回答 · 2020-06-09

解决node中跨域代理 proxyTable的原理是什么?

跨域是浏览器禁止的,服务端并不禁止跨域
所以浏览器可以发给自己的服务端然后,由自己的服务端再转发给要跨域的服务端,做一层代理
vue-cliproxyTable用的是http-proxy-middleware中间件
create-react-app用的是webpack-dev-server内部也是用的http-proxy-middleware
http-proxy-middleware内部用的http-proxy

关注 4 回答 2

山山而川 赞了文章 · 2019-12-10

Vue3.0 新特性全面探索 - 基于 Composition Api 快速构建实战项目

Quick Start

本项目综合运用了 Vue3.0 的新特性,适合新手学习😁

  • 基于 Composition APIFunction-based API 进行改造,配合 Vue Cli,优先体验 Vue3 特性
  • 使用单例对象模式进行组件通信
  • 使用 axios 库进行网络请求,weui 库实现 UI 界面
# 安装依赖
npm install
# 在浏览器打开localhost:8080查看页面,并实时热更新
npm run serve
# 发布项目
npm run build

建议配合 Visual Studio Code 和 Vue 3 Snippets 代码插件食用Ψ( ̄∀ ̄)Ψ。

Dependencies

以下是项目运用到的依赖,@vue/composition-api 配合 vue 模块让我们 Vue2.0 版本可以抢先体验 Vue3.0 的新特性,axios 是辅助我们发送网络请求得到数据的工具库,weui是一套与微信原生视觉一致的基础样式库,方便我们快速搭建项目页面。

"@vue/composition-api": "^0.3.4",
"axios": "^0.19.0",
"core-js": "^3.4.3",
"vue": "^2.6.10",
"weui": "^2.1.3"

Directory Structure

├── src
│   ├── App.vue                          # 组件入口
│   ├── assets                           # 资源目录
│   ├── stores/index.js                  # 状态管理
│   ├── components                       # 组件目录
│   │   ├── Header.vue                   # 头部组件
│   │   ├── Search.vue                   # 搜索框组件
│   │   ├── Panel.vue                    # 列表组件
│   ├── main.js                          # 项目入口
├── public                               # 模板文件
├── vue.config.js                        # 脚手架配置文件
├── screenshot                           # 程序截图

Composition API

npm install @vue/composition-api --save

使用 npm 命令下载了 @vue/composition-api 插件以后,引入该模块后,需要显式调用 Vue.use(VueCompositionApi) ,按照文档在 main.js 引用便开启了 Composition API 的能力。

// main.js
import Vue from 'vue'
import App from './App.vue'
// 1.引入Composition API模块
import VueCompositionApi from '@vue/composition-api'

Vue.config.productionTip = false
// 2.不要漏了显式调用 VueCompositionApi
Vue.use(VueCompositionApi)

new Vue({
  render: h => h(App),
}).$mount('#app')
npm install weui --save

我们同样使用 npm 安装 weui 模块,然后在 main.js 中引入 weui的基础样式库,方便我们可以在全局使用微信基础样式构建项目页面。

// main.js
import Vue from 'vue'
import App from './App.vue'
// 全局引入 `weui` 的基础样式库
import 'weui'
import VueCompositionApi from '@vue/composition-api'

Vue.config.productionTip = false
Vue.use(VueCompositionApi)

new Vue({
  render: h => h(App),
}).$mount('#app')

回到 App.vue,保留 components 属性值清空 <template> 模板的内容,删除 <style> 模板,等待重新引入新的组件。

<template>
  <div id="app">
    Hello World
  </div>
</template>
<script>
export default {
  name: "app",
  components: {}
};
</script>

src/components 目录下新建第一个组件,取名为 Header.vue 写入以下代码,点击查看源代码

<template>
  <header :style="{
    backgroundColor: color?color:defaultColor
  }">{{title}}</header>
</template>
<script>
import { reactive } from "@vue/composition-api";
export default {
  // 父组件传递进来更改该头部组件的属性值
  props: {
    // 标题
    title: String,
    // 颜色
    color: String
  },
  setup() {
    const state = reactive({
      defaultColor: "red"
    });
    return {
      ...state
    };
  }
};
</script>
<style scoped>
header {
  height: 50px;
  width: 100%;
  line-height: 50px;
  text-align: center;
  color: white;
}
</style>

setup

这里运用了一个全新的属性 setup ,这是一个组件的入口,让我们可以运用 Vue3.0 暴露的新接口,它运行在组件被实例化时候,props 属性被定义之后,实际上等价于 Vue2.0 版本的 beforeCreateCreated 这两个生命周期,setup 返回的是一个对象,里面的所有被返回的属性值,都会被合并到 Vue2.0render 渲染函数里面,在单文件组件中,它将配合 <template> 模板的内容,完成 ModelView 之间的绑定,在未来版本中应该还会支持返回 JSX 代码片段。

<template>
  <!-- View -->
  <div>{{name}}</div>
</template>
<script>
import { reactive } from '@vue/composition-api'
export default {
  setup() {
    const state = reactive({ name: 'Eno Yao' });
    // return 暴露到 template 中
    return {
      // Model
      ...state
    }
  }
}
</script>

reactive

setup 函数里面, 我们适应了 Vue3.0 的第一个新接口 reactive 它主要是处理你的对象让它经过 Proxy 的加工变为一个响应式的对象,类似于 Vue2.0 版本的 data 属性,需要注意的是加工后的对象跟原对象是不相等的,并且加工后的对象属于深度克隆的对象。

const state = reactive({ name: 'Eno Yao' })

props

Vue2.0 中我们可以使用 props 属性值完成父子通信,在这里我们需要定义 props 属性去定义接受值的类型,然后我们可以利用 setup 的第一个参数获取 props 使用。

export default {
  props: {
    // 标题
    title: String,
    // 颜色
    color: String
  },
  setup(props) {
    // 这里可以使用父组件传过来的 props 属性值
  }
};

我们在 App.vue 里面就可以使用该头部组件,有了上面的 props 我们可以根据传进来的值,让这个头部组件呈现不同的状态。

<template>
  <div id="app">
    <!-- 复用组件,并传入 props 值,让组件呈现对应的状态 -->
    <Header title="Eno" color="red" />
    <Header title="Yao" color="blue" />
    <Header title="Wscats" color="yellow" />
  </div>
</template>
<script>
import Header from "./components/Header.vue";
export default {
  name: "app",
  components: {
    Header,
  }
};
</script>

1.gif

context

setup 函数的第二个参数是一个上下文对象,这个上下文对象中包含了一些有用的属性,这些属性在 Vue2.0 中需要通过 this 才能访问到,在 vue3.0 中,访问他们变成以下形式:

setup(props, ctx) {
  console.log(ctx) // 在 setup() 函数中无法访问到 this
  console.log(this) // undefined
}

具体能访问到以下有用的属性:

  • root
  • parent
  • refs
  • attrs
  • listeners
  • isServer
  • ssrContext
  • emit

完成上面的 Header.vue 我们就编写 Search.vue 搜索框组件,继续再 src/components 文件夹下面新建 Search.vue 文件,点击查看源代码

<template>
  <div :class="['weui-search-bar', {'weui-search-bar_focusing' : isFocus}]" id="searchBar">
    <form class="weui-search-bar__form">
      <div class="weui-search-bar__box">
        <i class="weui-icon-search"></i>
        <input
          v-model="searchValue"
          ref="inputElement"
          type="search"
          class="weui-search-bar__input"
          id="searchInput"
          placeholder="搜索"
          required
        />
        <a href="javascript:" class="weui-icon-clear" id="searchClear"></a>
      </div>
      <label @click="toggle" class="weui-search-bar__label" id="searchText">
        <i class="weui-icon-search"></i>
        <span>搜索</span>
      </label>
    </form>
    <a @click="toggle" href="javascript:" class="weui-search-bar__cancel-btn" id="searchCancel">取消</a>
  </div>
</template>
<script>
import { reactive, toRefs, watch } from "@vue/composition-api";
import store from "../stores";
export default {
  // setup相当于2.x版本的beforeCreate生命周期
  setup() {
    // reactive() 函数接收一个普通对象,返回一个响应式的数据对象
    const state = reactive({
      searchValue: "",
      // 搜索框两个状态,聚焦和非聚焦
      isFocus: false,
      inputElement: null
    });
    // 切换搜索框状态的方法
    const toggle = () => {
      // 让点击搜索后出现的输入框自动聚焦
      state.inputElement.focus();
      state.isFocus = !state.isFocus;
    };
    // 监听搜索框的值
    watch(
      () => {
        return state.searchValue;
      },
      () => {
        // 存储输入框到状态 store 中心,用于组件通信
        store.setSearchValue(state.searchValue);
        // window.console.log(state.searchValue);
      }
    );
    return {
      // 将 state 上的每个属性,都转化为 ref 形式的响应式数据
      ...toRefs(state),
      toggle
    };
  }
};
</script>

toRefs

可以看到我们上面用了很多的新属性,我们先介绍 toRefs ,函数可以将 reactive() 创建出来的响应式对象,转换为普通的对象,只不过,这个对象上的每个属性节点,都是 ref() 类型的响应式数据,配合 v-model 指令能完成数据的双向绑定,在开发中非常高效。

import { reactive, toRefs } from "@vue/composition-api";
export default {
  setup() {
    const state = reactive({ name: 'Eno Yao' })
  }
  return {
    // 直接返回 state 那么数据会是非响应式的, MV 单向绑定
    // ...state,
    // toRefs 包装后返回 state 那么数据会是响应式的, MVVM 双向绑定
    ...toRefs(state),
  };
}

2.gif

template refs

这里的输入框拥有两个状态,一个是有输入框的状态和无输入框的状态,所以我们需要一个布尔值 isFocus 来控制状态,封装了一个 toggle 方法,让 isFocus 值切换真和假两个状态。

const toggle = () => {
  // isFocus 值取反
  state.isFocus = !state.isFocus;
};

然后配合 v-bind:class 指令,让 weui-search-bar_focusing 类名根据 isFocus 值决定是否出现,从而更改搜索框的状态。

<div :class="['weui-search-bar', {'weui-search-bar_focusing' : isFocus}]" id="searchBar">

这里的搜索输入框放入了 v-model 指令,用于接收用户的输入信息,方便后面配合列表组件执行检索逻辑,还放入了 ref 属性,用于获取该 <input/> 标签的元素节点,配合state.inputElement.focus() 原生方法,在切换搜索框状态的时候光标自动聚焦到输入框,增强用户体验。

<input
  v-model="searchValue"
  ref="inputElement"
/>

3.gif

watch

watch() 函数用来监视某些数据项的变化,从而触发某些特定的操作,使用之前还是需要按需导入,监听 searchValue 的变化,然后触发回调函数里面的逻辑,也就是监听用户输入的检索值,然后触发回调函数的逻辑把 searchValue 值存进我们创建 store 对象里面,方面后面和 Panel.vue 列表组件进行数据通信:

import { reactive, watch } from "@vue/composition-api";
import store from "../stores";
export default {
  setup() {
    const state = reactive({
      searchValue: "",
    });
    // 监听搜索框的值
    watch(
      () => {
        return state.searchValue;
      },
      () => {
        // 存储输入框到状态 store 中心,用于组件通信
        store.setSearchValue(state.searchValue);
      }
    );
    return {
      ...toRefs(state)
    };
  }
};

state management

在这里我们维护一份数据来实现共享状态管理,也就是说我们新建一个 store.js 暴露出一个 store 对象共享 PanelSearch 组件的 searchValue 值,当 Search.vue 组件从输入框接受到 searchValue 检索值,就放到 store.jsstore 对象中,然后把该对象注入到 Search 组件中,那么两个组件都可以共享 store 对象中的值,为了方便调试我们还分别封装了 setSearchValuegetSearchValue 来去操作该 store 对象,这样我们就可以跟踪状态的改变。

// store.js
export default {
    state: {
        searchValue: ""
    },
    // 设置搜索框的值
    setSearchValue(value) {
        this.state.searchValue = value
    },
    // 获取搜索框的值
    getSearchValue() {
        return this.state.searchValue
    }
}

完成上面的 Search.vue 我们紧接着编写 Panel.vue 搜索框组件,继续再 src/components 文件夹下面新建 Panel.vue 文件,点击查看源代码

<template>
  <div class="weui-panel weui-panel_access">
    <div v-for="(n,index) in newComputed" :key="index" class="weui-panel__bd">
      <a href="javascript:void(0);" class="weui-media-box weui-media-box_appmsg">
        <div class="weui-media-box__hd">
          <img class="weui-media-box__thumb" :data-original="n.author.avatar_url" alt />
        </div>
        <div class="weui-media-box__bd">
          <h4 class="weui-media-box__title" v-text="n.title"></h4>
          <p class="weui-media-box__desc" v-text="n.author.loginname"></p>
        </div>
      </a>
    </div>
    <div @click="loadMore" class="weui-panel__ft">
      <a href="javascript:void(0);" class="weui-cell weui-cell_access weui-cell_link">
        <div class="weui-cell__bd">查看更多</div>
        <span class="weui-cell__ft"></span>
      </a>
    </div>
  </div>
</template>
<script>
import { reactive, toRefs, onMounted, computed } from "@vue/composition-api";
import axios from "axios";
import store from "../stores";
export default {
  setup() {
    const state = reactive({
      // 页数
      page: 1,
      // 列表数据
      news: [],
      // 通过搜索框的值去筛选劣列表数据
      newComputed: computed(() => {
        // 判断是否输入框是否输入了筛选条件,如果没有返回原始的 news 数组
        if (store.state.searchValue) {
          return state.news.filter(item => {
            if (item.title.indexOf(store.state.searchValue) >= 0) {
              return item;
            }
          });
        } else {
          return state.news;
        }
      }),
      searchValue: store.state
    });
    // 发送 ajax 请求获取列表数据
    const loadMore = async () => {
      // 获取列表数据
      let data = await axios.get("https://cnodejs.org/api/v1/topics", {
        params: {
          // 每一页的主题数量
          limit: 10,
          // 页数
          page: state.page
        }
      });
      // 叠加页数
      state.page += 1;
      state.news = [...state.news, ...data.data.data];
    };
    onMounted(() => {
      // 首屏加载的时候触发请求
      loadMore();
    });
    return {
      // 让数据保持响应式
      ...toRefs(state),
      // 查看更多事件
      loadMore
    };
  }
};
</script>

lifecycle hooks

Vue3.0 的生命周期钩子和之前不一样,新版本都是以 onXxx() 函数注册使用,同样需要局部引入生命周期的对应模块:

import { onMounted, onUpdated, onUnmounted } from "@vue/composition-api";
export default {
  setup() {
    const loadMore = () => {};
    onMounted(() => {
      loadMore();
    });
    onUpdated(() => {
      console.log('updated!')
    })
    onUnmounted(() => {
      console.log('unmounted!')
    })
    return {
      loadMore
    };
  }
};

以下是新旧版本生命周期的对比:

  • <s>beforeCreate</s> -> use setup()
  • <s>created</s> -> use setup()
  • beforeMount -> onBeforeMount
  • mounted -> onMounted
  • beforeUpdate -> onBeforeUpdate
  • updated -> onUpdated
  • beforeDestroy -> onBeforeUnmount
  • destroyed -> onUnmounted
  • errorCaptured -> onErrorCaptured

同时新版本还提供了两个全新的生命周期帮助我们去调试代码:

  • onRenderTracked
  • onRenderTriggered

Panel 列表组件中,我们注册 onMounted 生命周期,并在里面触发请求方法 loadMore 以便从后端获取数据到数据层,这里我们使用的是 axios 网络请求库,所以我们需要安装该模块:

npm install axios --save

封装了一个请求列表数据方法,接口指向的是 Cnode 官网提供的 API ,由于 axios 返回的是 Promise ,所以配合 asyncawait 可以完美的编写异步逻辑,然后结合onMounted 生命周期触发,并将方法绑定到视图层的查看更多按钮上,就可以完成列表首次的加载和点击查看更多的懒加载功能。

// 发送 ajax 请求获取列表数据
const loadMore = async () => {
  // 获取列表数据
  let data = await axios.get("https://cnodejs.org/api/v1/topics", {
    params: {
      // 每一页的主题数量
      limit: 10,
      // 页数
      page: state.page
    }
  });
  // 叠加页数
  state.page += 1;
  // 合并列表数据
  state.news = [...state.news, ...data.data.data];
};
onMounted(() => {
  // 首屏加载的时候触发请求
  loadMore();
});

4.gif

computed

接下来我们就使用另外一个属性 computed 计算属性,跟 Vue2.0 的使用方式很相近,同样需要按需导入该模块:

import { computed } from '@vue/composition-api';

计算属性分两种,只读计算属性和可读可写计算属性:

// 只读计算属性
let newsComputed = computed(() => news.value + 1)
// 可读可写
let newsComputed = computed({
  // 取值函数
  get: () => news.value + 2,
  // 赋值函数
  set: val => {
    news.value = news.value - 3
  }
})

5.gif

这里我们使用可读可写计算属性去处理列表数据,还记得我们上一个组件 Search.vue 吗,我们可以结合用户在搜索框输入的检索值,配合 computed 计算属性来筛选对我们用户有用列表数据,所以我们首先从 store 的共享实例里面拿到 Search.vue 搜索框共享的 searchValue ,然后利用原生字符串方法 indexOf 和 数组方法 filter 来过滤列表的数据,然后重新返回新的列表数据 newsComputed,并在视图层上配合 v-for 指令去渲染新的列表数据,这样做既可以在没搜索框检索值的时候返回原列表数据 news ,而在有搜索框检索值的时候返回新列表数据 newsComputed

import store from "../stores";
export default {
  setup() {
    const state = reactive({
      // 原列表数据
      news: [],
      // 通过搜索框的值去筛选后的新列表数据
      newsComputed: computed(() => {
        // 判断是否输入框是否输入了筛选条件,如果没有返回原始的 news 数组
        if (store.state.searchValue) {
          return state.news.filter(item => {
            if (item.title.indexOf(store.state.searchValue) >= 0) {
              return item;
            }
          });
        } else {
          return state.news;
        }
      }),
      searchValue: store.state
    });
  }
}

项目源码

如果文章和笔记能带您一丝帮助或者启发,请不要吝啬你的赞和 Star,你的肯定是我前进的最大动力😁

查看原文

赞 24 收藏 17 评论 0

山山而川 关注了问题 · 2019-11-01

解决el-table本地搜索相关,一言难尽,求助!

场景:表格数据太多,采用搜索,表格属于可选的(可选是重点)

问题描述:后端搜索后表格对象会替换地址,导致上一次搜索选中的项没了,接着尝试本地搜索,由于Element-UI的table无法直接操作一行的显隐,所以只能操作替换数据,又绕回来了,怎么做都要改变地址,改变地址就不可能保留上一次的选择,思路求解啊!!

总结:Element-UI表格,不能控制哪一行隐藏,所以只能控制数据的增删,但是直接操作数据会导致对象地址更改,上一次操作的对象没了

br
br

注:强行保存上次选中为保底方案

关注 2 回答 1

认证与成就

  • 获得 1 次点赞
  • 获得 6 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 6 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2019-09-26
个人主页被 273 人浏览