文档传送门
https://vue.w3ctech.com/
尤雨溪vue3有关演讲
回顾
1. 为什么还没发布
因为ie11不支持proxy且市场占有率还不低,发布早了这个功能其实很多人很难用得到
2. vue3的目标
更快(vdom优化)和ts更好支持是两个主要目标
vdom优化
传统vdom的性能瓶颈
- 虽然 Vue 能够保证触发更新的组件最小化,但在单个组件内部依然需要遍历该
组件的整个 vdom 树 - 传统 vdom 的性能跟模版大小正相关,跟动态节点的数量无关。在一些组件整个
模版内只有少量动态节点的情况下,这些遍历都是性能的浪费 - 传统vdom为啥要那么做?因为JSX 和手写的 render function 是完全动态的,过度的灵活性导致运行时可以用于优化的信息不足(react是通过时间分片来解决这个问题)
- 而如果使用模板template来编译成vdom,就可以有更多信息提供给引擎优化
- vue3认为,如果编译足够快,不需要通过类似时间分片去弥补动态渲染的性能瓶颈问题
- 另一个极致的实现是某些框架SVELTE不用vdom,而是直接用静态模板去编译,实现运行时更快
vue并不抛弃vdom
vue并不会走这种极端,因为:
- jsx和render等比模板更底层的方法能够实现比模板更复杂的功能
- 生成代码更简洁(对比静态模板,有时候生成代码量很大,尽管运行时很“轻”)
- vue2兼容
vue特有的
- 底层是 Virtual DOM
- 上层有包含大量静态信息的模版
vue3目标
- 兼容手写 render function
- 最大化利用模版静态信息
如何最大化的动静结合?
新的策略:
- 将模版基于动态节点指令切割为嵌套的区块
- 每个区块内部的节点结构是固定的
- 每个区块只需要以一个 Array 追踪自身包含的动态节点
因为遍历是耗时的,新策略将 vdom 更新性能由与模版整体大小相关提升为与动态内容的数量相关
Typescript
为什么撤销了class API
- 原本的目的是更好的ts支持
Props 和其它需要注入到 this 的属性导致类型声明依然存在问题 - 类型支持外没太大的优势,除了似乎用了原生api
写UI组件时更多是组合逻辑,而不是OOP的继承的逻辑,所以Vue有更好的选择
Function-based API
代码形式
const App = {
setup() {
// data
const count = value(0)
// computed
const plusOne = computed(() => count.value + 1)
// method
const increment = () => { count.value++ }
// watch
watch(() => count.value * 2, v => console.log(v))
// lifecycle
onMounted(() => console.log('mounted!'))
// 暴露给模版或渲染函数
return { count }
}
}
把vue实例的选项全部放入setup函数,value表示包装类型,使得能够count.value这样使用,等于对vue的很大改动
funtion-base API优点
对比 Class API
- 更好的 TypeScript 类型推导支持
ts对对象的推到不如对函数推导,上面的代码形式更容易被ts推导 - 更灵活的逻辑复用能力
都放在函数中了,因此函数调用比组件调用更灵活 - Tree-shaking 友好
原来的形式导致没有数据也会编译出data methods之类的选项,新的形式如果没使用就会去掉该选项,使得vue代码大小与使用的功能正相关 - 代码更容易被压缩
function的参数可以被压缩为单个字母,但对象的内容一般是不压缩的
逻辑复用案例-鼠标位置侦听
可以有以下方法:
1. mixin
- 命名空间冲突
- 版数据来源不清晰
2. 高阶组件(Higher-order Components)
- props 命名空间冲突
- props 来源不清晰
- 额外的组件实例性能消耗
3. Renderless Components(作用域插槽)
没有命名空间冲突数据来源清晰- 额外的组件实例性能消耗
4. new API
function useMousePosition() {
const x = value(0)
const y = value(0)
const update = e => {
x.value = e.pageX
y.value = e.pageY
}
onMounted(() => {
window.addEventListener('mousemove'
, update)
})
onUnmounted(() => {
window.removeEventListener('mousemove'
, update)
})
return { x, y }
}
new Vue({
template: `
<div>
Mouse position: x {{ x }} / y {{ y }}
</div>
`,
data() {
const { x, y } = useMousePosition()
return {
x,
y,
// ... other data
}
}
})
使用时,不用再关心x和y是包装类型,当普通值使用即可
对比 React Hooks
- 同样的逻辑组合、复用能力
- 只调用一次
- 符合 JS 直觉
- 没有闭包变量问题
- 没有内存/GC 压力
- 不存在内联回调导致子组件永远更新的问题
Vue Beyond Vue Loader(vue的用法总结)
蒋豪群,vue-loader和vue/cli维护者
vue写法分几种?
大体有三种,模板字符串、id、render函数,本质是前两种也要解析成render函数
写法分类
1. Vue.component()
字符串模板直接写在js里
Vue.component('compName',{
props: ['todo'],
template: '<li>{{todo.text}}</li>'
})
2. el方式
字符串模板写在html中,通过id选择
Vue.component('compName',{
props: ['todo'],
template: '#domId'
})
3. render函数
render过程解析
模板:
<div>
<h1>My title</h1>
Some text content
<!--todo:add tagline-->
</div>
解析为dom树:
![dom.png]
vue在生成虚拟dom时,需要用到这些函数

