vue3文档学习
阅读原文时间:2023年07月10日阅读:4

1.vue的核心功能

1.声明式渲染
2.响应性: vue会自动跟踪JavaScript状态并在其发生变化时响应式的更新DOM。

2.渐进式框架

根据不同的需求场景,可以用不同的方式使用vue:
1.无需构建步骤,渐进式增强静态的HTML;
2.在任何页面中作为 Web Components 嵌入;
3.单页应用 (SPA);
4.全栈 / 服务端渲染 (SSR);
5.Jamstack / 静态站点生成 (SSG);
6.开发桌面端、移动端、WebGL,甚至是命令行终端中的界面

3.SFC(single-file-components) - 单文件组件

即:

4.API风格

即: 选项式API和组合式API。

选项式API:
使用选项式 API,我们可以用包含多个选项的对象来描述组件的逻辑,例如 datamethods 和 mounted。选项所定义的属性都会暴露在函数内部的 this 上,它会指向当前的组件实例。

组合式API:
通过组合式 API,我们可以使用导入的 API 函数来描述组件逻辑。在单文件组件中,组合式 API 通常会与 <script setup> 搭配使用。这个 setup attribute 是一个标识,
告诉 Vue 需要在编译时进行一些处理,让我们可以更简洁地使用组合式 API。比如,<script setup> 中的导入和顶层变量/函数都能够在模板中直接使用。

5.安装流程

前提: nodejs最新版本
然后执行: npm init vue@latest =>这个命令是安装并执行 create-vue;

安装依赖: npm install
运行: npm run dev

6.创建一个应用

每个 Vue 应用都是通过 createApp 函数创建一个新的 应用实例:
import { createApp } from 'vue'
// 从一个单文件组件中导入根组件
import App from './App.vue'
const app = createApp({
/* 根组件选项 */
App
})
app.mount('#app');

App.vue页面:

挂载应用:
应用实例必须在调用了 .mount() 方法后才会渲染出来。该方法接收一个“容器”参数,可以是一个实际的 DOM 元素或是一个 CSS 选择器字符串。

7.模板语法

文本插值:
最基本的数据绑定形式是文本插值,它使用的是“Mustache”语法 (即双大括号):
{{message}}

原始HTML:
双大括号会将数据解释为纯文本,而不是 HTML。若想插入 HTML,你需要使用 v-html 指令

Attribute绑定:
双大括号不能在 HTML attributes 中使用。想要响应式地绑定一个 attribute,应该使用 v-bind 指令

动态绑定多个值:
const objAttributes = {
id: 'container',
class: 'hello'
}
通过不带参数的 v-bind,你可以将它们绑定到单个元素上:

使用JavaScript表达式:
在 Vue 模板内,JavaScript 表达式可以被使用在如下场景上:
1.在文本插值中 (双大括号)
2.在任何 Vue 指令 (以 v- 开头的特殊 attribute) attribute 的值中

8.响应式基础

 声明响应式状态:
使用 reactive() 函数创建一个响应式对象或数组:
import { reactive } from 'vue'
const state = reactive({ count: 0 })

DOM更新时机:
当你更改响应式状态后,DOM 会自动更新。然而,你得注意 DOM 的更新并不是同步的。相反,Vue 将缓冲它们直到更新周期的 “下个时机” 以确保无论你进行了多少次状态更改,每个组件都只需要更新一次。
若要等待一个状态改变后的 DOM 更新完成,你可以使用 nextTick() 这个全局 API:
import { nextTick } from 'vue'
function increment() {
state.count++
nextTick(() => {
// 访问更新后的 DOM
})
}

深层响应式:
在 Vue 中,状态都是默认深层响应式的。这意味着即使在更改深层次的对象或数组,你的改动也能被检测到。
值得注意的是,reactive() 返回的是一个原始对象的 Proxy,它和原始对象是不相等的:
const raw = {}
const proxy = reactive(raw)

// 代理对象和原始对象不是全等的
console.log(proxy === raw) // false

9.自定义事件配合v-model使用


等价于(编译器会对 v-model进行展开)
@input="searchText = $event.target.value" />

而当使用在一个组件上时,v-model会被展开为如下的形式:
@update:modelValue="newValue => searchText = newValue"
/>
在刚刚这个例子中,组件内部需要做两件事:
1.将内部原生input元素的value attribute绑定到 modelValue prop.
2.输入新的值时在 input 元素上触发 update:modelValue 事件。
CustomInput.vue:


10.依赖注入

prop 逐级透传问题

背景:当从父组件向子组件传递数据时,会用到props,有一些多层级嵌套的组件,形成了一颗巨大的组件树,而某个
深层的子组件需要一个较远的祖先组件中的部分数据。在这种情况下,如果仅用props则必须将其沿着组件链逐级传递
下去,这样非常麻烦。

