找回密码
 立即注册
首页 业界区 业界 初学vue3, 全是黑盒子,vue3知识点汇总

初学vue3, 全是黑盒子,vue3知识点汇总

眺愤 2025-6-6 11:55:16
学习 Vue.js 应该像学习一门编程语言一样,首先要熟练掌握常用的知识,而对于不常用的内容可以简单了解一下。先对整个框架和语言有一个大致的轮廓,然后再逐步补充细节。千万不要像学习算法那样,一开始就钻牛角尖。
前序:

vueAPI的风格分为: 选项式和组合式,vue2中一般用选项式, 所以文章中讲到的api一般都是组合式
vue3官方推荐用基于 Vite 的构建项目,首先安装 node.js, 然后在终端输入
npm create vue@latest,根据提示构建项目。npm install 和 npm run dev 分别是下载依赖和运行项目
当然你也可以通过vue ui来构建项目
1、初识vue:

1.1、项目结构:

当我们新建一个vue项目时, 整个项目刚开始会有很多.vue, .js, .html .css文件,但真正有用的只有index.html, App.vue和一些配置文件
vue组件包含三个区域, 分别用来写html,js(ts),css  其中style的scoped可以让css样式的作用域限定到当前组件
  1. [/code][size=4]1.2、vue常用函数[/size]
  2. createApp():是Vue 3中用来创建一个新的Vue应用实例的方法。它接受一个根组件作为参数,并返回一个应用实例。根组件就是export出去的name字符串
  3. mount(): 是把createApp创建的应用实例挂载到一个容器上。 接受的参数容器可以是一个css的选择器
  4. [code]createApp(App).mount('#app') // App.vue文件中
  5.         //index.html中
  6. 我们刚创建的项目中会有上面的两个文件, 实际上就是创建了一个App实列, 通过id选择器把它挂载到一个div上
复制代码
setup(): 是一个函数, 函数里面可以定义响应式变量、计算属性、方法, 然后把变量, 方法 return 出去, 就可以在该组件的template中使用。 (我们一个组件所用到的函数、变量都写在这里面)
我们每个组件的name、setup、components...都需要export出去。 其中name是这个组件的名字, 当其他组件要用到当前组件的时候就是要,
如下: 在setup函数中定义了nameclick方法给当前组件的html使用。 代码中的(@用来绑定事件, 包括html所有事件和自定义事件)
  1. <template>
  2.   <h1>{{ age }}</h1>                
  3.   <button @click="handleClick">click</button>
  4. </template>
复制代码
前面讲到setup里面定义的方法,变量等都需要return出去之后 html 中才能使用,下面这个语法糖可以让我们不用一个个写return
setup语法糖: 在中写方法、状态的话,不需要把方法或状态return回去, vue会自动帮我们return, 而且也不需要用components注册用到的组件。
ref(): 是一个函数,使用 ref 函数可以创建一个包装过的响应式对象,使其能够在 Vue 组件中进行响应式数据绑定。ref接受的参数是基本类型、数组、对象类型的。(当参数是对象时, ref内部其实是调用的reactive)
reactive(): 使用 reactive函数可以创建一个包装过的响应式对象,reactive接受的参数是对象类型
响应式数据指的是当我们的变量发生变化的时候, 跟这个变量相关的元素就会自动刷新
上面的代码中我们点击button的时候会把age = 18, 但实际上我们页面显示的时候age还是等于10, 因为age不是响应式的变量
所以我们需要用ref创建age变量, let age = ref(10), 这样age发生变化时, 跟age相关的元素也会自动刷新。(需要注意: 在js中使用由ref创建的响应式对象是要加上".value", 比如 age.value;在html中则不需要, 可直接写成age)
toRefs和toRef:当我们把一个对象或者变量解构的时候。假设person对象中有name, age const {name, age} = person,那么此时解构出来的的name和age不再具有响应式。为了使解构出来的仍然具有响应式,那么应该用toRefs或toRef包括起来。 const {name, age} = toRefs(person).
computed():是基于其他数据的值计算出来属性,并且当这些数据变化时,计算属性的值会自动更新
计算属性是基于它们的依赖进行缓存的,只在其依赖发生变化时才会重新计算,而方法每次调用时都会重新执行。
如下, 如果是基于函数getFullName()计算全名的话当name发生变化是控制台会输出3次1, 如果是用FullNameByComputed的话, 控制台只会输出一个1
  1. {{ getFullName() }}
  2. {{ getFullName() }}
  3. {{ getFullName() }}
  4. setup : () => {
  5.     let firstname = ref('');
  6.     let lastname = ref('');
  7.     const getFullName = () => {
  8.       return firstname.value + lastname.value;
  9.     }
  10.         const FullNameByComputed= computed(() => {
  11.       console.log(1);
  12.       return firstname.value + lastname.value;
  13.     });
  14.    
  15.         return {firstname, lastname, getFullName, FullNameByComputed}
  16. }