vue对这些函数做了简化,直接可以用h函数,h函数就是以上所有的函数的简写,根据使用方法决定是哪个函数,h是html的hyper的首字母,通常读作createElement,当然实际实现的是图中所有函数

vue-loader
vue通过webpack+vue-loader来预编译
vue-loader做了什么
主要工作:
- 模板解析和编译(vue-template-compiler)
- 表达式的新语法支持+作用域分析(vue-template-es2015-compiler,只在vue-loader中引用,只有在预编译的一步做,运行时交给js引擎做)
- 合并单文件组件的所有区块,并支持scoped css和url转换等(vue/component-compiler-utils)

- vue-template-es2015-compiler支持所有新语法,如es2016及更新版本
- vue/component-compiler-utils 函数库
- vue-loader是webpack相关的逻辑,主要是支持单文件组件(不使用webpack,最后这一层可以放弃)
不用webpack怎么支持单文件解析与打包
1. 官方插件rollup-plugin-vue
完美适用于库文件的打包,tree-shaking能力远超过webpack

2. @vue/dev-server
- 静态文件服务器中间件
- 可以直接在浏览器中使用 import App from “APP.vue”
原理
- 遇到.vue解析成ES modules
- 浏览器只需要MIME类型,不关心扩展名是什么(但是得有扩展名)
实例
- 安装dev-server静态资源服务器
yarn global add @vue/dev-server
注意,global使得命令“vue-dev-server”全局可用
2. 写静态文件
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app"></div>
<script type="module">
import './main.js';
</script>
</body>
</html>
注意,只需要写type=“module”即可使用import,即js的module方案
main.js:
import Vue from 'vue';
import App from './test.vue';
new Vue({
render: h => h(App)
}).$mount('#app')
test.vue:
<template>
<h1>{{msg}}</h1>
</template>
<script>
export default {
data() {
return {
msg: 'hello world'
}
}
}
</script>
<style scoped>
h1 {
color:lightcoral;
}
</style>
- 运行静态文件
vue-dev-server
运行后有提示监听端口,打开即可
3. 对vue文件支持插件-@vue/component-compiler-utils
如果不用dev-server,可以借助@vue/component-compiler-utils来实现开源项目对vue文件的支持
4. 不使用单文件组件但要vue纯逻辑组件的能力时
jsx
JSX手动拼装vnode的数据结构,即等同于h开头的函数所做的工作
涉及:
@vue/babel-preset-jsx
@babel/plugin-syntax-jsx
template-strings
vue-html这个库 利用了js模板字符串,等于换了一种方式拼装vnode,mixin改写render函数传入的参数,运行时拿到的与h函数的返回值一样,都是vnode
typescipt与类型安全
现存问题
- vue2中使用vue-class-component、vue-property-decorator,利用了decorator标准来实现类型安全
- decorator存在以下问题:
- 但decorator本身一直很不稳定
- ts实现的是decorator的早期标准
- ts与babel的实现也有差异
vue3
- Class Api不再在vue core中实现
- Composition function(function-base api)实现更好的类型推断(ts对函数及其参数的类型推断支持很好,Composition function写出的代码和ts代码一致)
- vue-class-component、vue-property-decorator仍然会保留
vuepress1.x
简介
- vuepress是一个静态网站生成器,竞品包括Wordpress、Hexo等建站工具
- 一个 VuePress 网站是一个由 Vue、Vue Router 和 webpack 驱动的单页应用
- 它也借鉴了nuxt的nuxt generate来实现ssr
vuepress1.x提供功能
- 插件API
- 增强主题
- 新增博客主题
评论 0
还没有评论,来抢个沙发吧。