文章目录
- Vue 3 介绍
- 为什么要学习 vue 3
- Vue3 动机 和 新特性
- Vite 的使用
- vite介绍
- 为什么选 Vite ?
- Vite 的基本使用
- Vue3.0项目介绍
- vscode插件说明
- 组合式API
- composition API vs options API
- 体验 composition API
- setup 函数
- reactive 函数
- ref 函数
- script setup语法(★)
- 计算属性computed函数
- 侦听器watch函数
- 钩子函数的使用
- 组件通讯-父传子
- 组件通讯-子传父
- 依赖注入 - provide 和 inject
- 模板中 ref 的使用
- vue3中废弃了过滤器
- 补充-toRefs 函数
- vue-router4
- 基本使用
- 组件中使用route与router
- vuex4
- 基本使用
- 在组件中使用vuex
为什么要学vue3:
官方文档:
目前已支持 vue3 的UI组件库:
element-plus
https://element-plus.gitee.io/#/zh-CN (PC组件库)
Element Plus,一套为开发者、设计师和产品经理准备的基于 Vue 3.0 的桌面端组件库。
vant
https://vant-contrib.gitee.io/vant/v3/#/zh-CN
轻量、可靠的移动端 Vue 组件库。
Vant 是有赞前端团队开源的移动端组件库,于 2016 年开源,已持续维护 4 年时间。
目前 Vant 已完成了对 Vue 3.0 的适配工作,并发布了 Vant 3.0 版本
ant-design-vue (PC组件库)
https://antdv.com/docs/vue/introduce-cn/
ant-design-vue 是 Ant Design 的 Vue 实现,组件的风格与 Ant Design 保持同步
Vue3 设计理念 https://vue3js.cn/vue-composition/
动机与目的:
更好的逻辑复用 与 代码组织 (composition组合式api)
optionsAPI(旧) => compositionAPI(新), 效果: 代码组织更方便了, 逻辑复用更方便了 非常利于维护!!
更好的类型推导 (typescript支持)
vue3 源码用 ts 重写了, vue3 对 ts 的支持更友好了 (ts 可以让代码更加稳定, 类型检测! )
vue3新特性:
数据响应式原理重新实现 (ES6 proxy 替代了 ES5 的 Object.defineProperty)
解决了: 例如数组的更新检测等bug, 大大优化了响应式监听的性能
(原来检测对象属性的变化, 需要一个个对属性递归监听) proxy 可以直接对整个对象劫持
虚拟DOM - 新算法 (更快 更小)
提供了composition api, 可以更好的逻辑复用
模板可以有多个根元素
源码用 typescript 重写, 有更好的类型推导 (类型检测更为严格, 更稳定)
…
小结: vue3 性能更高, 体积更小, 更利于复用, 代码维护更方便
webpack => 实时打包(服务器) => 浏览器运行
vite => 直接编译输出 => 将一部分模块化依赖加载解析的功能 交给了浏览器
Vite 官方文档:https://cn.vitejs.dev/
Vite(法语意为 “快速的”,发音 /vit/,发音同 “veet”)是一种新型前端构建工具
优势
传统方式
vite 方式
问题小结:
目标:能够使用vite创建一个vue3的项目
(1)使用vite创建项目
npm create vite # or yarn create vite
(2)输入项目名字,默认为vite-project
(3)选择创建的项目类型,选择vue即可
(4)选择创建的vue项目类型, 不选ts
(5)启动项目
vite快捷使用
如果想要快速创建一个vue3项目,可以使用如下命令
yarn create vite vite-demo --template vue
yarn create vite vite-demo-ts --template vue-ts
任务目标:掌握vue3的项目目录结构
删除src下所有的文件和代码
创建App.vue
我是App组件
import { createApp } from 'vue' import App from './App.vue' createApp(App).mount('#app')
vue2 采用的就是 optionsAPI
(1) 优点:易于学习和使用, 每个代码有着明确的位置 (例如: 数据放 data 中, 方法放 methods中)
(2) 缺点: 相似的逻辑, 不容易复用, 在大项目中尤为明显
(3) 虽然 optionsAPI 可以通过mixins 提取相同的逻辑, 但是也并不是特别好维护
vue3 新增的就是 compositionAPI
(1) compositionAPI 是基于 逻辑功能 组织代码的, 一个功能 api 相关放到一起
(2) 即使项目大了, 功能多了, 也能快速定位功能相关的 api
(3) 大大的提升了 代码可读性 和 可维护性
vue3 推荐使用 composition API, 也保留了options API
即就算不用composition API, 用 vue2 的写法也完全兼容!!
问题小结: optionsAPI的优缺点是什么? vue3 新增的 compositionAPI 有什么特征? 有什么优势?
需求: 鼠标移动显示鼠标坐标 x, y
options API 版本
当前鼠标位置x: {{ mouse.x }}y: {{ mouse.y }}当前点击次数:{{ count }}
composition API 版本
当前鼠标位置x: {{ mouse.x }}y: {{ mouse.y }}当前点击次数:{{ count }}
抽离逻辑
function useMouse() { const mouse = reactive({ x: 0, y: 0, }) const move = (e) => { mouse.x = e.pageX mouse.y = e.pageY } onMounted(() => { document.addEventListener('mousemove', move) }) onUnmounted(() => { document.removeEventListener('mousemove', move) }) return mouse } function useCount() { const count = ref(0) const add = () => { count.value++ } return { count, add, } }
问题小结: optionsAPI的优缺点是什么? vue3 新增的 compositionAPI 有什么特征? 有什么优势?
optionsAPI:
compositionAPI:
composition api的使用, 需要配置一个setup 函数
{{msg}}
前置说明:
作用: 传入一个复杂数据类型,将复杂类型数据, 转换成响应式数据 (返回该对象的响应式代理)
{{ obj.name }}{{ obj.age }}
总结: 通常是用来定义响应式 对象数据
问题小结:
reactive 处理的数据, 必须是复杂类型, 如果是简单类型无法处理成响应式, 所以有 ref 函数!
作用: 对传入的数据(一般简单数据类型),包裹一层对象, 转换成响应式。
{{ money }}
ref 和 reactive 的最佳使用方式:
问题小结:
script setup是在单文件组件 (SFC) 中使用组合式 API 的编译时语法糖。相比于普通的 script 语法更加简洁
要使用这个语法,需要将 setup attribute 添加到
顶层的绑定会自动暴露给模板,所以定义的变量,函数和import导入的内容都可以直接在模板中直接使用
根组件
点击次数:{{ count }}
computed函数调用时, 要接收一个处理函数, 处理函数中, 需要返回计算属性的值
我今年的年纪我明年的年龄 {{ nextAge }}我后年的年龄
问题小结: computed 函数提供计算属性, 有几种写法?
watch监视, 接收三个参数 1. 参数1: 监视的数据源 2. 参数2: 回调函数 3. 参数3: 额外的配置
// 监听单个ref const money = ref(100) watch(money, (value, oldValue) => { console.log(value) }) // 监听多个ref const money = ref(100) const count = ref(0) watch([money, count], (value) => { console.log(value) }) // 监听ref复杂数据 const user = ref({ name: 'zs', age: 18, }) watch( user, (value) => { console.log('user变化了', value) }, { // 深度监听,,,当ref的值是一个复杂数据类型,需要深度监听 deep: true, immediate: true } ) // 监听对象的某个属性的变化 const user = ref({ name: 'zs', age: 18, }) watch( () => user.value.name, (value) => { console.log(value) } )
生命周期函数 vue3 中的生命周期函数, 需要在 setup 中调用
import { onMounted, onUpdated, onUnmounted } from 'vue' const MyComponent = { setup() { onMounted(() => { console.log('mounted!') }) onUpdated(() => { console.log('updated!') }) onUnmounted(() => { console.log('unmounted!') }) } }
目标:能够实现组件通讯中的父传子组件通讯
步骤:
核心代码:
父组件
我是父组件
金钱:{{ money }}车辆:{{ car }}
子组件
我是子组件
{{ money }} --- {{ car }}
注意:如果使用defineProps接收数据,这个数据只能在模板中渲染,如果想要在script中也操作props属性,应该接收返回值。
目标:能够实现组件通讯中的子传父
步骤:
核心代码
子组件
父组件
依赖注入, 可以非常方便的实现 跨层级的 组件通信
父组件利用 provide 提供数据
我是父组件
金钱:{{ money }}
子组件 (子孙后代, 都可以拿到这个数据)
我是子组件--{{ money }}
如果希望子传父, 可以 provide 传递一个方法
父组件
子组件
联想之前的 ref 和 $refs, 获取模板的元素(dom元素,组件)
1 创建 ref => const hRef = ref(null)
2 模板中建立关联 =>
3 使用 => hRef.value
我是标题
ref操作组件
需要配合defineExpose
我是Form组件
vue3.0中不能使用过滤器,直接使用函数进行替代
ref的使用
我是一个h3的内容 {{ formatTime(now) }}
{{ formatTime(other) }}
使用场景: 如果对一个响应数据, 进行解构 或者 展开, 会丢失他的响应式特性!
原因: vue3 底层是对 对象 进行监听劫持
作用: 对一个响应式对象的所有内部属性, 都做响应式处理
{{ money }}{{ car }}{{ name }}
问题小结: toRefs 函数的作用是什么 ?
作用: 对一个 响应式对象 的所有内部属性, 都做响应式处理, 保证展开或者解构出的数据也是响应式的
vue升级vue3之后,配套的vue-router也升级为vue-router@4.x版本
vue-router4的语法和3的版本语法基本一致,但是有一些细微的修改。
vue-router官网:https://router.vuejs.org/
vue@2 + vue-router@3 + vuex@3 options api vue@3 + vue-router@4 + vuex@4 composition api
(0)安装vue-router
yarn add vue-router
(1)创建组件Home.vue和Login.vue
(2)创建文件router/index.js
import { createRouter, createWebHashHistory, createWebHistory, } from 'vue-router' // 1. 创建路由 const router = createRouter({ // 创建history模式的路由 // history: createWebHistory(), // 创建hash模式的路由 history: createWebHashHistory(), // 配置路由规则 routes: [ { path: '/home', component: () => import('../pages/Home.vue') }, { path: '/login', component: () => import('../pages/Login.vue') }, ], }) export default router
(3)在main.js中引入
import { createApp } from 'vue' import App from './App.vue' import router from './router' createApp(App).use(router).mount('#app')
(4)App.vue中使用
首页 登陆
由于组件中无法访问this,因为无法访问this. r o u t e 与 t h i s . route与this. route与this.router
(1)通过useRoute()可以获取route信息
(2)通过useRouter()可以获取router信息
yarn add vuex
import { createStore } from 'vuex' const store = createStore({ state: { money: 100, }, mutations: { changeMoney(state) { state.money += 10 }, }, actions: { changeMoneyAsync(context) { setTimeout(() => { context.commit('changeMoney') }, 1000) }, }, getters: { double(state) { return state.money * 2 }, }, }) export default store
import { createApp } from 'vue' import App from './App.vue' import router from './router' import store from './store' const app = createApp(App) app.use(router) app.use(store) app.mount('#app')
const store = useStore() const money = computed(() => store.state.money) const double = computed(() => store.getters.double) // mapState mapMutations mapActions mapGetters 需要配合options api才能使用
总结:vuex4 在vue3项目中能用,但是不好用