对于会vue2 的同学, 可以直接看以下地址来学习 Vue3 官网是首选方案,不会被人带偏v3.cn.vuejs.org/guide/migra…
快速开始
一上来作者先给出如何安装使用,快捷使用方式,对于程序员来说边写代码边学习是最佳的方式。我发现一个 Bug codesandbox 打不开,提了一个issue github.com/vuejs-trans… 另外一种方式是codepen,但是国内codepen打开非常慢
还是采用本地 vite 生成一个 vue3 的简单工程靠谱
yarn create vite hello-vue3 --template vue
下载模板速度很快
Yarn 安装 node_modules 花费还是比较久的
yarn dev
启动很快,126ms
从 main.js 上看,已经和 vue2 挂载的方式不一样了,采用createApp
App.vue里面张这样,一个让我不爽的点是,js 这块是置灰的,类似没有使用这个变量的提示,不知道有没有办法解决
- Helloworld 组件,里面的一个变量 count 使用了ref 方式绑定,
- 属性采用了 defineProps 的方式引入
- script 标签上有一个setup
这么看和 vue2 使用差距还是很大的
新特性
- 组合式 API
- Teleport
- 片段
- 触发组件选项
- 来自
@vue/runtime-core的createRendererAPI,用于创建自定义渲染器 - 单文件组件组合式 API 语法糖 (
<script setup>) - 单文件组件状态驱动的 CSS 变量 (
<style>中的v-bind) - SFC
<style scoped>现在可以包含全局规则或只针对插槽内容的规则 - Suspense 实验性
组合式 API
作者说大型项目光靠提取组件还不够,对于一个大型容器组件,逻辑多而且碎片化,难以继续组件化, 组合式 API 的目的是,将同一个逻辑关注点相关代码收集在一起,上面的setup 就是干这个事情的。
在组合式 API 中,会使用 toRef
import { ref } from 'vue'
const counter = ref(0)
console.log(counter) // { value: 0 }
console.log(counter.value) // 0
counter.value++
console.log(counter.value) // 1
toRef 的能力,是将基础类型, 变成引用类型,这样改变一个地方,所有的引用都会改变,但是此处必须用 xxx.value 的形式赋值了, 还有一个 toRefs,用处是包含一个对象,比如 props ,用于解构
const title = toRef(props, 'title')
生命周期使用方式也变了,参数是回调函数
import { ref, onMounted } from 'vue'
onMounted(getUserRepositories)
watch 和 computed 也是类似的
不过所有的逻辑都放在 setup 里面,还是会非常大,和之前的单页面组件一样,
import { ref, watch, computed } from 'vue'
const counter = ref(0)
watch(counter, (newValue, oldValue) => {
console.log('The new counter value is: ' + counter.value)
})
const twiceTheCounter = computed(() => counter.value * 2)
console.log(twiceTheCounter.value) // 2
所以作者设计了函数式组件,类似于react, 这是一个巨大的创新,有点类似 vue2 之前的 mixin, mixin 还是一个 Object 类,现在是一个函数,还是不一样。
// src/composables/useUserRepositories.js
import { fetchUserRepositories } from '@/api/repositories'
import { ref, onMounted, watch } from 'vue'
export default function useUserRepositories(user) {
const repositories = ref([])
const getUserRepositories = async () => {
repositories.value = await fetchUserRepositories(user.value)
}
onMounted(getUserRepositories)
watch(user, getUserRepositories)
return {
repositories,
getUserRepositories
}
}
有了这个函数式组件之后,要如何使用呢? 官网给的 demo 非常棒
// src/components/UserRepositories.vue
import useUserRepositories from '@/composables/useUserRepositories'
import useRepositoryNameSearch from '@/composables/useRepositoryNameSearch'
import { toRefs } from 'vue'
export default {
components: { RepositoriesFilters, RepositoriesSortBy, RepositoriesList },
props: {
user: {
type: String,
required: true
}
},
setup (props) {
const { user } = toRefs(props)
const { repositories, getUserRepositories } = useUserRepositories(user)
const {
searchQuery,
repositoriesMatchingSearchQuery
} = useRepositoryNameSearch(repositories)
return {
// 因为我们并不关心未经过滤的仓库
// 我们可以在 `repositories` 名称下暴露过滤后的结果
repositories: repositoriesMatchingSearchQuery,
getUserRepositories,
searchQuery,
}
},
data () {
return {
filters: { ... }, // 3
}
},
computed: {
filteredRepositories () { ... }, // 3
},
methods: {
updateFilters () { ... }, // 3
}
}
把这些函数组件,用的像过滤器一样,大大减少了 setup 里面的逻辑,而且 use 这种函数,还能多出复用,非常灵活,后续我们继续学习 vue3 中其他的特性。