Vue.js 是 渐进式
的 JavaScript 框架。什么是 渐进式
(Progressive) ?就是由浅入深,一步一步的,为何 Evan You 说 Vue.js 是渐进式的框架呢?javascript
Vue.js 有啥特色呢?html
固然,若是想更全面的了解 Vue,对比 React 和 Angular 等框架,能够看看这里的 横向对比前端
参考资料:cn.vuejs.org/v2/guide/vue
Vue2.xjava
Vue 自诞生开始,每个大版本都在进步,相比 Vue1.x
而言,咱们如今使用的 Vue 2.x
效果:react
更小
,vue、vue-router 和 vuex 三个加一块儿,跟 Vue1.0 的核心库大小同样更快
,基本是当前最快的框架,查看测试对比支持SSR 和 原生渲染
参考资料:juejin.im/entry/58102…webpack
Vue3.xgit
相比 Vue2.x
而言,Vue3.x
的设计目标:github
参考资料:img.w3ctech.com/VueConf2019…web
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…
One more thing
另外 Evan You 当初为何选择使用 Flow
,而不是直接上 Ts
?
看这里:www.zhihu.com/question/46…
首先来看看知乎上的一个帖子,你们讨论的热火朝天:为何react比vue更适合大型应用?
在我以前的面试中,当问到如何看待 React 和 Vue 这2个框架的时候,也有很多的人的回答是:Vue 适合中小项目,React 适合大型项目!
其实,在回答这个问题以前,你们首先得弄明白 “什么是中小项目?什么是大型项目?” 若是这个标准不统一,那你们争论是没有意义的。
就比如,什么是大前端?什么是前端工程化?这是个人理解
其实业界也没有太多定义,如下是我的观点(欢迎指正),大型项目知足其一就行:
1000w
的100人
的500个
的10w行
的除此以外,都应该算做中小项目。
若是按照以上标准划分大中小型项目的话,你们平时有机会接触到的大项目有多少呢?
更况且,为了下降风险,除非没法拆分,否则通常公司里面大型项目也会被拆分红多个中小项目落地。因此,我要说的是,你们不必从这个角度来划分一个前端框架,意义不大。
只是从人们的认知里面,通常认为的大型项目会出现如下问题,好比:
好了,其实按个人理解,与其说是用项目大小来决定该选择哪一个框架,不如从自身遇到问题出发衡量下适合本身的框架,由于以上问题不止大型项目的问题,全部项目均可能会遇到。
Vue setup 的思路借鉴了 React hooks 的灵感,同时也解决了 hooks 存在的上面的问题。
参考资料:vue-composition-api-rfc.netlify.com/#comparison…
简单对比下 React 和 Vue(我的理解和翻阅相关资料,欢迎批量指正,不引战!轻点喷!):
Vue3.x
的发布,答案就明了(下文会说)!Vue2.x
时代的时候,确定有一些大的团队会优先考虑稳定性,毕竟历史上烂尾的例子太多了(近在眼前的 Flow 不就是么?偷笑)。通过了上面各类对比,咱们回过头来再看看 Vue3.x 改进:
这实际上是由彻底面向对象OOP的思路,到函数式编程的思想转变。
只不过提及函数式编程你们看看文档可能都知道概念,无非业务逻辑都是一个个函数实现嘛!可是,真让你在项目里自由发挥写那么多函数的时候,你该怎么写?(这可能也是你们以为 React 不太容易上手的以一个缘故吧,喜欢被 Vue 安排的明明白白!)
因而结合着 Vue2.x 里面的 Options API,将之前彻底按照AOP模式的Options API,细粒度拆分红细小的函数,而后统一放到 setup
这一个入口函数中调用!鸡贼!佩服!
这样作的3个好处:
Vue2.x
中各个函数的功能,作到兼容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种常见的优化方案:
一、将这个文件拆分红多个子组件或者模块
好比:若是按模块拆分,能够把 data
拆分红一个js文件,methods
拆分红一个 js 文件,等等。这么作只是至关于把一堆代码打散而已,代码连贯性、可维护性方面,变得更糟了。
再好比:拆分红多个子组件,每一个子组件实现一块逻辑!(这是强拆!)你们拆分组件的原则,确定不是基于代码量去拆的吧!因此,这会让业务模块,变得支离破碎,难以理解和维护。
二、使用 mixins
提取公共代码
mixins
解决的是公共的代码混入复用,若是只是一个组件过于庞大,你拆分到 mixins 多个文件中,有啥意义呢?跟上面的强拆有啥区别?
更况且,即使有复用的代码,若是一个文件中引入 10个以上的 mixin 文件,里面的 data 可能会覆盖,methods 可能会覆盖,你知道哪一个生效了?template 使用的变量,你知道来自哪里?
对于上面的示例,Vue3.x 的解决办法
定义独立文件 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
引入文件
这里的代码量也变的不多,很清晰。
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个版本的未压缩版本的文件大小:
单纯从这2个独立的版本看,3.0还变大了!
因此,我的认为,真正要能变小,可能仍是要放到工程化体系中,依赖编译器,好比:webpack,而后基于 3.0 这种函数式编程更好 tree shaking 的机制,最终打包编译后的效果而言。
更快
Vue3.x 如下重大变化:
Object.defineProperty()
换成了 new Proxy()
参考地址:img.w3ctech.com/VueConf2019…
理论上性能上确定要比以前好(至少 Proxy 就更高效一些),可是这个目前还很差验证,相信正式 Release 后续官方也会给出一些数据,同时圈内确定也会有不少测试结果出炉。
开放更多底层功能
这个目前还不太清楚,等官方出炉吧。
(本文完)