复制代码
通过上面的computed创建的FullNameByComputed是一个类似ref创建的对象, 在js(script标签)中要访问FullNameByComputed的话需要FullNameByComputed.value。
如果需要直接修改value的话需要在创建对象的时候传递get和set方法,如下
  1. const getFullNameComputed = computed({
  2.       get: ()=> {
  3.         return firstname.value + "-" + lastname.value;
  4.       },
  5.       set: (newName)=> {
  6.         let name = newName.split('-');
  7.         firstname.value = name[0];
  8.         lastname.value = name[1];
  9.       }
  10.     });
复制代码
上面代码中,当我们FullNameByComputed.value的话, vue会自动调用get方法, 当我们FullNameByComputed.value=newName的时候,会自动调用set方法, 并把等号右边的值传递到set参数中
1.3、常用语法糖

v-model: 是 Vue.js 中用于在表单控件(如输入框、复选框、单选按钮等)和组件之间创建双向数据绑定
如下: 我们让username和输入框双向绑定, 当用户在输入框中输入字符时, username 就会变成用户输入的值。其中username需要是响应式的变量
  1. <input v-model="username" type="text">
  2. <p>{{ username }}</p>
  3. let username = ref('');
复制代码
v-for: 通过 ... in ... 用来遍历数组
如下: 假设我们有一个persons数组, 数组长度是3,那么我们可以通过v-for来生成3个li标签。其中对于遍历生成的标签我们需要通过:key="“给他绑定一个唯一的key, 一般用id。(注意key前面的:, 不写:的话,vue会把person.id当成字符串解析)
  1. <li v-for="person in persons" :key="person.id">{{ person.name }}</li>
复制代码
v-if和v-else就如他们的字面意思, 判断用的
注意: 上面文章和下面文章中用到的函数需要自己引入,如computed、ref等等,文章中就不再过多赘述了。
2、路由器router:

2.1、路由的定义与使用:

通过 Vue Router,我们可以轻松地定义路由规则,将不同的 URL 映射到不同的组件,并在这些组件之间切换,通俗的讲就是我们可以让页面在不同的url上显示我们想要显示的组件。
router是路由器的意思, route是路由的意思,我们需要给vue的实例创建一个router, 通过createRouter()函数.
  1. const router = createRouter({
  2.     history: createWebHistory(),    // 路由器的工作模式, 下面会讲到
  3.     routes : [
  4.         {
  5.             path : "/home",        // url匹配path的时候路由器会渲染这个路由的组件
  6.             name : "HomeView",        // 当前的路由route的名字
  7.             component : Person,        // 路由的组件
  8.         },        // 后面可以继续写多个route, router匹配时会从前往后匹配
  9.         {},...
  10.     ]
  11. })
