Open sunmaobin opened 3 years ago
Vue.js 是 渐进式 的 JavaScript 框架。什么是 渐进式(Progressive) ?就是由浅入深,一步一步的,为什么 Evan You 说 Vue.js 是渐进式的框架呢?
渐进式
Vue.js 有啥特点呢?
当然,如果想更全面的了解 Vue,对比 React 和 Angular 等框架,可以看看这里的 横向对比
参考资料:cn.vuejs.org/v2/guide/
Vue2.x
Vue 自诞生开始,每一个大版本都在进步,相比 Vue1.x 而言,我们现在使用的 Vue 2.x 效果:
Vue1.x
Vue 2.x
更小
更快
支持SSR 和 原生渲染
参考资料:juejin.im/entry/68449…
Vue3.x
相比 Vue2.x 而言,Vue3.x 的设计目标:
参考资料:img.w3ctech.com/VueConf2019…
Evan You 为什么制定 Vue3.x 的这些目标呢?可能大家要先了解下 Vue2.x 的现状。
总体一个观点:众口难调!
众口难调!
总体一个原则:没有绝对好的框架,也没有绝对差的框架。每个人还是从各方面(自身技术能力、团队技术基础、上手成本、项目特点)考虑,选择一款适合自己的框架为好。
以下是 Evan You 对 Vue 和 React 对比的自我评价:
了解详情:www.zhihu.com/question/30…
One more thing
补充一点 Evan you 对 Vue 和 Angular 对比的自我评价:
了解详情:www.zhihu.com/question/40…
总体评价:Vue2.x 支持显然跟 React 和 Angular 是有差距的。
以下是 Evan You 对 Ts 的自我评价:
了解详情:www.zhihu.com/question/31…
另外 Evan You 当初为什么选择使用 Flow ,而不是直接上 Ts ?
Flow
Ts
看这里:www.zhihu.com/question/46…
首先来看看知乎上的一个帖子,大家讨论的热火朝天:为什么react比vue更适合大型应用?
在我之前的面试中,当问到如何看待 React 和 Vue 这2个框架的时候,也有不少的人的回答是:Vue 适合中小项目,React 适合大型项目!
Vue 适合中小项目,React 适合大型项目!
其实,在回答这个问题之前,大家首先得弄明白 “什么是中小项目?什么是大型项目?” 如果这个标准不统一,那大家争论是没有意义的。
就好比,什么是大前端?什么是前端工程化?这是我的理解
其实业界也没有太多定义,以下是个人观点(欢迎指正),大型项目满足其一就行:
1000w
100人
500个
10w行
除此之外,都应该算作中小项目。
如果按照以上标准划分大中小型项目的话,大家平时有机会接触到的大项目有多少呢?
更何况,为了降低风险,除非无法拆分,不然一般公司里面大型项目也会被拆分成多个中小项目落地。所以,我要说的是,大家没必要从这个角度来划分一个前端框架,意义不大。
只是从人们的认知里面,一般认为的大型项目会出现以下问题,比如:
好了,其实按我的理解,与其说是用项目大小来决定该选择哪个框架,不如从自身遇到问题出发衡量下适合自己的框架,因为以上问题不止大型项目的问题,所有项目都可能会遇到。
Vue setup 的思路借鉴了 React hooks 的灵感,同时也解决了 hooks 存在的上面的问题。
参考资料:vue-composition-api-rfc.netlify.com/#comparison…
简单对比下 React 和 Vue(个人理解和翻阅相关资料,欢迎批量指正,不引战!轻点喷!):
经过了上面各种对比,我们回过头来再看看 Vue3.x 改进:
这其实是由完全面向对象OOP的思路,到函数式编程的思想转变。
只不过说起函数式编程大家看看文档可能都知道概念,无非业务逻辑都是一个个函数实现嘛!但是,真让你在项目里自由发挥写那么多函数的时候,你该怎么写?(这可能也是大家觉得 React 不太容易上手的以一个缘故吧,喜欢被 Vue 安排的明明白白!)
于是结合着 Vue2.x 里面的 Options API,将以前完全按照AOP模式的Options API,细粒度拆分成细小的函数,然后统一放到 setup 这一个入口函数中调用!鸡贼!佩服!
setup
这样做的3个好处:
tree-shaking
可谓:一石三鸟!
一石三鸟
下面以示例的形式来解释下这个概念。
比如 Vue2.x 时对于一个独立组件:
开始只有简单的鼠标处理逻辑。
export default { data() { return { x: 0, y: 0 } }, mounted() { window.addEventListener('mousemove', this.update) }, methods: { update(e) { this.x = e.pageX this.y = e.pageY } }, destroyed() { window.removeEventListener('mousemove', this.update) } } 复制代码
以上会存在什么问题呢?举例来说明:
随着时间的推移,这个组件可能会发展成如下的模样!
export default { data() { return { x: 0, y: 0, a: 0, b: 0, c: 0, d: 0, e: 0, f: 0, g: 0, h: 0, i: 0, j: 0, k: 0, l: 0, m: 0, n: 0 // 算了写不下去了。。。总之 data 可能会有很多 } }, mixins: [ a, b, c, d, e, f // 算了,写不下去了,总之为了拆分代码,mixins 已经让我写到吐了 ], mounted() { window.addEventListener('mousemove', this.update) // TODO 接下来可能会有一堆页面渲染完成的逻辑在这里哦 // 这里是业务逻辑1 // if / else if / else // 下面是业务逻辑2 // while // 哎呀所有的事情,都需要在页面渲染完去做呀,没办法 // switch // 算了,写不下去了。。。 // 跑路。。。 }, methods: { update(e) { this.x = e.pageX this.y = e.pageY }, // 下面有一堆方法等着你哦 method1() { // 预留着,方法只能放到 methods 对象下啊 }, method2() { // 张三的注释 // 一堆逻辑 }, method3() { // ... 跑路了。。。 } }, destroyed() { window.removeEventListener('mousemove', this.update) } } 复制代码
大家看出来上面的代码的问题了么?因为大家必须在 Vue 规定的条条框框里面写东西,所以,尤其初学者,会把一个简单的组件,写到简直无法直视的地步!
那你可能要说了,以上代码是有很多解决办法的呀,比如下面2种常见的优化方案:
1、将这个文件拆分成多个子组件或者模块
比如:如果按模块拆分,可以把 data 拆分成一个js文件,methods 拆分成一个 js 文件,等等。这么做只是相当于把一堆代码打散而已,代码连贯性、可维护性方面,变得更糟了。
data
methods
再比如:拆分成多个子组件,每个子组件实现一块逻辑!(这是强拆!)大家拆分组件的原则,肯定不是基于代码量去拆的吧!所以,这会让业务模块,变得支离破碎,难以理解和维护。
2、使用 mixins 提取公共代码
mixins
mixins 解决的是公共的代码混入复用,如果只是一个组件过于庞大,你拆分到 mixins 多个文件中,有啥意义呢?跟上面的强拆有啥区别?
更何况,即便有复用的代码,如果一个文件中引入 10个以上的 mixin 文件,里面的 data 可能会覆盖,methods 可能会覆盖,你知道哪个生效了?template 使用的变量,你知道来自哪里?
对于上面的示例,Vue3.x 的解决办法
定义独立文件 mouse.js
mouse.js
这个文件就只处理鼠标事件!业务和代码逻辑都在一起,好理解,易于维护。
import { ref, onMounted, onUnmounted } from 'vue' export function useMousePosition() { const x = ref(0) const y = ref(0) function update(e) { x.value = e.pageX y.value = e.pageY } onMounted(() => { window.addEventListener('mousemove', update) }) onUnmounted(() => { window.removeEventListener('mousemove', update) }) return { x, y } } 复制代码
main.vue 引入文件
main.vue
这里的代码量也变的很少,很清晰。
import { useMousePosition } from './mouse' export default { setup() { const { x, y } = useMousePosition() // other logic... return { x, y } } } 复制代码
示例参考:vue-composition-api-rfc.netlify.com/#logic-extr…
如果遇到不同的业务模块,就单独到独立文件或者模块处理,然后引入即可,比如:
(下面的逻辑如果在 vue2.x 中还真不太好处理!)
export default { setup () { // Network const { networkState } = useNetworkState() // Folder const { folders, currentFolderData } = useCurrentFolderData(networkState) const folderNavigation = useFolderNavigation({ networkState, currentFolderData }) const { favoriteFolders, toggleFavorite } = useFavoriteFolders(currentFolderData) const { showHiddenFolders } = useHiddenFolders() const createFolder = useCreateFolder(folderNavigation.openFolder) // Current working directory resetCwdOnLeave() const { updateOnCwdChanged } = useCwdUtils() // Utils const { slicePath } = usePathUtils() return { networkState, folders, currentFolderData, folderNavigation, favoriteFolders, toggleFavorite, showHiddenFolders, createFolder, updateOnCwdChanged, slicePath } } } 复制代码
参考代码:vue-composition-api-rfc.netlify.com/#code-organ…
看了以上代码有啥感想?我自己的感受:
Vue2.x 写法:
import { Component, Prop, Vue } from 'vue-property-decorator' @Component export default class HelloWorld extends Vue { @Prop() private message!: string; data (): object { // this.message } } 复制代码
Vue3.x 写法:
import { defineComponent } from 'vue' export default defineComponent({ props: { message: String }, setup(props, context) { // setup 中无法使用 this 关键词 // props.message // context.attrs // context.slots // context.emit } }) 复制代码
对比下,至少写法上更简单,而且不用在使用那么多的 装饰器 了!
装饰器
再回过头来看看 Evan You 对 Vue3.x 的目标定义:
上文已说明
对比了 vue@3.0.0-alpha.8 和 vue@2.6.11 这2个版本的未压缩版本的文件大小:
vue@3.0.0-alpha.8
vue@2.6.11
单纯从这2个独立的版本看,3.0还变大了!
所以,个人认为,真正要能变小,可能还是要放到工程化体系中,依赖编译器,比如:webpack,然后基于 3.0 这种函数式编程更好 tree shaking 的机制,最终打包编译后的效果而言。
Vue3.x 以下重大变化:
Object.defineProperty()
new Proxy()
参考地址:img.w3ctech.com/VueConf2019…
理论上性能上肯定要比之前好(至少 Proxy 就更高效一些),但是这个目前还不好验证,相信正式 Release 后续官方也会给出一些数据,同时圈内肯定也会有很多测试结果出炉。
开放更多底层功能
我觉得应该就是 API 更完善一些吧,比如:
Vue3.x 的生命周期新增了2个 Debug Hooks(用于调试的钩子函数):
参考:vue-composition-api-rfc.netlify.com/api.html#li…
更多的等后面在仔细梳理。
(本文完)
1 Vue 回顾
Vue.js 是
渐进式
的 JavaScript 框架。什么是渐进式
(Progressive) ?就是由浅入深,一步一步的,为什么 Evan You 说 Vue.js 是渐进式的框架呢?Vue.js 有啥特点呢?
当然,如果想更全面的了解 Vue,对比 React 和 Angular 等框架,可以看看这里的 横向对比
参考资料:cn.vuejs.org/v2/guide/
Vue2.x
Vue 自诞生开始,每一个大版本都在进步,相比
Vue1.x
而言,我们现在使用的Vue 2.x
效果:更小
,vue、vue-router 和 vuex 三个加一起,跟 Vue1.0 的核心库大小一样更快
,基本是当前最快的框架,查看测试对比支持SSR 和 原生渲染
参考资料:juejin.im/entry/68449…
Vue3.x
相比
Vue2.x
而言,Vue3.x
的设计目标:参考资料:img.w3ctech.com/VueConf2019…
Evan You 为什么制定
Vue3.x
的这些目标呢?可能大家要先了解下Vue2.x
的现状。2 Vue 和 React 逃不掉的话题
2.1 Vue 和 React 哪个更好?
总体一个观点:
众口难调!
总体一个原则:没有绝对好的框架,也没有绝对差的框架。每个人还是从各方面(自身技术能力、团队技术基础、上手成本、项目特点)考虑,选择一款适合自己的框架为好。
以下是 Evan You 对 Vue 和 React 对比的自我评价:
了解详情:www.zhihu.com/question/30…
补充一点 Evan you 对 Vue 和 Angular 对比的自我评价:
了解详情:www.zhihu.com/question/40…
2.2 Vue 对于 Ts 的支持不够友好?
总体评价:Vue2.x 支持显然跟 React 和 Angular 是有差距的。
以下是 Evan You 对 Ts 的自我评价:
了解详情:www.zhihu.com/question/31…
另外 Evan You 当初为什么选择使用
Flow
,而不是直接上Ts
?看这里:www.zhihu.com/question/46…
2.3 Vue 更适合中小项目?
首先来看看知乎上的一个帖子,大家讨论的热火朝天:为什么react比vue更适合大型应用?
在我之前的面试中,当问到如何看待 React 和 Vue 这2个框架的时候,也有不少的人的回答是:
Vue 适合中小项目,React 适合大型项目!
其实,在回答这个问题之前,大家首先得弄明白 “什么是中小项目?什么是大型项目?” 如果这个标准不统一,那大家争论是没有意义的。
就好比,什么是大前端?什么是前端工程化?这是我的理解
其实业界也没有太多定义,以下是个人观点(欢迎指正),大型项目满足其一就行:
1000w
的100人
的500个
的10w行
的除此之外,都应该算作中小项目。
如果按照以上标准划分大中小型项目的话,大家平时有机会接触到的大项目有多少呢?
更何况,为了降低风险,除非无法拆分,不然一般公司里面大型项目也会被拆分成多个中小项目落地。所以,我要说的是,大家没必要从这个角度来划分一个前端框架,意义不大。
只是从人们的认知里面,一般认为的大型项目会出现以下问题,比如:
好了,其实按我的理解,与其说是用项目大小来决定该选择哪个框架,不如从自身遇到问题出发衡量下适合自己的框架,因为以上问题不止大型项目的问题,所有项目都可能会遇到。
2.4 Vue3.x setup 和 React hooks 对比
Vue setup 的思路借鉴了 React hooks 的灵感,同时也解决了 hooks 存在的上面的问题。
参考资料:vue-composition-api-rfc.netlify.com/#comparison…
2.5 个人观点 React 对比 Vue
简单对比下 React 和 Vue(个人理解和翻阅相关资料,欢迎批量指正,不引战!轻点喷!):
Vue3.x
的发布,答案就明了(下文会说)!Vue2.x
时代的时候,肯定有一些大的团队会优先考虑稳定性,毕竟历史上烂尾的例子太多了(近在眼前的 Flow 不就是么?偷笑)。关于 Vue3.x
经过了上面各种对比,我们回过头来再看看 Vue3.x 改进:
3.1 Options API 到 Composition API 的转变
这其实是由完全面向对象OOP的思路,到函数式编程的思想转变。
只不过说起函数式编程大家看看文档可能都知道概念,无非业务逻辑都是一个个函数实现嘛!但是,真让你在项目里自由发挥写那么多函数的时候,你该怎么写?(这可能也是大家觉得 React 不太容易上手的以一个缘故吧,喜欢被 Vue 安排的明明白白!)
于是结合着 Vue2.x 里面的 Options API,将以前完全按照AOP模式的Options API,细粒度拆分成细小的函数,然后统一放到
setup
这一个入口函数中调用!鸡贼!佩服!这样做的3个好处:
Vue2.x
中各个函数的功能,做到兼容tree-shaking
可谓:
一石三鸟
!下面以示例的形式来解释下这个概念。
比如 Vue2.x 时对于一个独立组件:
开始只有简单的鼠标处理逻辑。
以上会存在什么问题呢?举例来说明:
随着时间的推移,这个组件可能会发展成如下的模样!
大家看出来上面的代码的问题了么?因为大家必须在 Vue 规定的条条框框里面写东西,所以,尤其初学者,会把一个简单的组件,写到简直无法直视的地步!
那你可能要说了,以上代码是有很多解决办法的呀,比如下面2种常见的优化方案:
1、将这个文件拆分成多个子组件或者模块
比如:如果按模块拆分,可以把
data
拆分成一个js文件,methods
拆分成一个 js 文件,等等。这么做只是相当于把一堆代码打散而已,代码连贯性、可维护性方面,变得更糟了。再比如:拆分成多个子组件,每个子组件实现一块逻辑!(这是强拆!)大家拆分组件的原则,肯定不是基于代码量去拆的吧!所以,这会让业务模块,变得支离破碎,难以理解和维护。
2、使用
mixins
提取公共代码mixins
解决的是公共的代码混入复用,如果只是一个组件过于庞大,你拆分到 mixins 多个文件中,有啥意义呢?跟上面的强拆有啥区别?更何况,即便有复用的代码,如果一个文件中引入 10个以上的 mixin 文件,里面的 data 可能会覆盖,methods 可能会覆盖,你知道哪个生效了?template 使用的变量,你知道来自哪里?
对于上面的示例,Vue3.x 的解决办法
定义独立文件
mouse.js
这个文件就只处理鼠标事件!业务和代码逻辑都在一起,好理解,易于维护。
main.vue
引入文件这里的代码量也变的很少,很清晰。
示例参考:vue-composition-api-rfc.netlify.com/#logic-extr…
如果遇到不同的业务模块,就单独到独立文件或者模块处理,然后引入即可,比如:
(下面的逻辑如果在 vue2.x 中还真不太好处理!)
参考代码:vue-composition-api-rfc.netlify.com/#code-organ…
看了以上代码有啥感想?我自己的感受:
3.2 更好的支持 Ts
Vue2.x 写法:
Vue3.x 写法:
对比下,至少写法上更简单,而且不用在使用那么多的
装饰器
了!3.3 其他
再回过头来看看 Evan You 对 Vue3.x 的目标定义:
上文已说明
上文已说明
上文已说明
更小
对比了
vue@3.0.0-alpha.8
和vue@2.6.11
这2个版本的未压缩版本的文件大小:单纯从这2个独立的版本看,3.0还变大了!
所以,个人认为,真正要能变小,可能还是要放到工程化体系中,依赖编译器,比如:webpack,然后基于 3.0 这种函数式编程更好 tree shaking 的机制,最终打包编译后的效果而言。
更快
Vue3.x 以下重大变化:
Object.defineProperty()
换成了new Proxy()
参考地址:img.w3ctech.com/VueConf2019…
理论上性能上肯定要比之前好(至少 Proxy 就更高效一些),但是这个目前还不好验证,相信正式 Release 后续官方也会给出一些数据,同时圈内肯定也会有很多测试结果出炉。
开放更多底层功能
我觉得应该就是 API 更完善一些吧,比如:
Vue3.x 的生命周期新增了2个 Debug Hooks(用于调试的钩子函数):
参考:vue-composition-api-rfc.netlify.com/api.html#li…
更多的等后面在仔细梳理。
(本文完)