provide 和 inject 可以解决这一问题。一个父组件相对于其所有的后代组件,会作为依赖提供者。任何后代的组件
树,无论层级有多深,都可以注入由父组件提供给整条链路的依赖。

11.异步组件

defineAsyncComponent

背景描述: 在大型项目中,需要拆分应用为更小的块,并仅在需要时再从服务器加载相关组件。

import { defineAsyncComponent } from 'vue';
const AsyncComp = defineAsyncComponent(()=>{
return new Promise((resolve, reject)=>{
//…从服务器获取组件
resolve(/*获取到的组件*/)
})
OR //或者直接导入vue单文件组件
import('./components/AdminPageComponent.vue')
})
// …像使用其他一般组件一样使用 AsyncComp

12.自定义组件

例如:


指令钩子: 一个指令的定义对象可以提供几种钩子函数
const myDirective = {
//在绑定元素的 attribute前
//或事件监听器应用前调用
created(el, binding, vnode, prevVnode){
el: 指令绑定到的元素。可以用于直接操作DOM。
binding:一个对象,包含 value,oldValue等属性。
vnode:代表绑定元素的底层VNode。
prevNode:之前的渲染中代表指令所绑定元素的VNode。
},
//在元素被插入到DOM钱调用
beforeMount(el, binding, vnode, prevVnode){},
//在绑定元素的父组件及他自己的所有子节点都挂载完成后调用
mounted(el, binding, vnode, prevVnode){},
//绑定元素的父组件更新前调用
beforeUpdate(el, binding,vnode,prevVnode){},
//在绑定元素的父组件及他自己的所有子节点都更新后调用
updated(el,binding,vnode,prevVnode){},
//绑定元素的父组件卸载前调用
beforeUnmount(el, binding, vnode, prevVnode){},
//绑定元素的父组件卸载后调用
unmounted(el,binding,vnode,prevVnode){}
}

例子:


app.directive('color',(el,binding)=>{
el.style.color = binding.color;
})

13.KeepAlive

元素来实现动态组件的用法:
// 非活跃的组件将会被缓存

默认会缓存内部的所有组件实例,也可以通过 include和 exclude
prop 来定制该行为。
例如:
include='a,b' OR :include='/a|b/' OR :include="['a','b']" 会根据组件的name选项进行匹配。
:max="10" 最大缓存实例数

缓存实例的生命周期:
onActivated()和 onDeactivated()注册相应的两个状态的生命周期钩子
import { onActivated, onDeactivated } from 'vue';
onActivated(()=>{
//调用时机为首次挂载以及每次从缓存中被重新插入时
})
onDeactivated(()=>{
//在从DOM上移除,进入缓存以及组件卸载时调用
})

14.Teleport

是一个内置组件,可以将一个组件内部的一部分模板 传送 到该组件的DOM结构外层的位置去。

15.路由

服务端路由指的是 服务器根据用户访问的URL路径返回不同的响应结果。

在单页面应用中,客户端的JavaScript可以拦截页面的跳转请求,动态获取新的数据,无需重新加载就可更新当前页面。
一个客户端路由器利用 History API 或是 hashchange 事件这样的浏览器API来管理应用当前应该渲染的视图。

vue默认路由模式是 hash 模式,hash模式背后的原理是 onhashchange事件,可以在window对象上监听这个事件。
hash发生变化的URL都会被浏览器记录下来。hashchange只能改变#后面的url片段。
在hash模式下,前端路由修改的是#中的信息,而浏览器请求时不带它玩,所以刷新的话不存在问题。

history路由:
切换历史状态:back();//后退 forward();//前进 go(2);//前进两次
修改历史状态: pushState, replaceState;接收三个参数: stateObj, title, url
通过pushstate把页面的状态保存在state对象中,当页面的url再变回这个url时,可以通过event.state
取到这个state对象,从而可以对页面状态进行还原。
无#标识。
不能刷新,因为刷新是去请求服务器。如果服务器中没有相应的响应或者资源,会报404.

16.状态管理

组成部分:状态,视图,交互。

Pinia用法
创建一个store:
// stores/counter.js
import{ defineStore } from 'pinia';
export const useCounterStore = defineStore('counter',{
state: ()=>{
return { count: 0, todos: [] }
},// 也可这样定义 state:()=>({ count: 0 })
actions: {
increment(){ this.count++ },
addTodo(text){
this.todos.push({ text, id:this.nextId++, isFinished:false })
}
},
getters: {
finishedTodos(state){
return state.todos.filter((todo)=>todo.isFinished)
}
}
})

//然后在一个组件使用这个store

pinia优点:
1.mutation已弃用;
2.无需动态添加Store
3.不再有可命名的模块
4.不再有嵌套结构的模块