复制代码
使用router:
引入:
我们通过createApp()可以创建一个vue实例, const app = createApp(App), 通过app.use(router)使实例使用router。use(router)的参数是我们上面代码用createRouter()创建的
上面我们创建并在实例中使用了router, 但是我们并没有给router说,我们要在页面的哪个部分渲染组件, 所以我们要在我们想要渲染的位置写上(一般是在App.vue的template的某个地方)。
最后实现的效果就是, 当url跟我们的某个route匹配时,vue的router就会自动的在我们指定的渲染位置上渲染url对应的组件
渲染模式
渲染模式分为前端渲染和后端渲染, html中可以通过a href标签实现点击跳转url,这是后端渲染。(点击a标签的时候页面会重新加载一下, 感觉不出来的话可以点击F12 选中network, 每次点击时network中会重新加载文件,)
vue中我们可以通过点击跳转,来代替a标签,to相当于href,这就是实现了前端渲染。(当我们点击的时候会发现浏览器并没有重新加载。)(这里不详细讲前后端渲染了)
to的三种写法
点击跳转中的to有三种写法.(to前面加上:, 才能让vue不把后面的内容解析成字符串)

  • to="/home"
  • :to="{path : "/home"}"
  • :to="{name: "HomeView"}"
路由模式

  • Hash 模式路由使用 URL 的 hash(#)部分来模拟一个完整的 URL,实际 URL 的路径部分始终是 # 符号之前的内容
  • History 模式利用 HTML5 History API 来管理路由,这使得 URL 看起来像普通的 URL,没有 # 符号。
2.2、路由的传参:

一般用第二种。(useRoute()创建的对象中包含query和params)

  • 通过props.query + path
    传递:
    上面我们通过to的第一种写法后面加上?加上我们要传的参数即可(通过&分隔要传不同的参数)。router link或     router link  , 通过这种方式即可把当前组件中的name传递到要路由到的组件中
    接收:
    路由组件通过useRoute()创建对象, 对象的query对象中就存着我们传递的数据const route = useRoute();  console.log(route.query.name)
  • 通过props.params + name
    前提我们需要修改router的routes的path路径, 通过用:占位。path : "/home/:name"。
    然后可以通过    router link  ,或 router link 进行传递
    需要渲染的路由组件中通过route.params.name访问
2.3、路由的props配置:

一般传参用上面2.2的第二种写法就行, 下面这个也是一种传参的写法, 只不过不需要用useRoute。
  1. {
  2.             path : "/home/:name",
  3.             name : "HomeView",
  4.             component : Person,
  5.             props(route) {        // props接收的是当前的路由信息, 里面有path,params,query等等, 你可以输出查看下
  6.                 return route.params;
  7.             },
  8.           //  props:true,        // 等价于 return route.params
  9.           // props(route) {return route.query}
  10.         },
复制代码
如上在路由中添加代码中的三种props代码的话,就相当于是在, 那么我们就可以通过defineProps来解析出路由中要传的name了。(defineProps3.1中会讲, 注意:每种props写法要对应上面路由的传参对应的传递写法)
2.4、编程式路由:

上面我们都是通过router-link标签的to属性实现跳转, router-link标签相当于html的a标签,那么我们只能实现通过点击链接的形式实现跳转, 如果要实现点击button实现跳转,那就可以通过管理路由器实现。(通过路由器就可以实现多种形式的跳转)
通过useRouter()创建一个router路由器,router.push()就可以实现跳转,push中可传递的参数和2.1中 "to的三种写法" 的参数一样
2.4、路由重定向:

通过在route配置中添加下面代码("/"重定向到"/home")
  1. {
  2.       path : "/",
  3.       redirect : "/home",
  4. },
  5. {
  6.       path: '/:pathMatch(.*)',        // 匹配所有路径
  7.       redirect: '/404',        //重定向到/404
  8.     },
复制代码
2.5、路由守卫:

导航守卫的主要目的是在用户尝试访问需要身份验证的页面时,检查用户是否已登录。如果未登录,则将用户重定向到登录页面;如果已登录,则允许继续访问目标页面。
导航守卫 beforeEach:
router.beforeEach((to, from, next) => { ... })  是一个全局的导航守卫,它在每次路由切换之前被调用。

  • to 是即将要进入的路由对象。
  • from 是当前导航正要离开的路由对象。
  • next 是一个函数,调用它来继续当前的导航。
  1. // meta 是自定义的, requestAuth 也是自定义的, 用来表示是否需要登录状态才可以访问
  2. {
  3.       path: "/pk",
  4.       name: "pk",
  5.       component: PkIndex,
  6.       meta: {
  7.         requestAuth: true,
  8.       },
  9.     },
  10. router.beforeEach((to, from, next) => {
  11.   // useUserStore 会在下面的 Pinia 中讲到
  12.   const userStore = useUserStore(); // 在beforeEach外面用的话会报错
  13.   if (to.meta.requestAuth && !userStore.user.is_login) {        // userStore.user.is_login表示用户是否已登录
  14.     next({ name: "user_account_login" });
  15.   } else {
  16.     next();
  17.   }
  18. });
复制代码
3、组件传递数据

我们在项目中分别创建Person.vue 和 App.vue, 其中App.vue中使用创建Person组件实例, 即App是Person的父组件
在一般情况下我们父传子的时候用的是下面讲的第一种1. 通过defineProps、子传父的时候用的第二种2. 通过自定义事件
3.1、父组件向子组件传递数据


  • 通过defineProps
父组件中, 前面我们向子组件中传递了person和str变量, 其中=右边的"person"和"str" 是我们在父组件如果是在这个中通过defineProps中过去的父组件数据的话, 可以直接修改父组件的数据
3.4 mitt自定义事件管理库

上面讲到的3.2的第二种自定义事件一般用于子组件和父组件, 但对于层级较深的就需要一层一层传递,很麻烦, mitt就可以很好帮我们解决问题
mitt一个js的事件管理库, 一般用于管理自定义事件。(安装指令npm install mitt)
一般在一个js文件中创建一个mitt实例, 在其他要用到自定义事件管理的文件中引入mitter
  1. 创建一个新的事件总线实例,返回一个包含 on, off, emit, all 等方法的对象,用于管理事件的订阅和发布。
  2. const mitter = mitt();
  3. 订阅指定类型的事件,当该类型的事件被触发时,执行指定的处理函数。
  4. mitter.on('eventName', (data) => {
  5.   console.log('Event received with data:', data);
  6. });
  7. 取消订阅指定类型的事件,停止执行特定的处理函数。
  8. mitter.off('eventName', handlerFunction);
  9. 触发指定类型的事件,并传递可选的事件数据给订阅该事件的处理函数。
  10. mitter.emit('eventName', { message: 'Hello, mitt!' });
  11. 订阅所有类型的事件,当任何类型的事件被触发时执行指定的处理函数。
  12. mitter.all((type, data) => {
  13.   console.log(`Event ${type} received with data:`, data);
  14. });
  15. // 清除所有事件监听器
  16. mitter.all.clear();
复制代码
4、组件之间共享数据Pinia

对于子组件和父组件之间,我们可以通过上面讲到的方法实现数据共享,但是对于有更深层级的组件,我们就需要集中管理状态的方法。Pinia就可以解决这个问题, 安装命令npm install pinia
下面讲到的pinia写法更推荐用vue3官方推荐的组合式写法。
4.1、数据的定义

在实例中引入pinia, 跟引入router一样
  1. import { createPinia } from 'pinia'
  2. const app = createApp(App)
  3. const pinia = createPinia();
  4. app.use(pinia)
复制代码
一般来说我们会把要共享的组件的数据的pinia放到一个src文件夹下的store中的js文件中。然后在需要使用的文件中引入js, 生成store
  1. import { defineStore } from 'pinia'
  2. // defineStore接收的第一个参数是这个store的id(自己定义)
  3. export const usePersonStore = defineStore('Person', () => {
  4.   let name = ref('hh');
  5.   const changeName = (newname) => {
  6.         name = newname;
  7.   }
  8.        
  9.   return {name, changeName};        // 记得把要用到的变量和方法暴漏出去
  10.   // 上面的写法是组合式的, 选项式的话一般把变量卸载state方法的return 中, 而且变量默认就是响应式的,
  11.   // 组合式的写法, 变量如果要弄成响应式的话需要自己加上 ref 或 reactive 。
  12. })
复制代码
如果要使用Person的数据的话就:
  1. import { usePersonStore } from '@/store/Person'
  2. const PersonStore = usePersonStore()        //PersonStore 是一个对象
  3. //PersonStore 中包含的就有name, PersonStore.name或PersonStore.$state.name
复制代码
4.2、数据的修改


  • 直接修改
  1. PersonStore.name = 'ld'
复制代码

  • 通过函数修改
  1. PersonStore.changeName('ld');        //
复制代码
对于PersonStore解构出来的数据跟1.2中讲的一样也是不再具有响应式,我们可以用storeToRefs来解构。(虽然也可以用toRefs,但非常不建议)
4.3 和 4.4 是选项式的写法, 可以仅作了解
4.3、action 和 getters

如果我们需要计算和返回基于已有状态(state)的新数据,那么可以在getters中写方法
  1.   state() {
  2.     return {
  3.       name: 'yxc',
  4.       age: 18
  5.     }
  6.   },
  7.   action: {
  8.           // 里面写函数, this指向state
  9.   },
  10.   getters: {        // vue也会自动维护一个this
  11.     doubleName() {
  12.       return this.name + this.name
  13.     }
  14.   }
复制代码
4.4、subscribe

subscribe 是用于监听 store 的状态变化的方法。Pinia 提供了一种简单而直观的方式来订阅状态变化
订阅方法:通过 store.$subscribe(callback) 方法来订阅状态变化,callback 接受一个参数 mutation,可以是状态的变化信息或其他相关内容。
取消订阅:订阅方法返回一个取消订阅的函数 unsubscribe(),你可以在不需要继续监听状态变化时调用它来取消订阅。
响应式更新:Pinia 使用 Vue.js 的响应式系统来管理状态,因此任何影响状态的变化都会触发订阅者的回调函数。
  1. PersonStore.$subscribe((mutation, state) => {})
复制代码
mutation: 一个对象,描述了引起状态变化的 mutation。它包含以下属性:

  • storeId: 发生变化的 store 的 ID。
  • type: 变化的类型,通常是 direct(直接变化)或 patch(通过 patch 变化)。
  • events: 包含变化详情的数组。
state: 变化后的 store 状态。
5、组件或Dom元素的引用

在 Vue.js 中,ref 属性是一个非常有用的特性,它允许你在组件或 DOM 元素上注册一个引用,以便在 JavaScript 中轻松访问它。这在进行直接操作或与组件/DOM 交互时非常便利。
1. ref 的基本用法

在 Vue 组件中,你可以在任何元素或子组件上使用 ref 属性。例如:
  1. <template>
  2.   
  3.     <input ref="myInput" type="text" />
  4.     <button @click="focusInput">聚焦输入框</button>
  5.   
  6. </template>
复制代码
在上面的示例中:

  • ref="myInput" 为输入框注册了一个引用。
  • 在 focusInput 方法中,通过 myInput.value 访问该输入框并调用其 focus 方法,使输入框获得焦点。
2. 组件引用

如果 ref 应用在一个子组件上,ref 将会返回该子组件的实例。这样你就可以访问子组件的公开方法和属性。
  1. <template>
  2.   <ChildComponent ref="child" />
  3.   <button @click="callChildMethod">调用子组件方法</button>
  4. </template>
复制代码
3. 使用 ref 在 v-for 循环中引用子组件

当 ref 应用在 v-for 循环中,Vue 会生成一个包含所有相同 ref 名称的数组。
  1. <template>
  2.   
  3.     <ChildComponent ref="children" />
  4.   
  5.   <button @click="callAllChildrenMethods">调用所有子组件方法</button>
  6. </template>
复制代码
4. ref 的生命周期

ref 的值在组件的生命周期中会随之变化:

  • 在组件创建时,ref 是空的。
  • 在 mounted 钩子中,ref 已经被填充,可以安全地使用。
  • 当组件被销毁时,ref 也会被清空。
学到这里, 你就可以用vue写项目了。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册