五分钟掌握vue3!!!

创建Vue命令 利用vite脚手架创建

pnpm create vite [name]   name你自己的项目名称

这个命令会让你自己选择

vue组件化:分模块写代码,数据渲染。

ref

使用ref声明响应式数据,响应式记忆技巧,打印出数据类型为xxxImpl,展开后不会显示数据,而是...

该响应式数据在js里要使用.value的方式读取值,在模版中会自动解包,不需要.value

ref的另一个作用是可以获取DOM对象(来自于vue2的),在标签添加一个ref属性,指向一个变量,该变量是ref方法的返回值

推荐使用ref声明基本数据类型的响应式,使用reactive声明引用类型的响应式

reactive:声明引用数据类型的响应式,在js中和模版中不需要使用.value的方式读取值

reactive声明的响应式数据不能重新赋值

解决reactive重新赋值响应式丢失的解决办法:

1、使用ref

2、使用Object.assign方法

争议:使用ref声明响应式数据为什么非要.value,能不能不用?

回答:可以实现,但不能实现,因为要区分普通数据和响应数据

8个常用生命周期

1、创建阶段,vue3中使用setup代替了beforeCreate和created两个生命周期

===使用场景:发送异步请求

2、挂载前后

onBeforeMount(() => {
​
 console.log('1、挂载前 onBeforeMount');
​
});

===使用场景:发送异步请求,操作DOM

onMounted(() => {
​
 console.log('2、挂载后 onMounted');
​
})

3、更新前后

onBeforeUpdate(() => {
​
 console.log('3、更新前 onBeforeUpdate');
​
});
​
onUpdated(() => {
​
 console.log('4、更新后 onUpdated');
​
})

4、卸载前后

===使用场景:清除定时器、清除全局变量,降低内存泄漏的风险

在vue组件中使用定时器,组件被销毁时定时器不会被销毁,因为定时器属于window对象的

onBeforeUnmount(() => {
​
 console.log('5、卸载前 onBeforeUnmount');
​
});
​
onUnmounted(() => {
​
 console.log('6、卸载后 onUnmounted');
​
})

vue指令

指令的作用都是用来进行DOM操作、渲染数据的

vue3常用指令:

v-on/@:绑定事件

v-mode:双向数据绑定

v-bind:给标签绑定动态属性

v-bind:给任意标签添加动态属性,使用频率非常高,所以提供了缩写形 式:

v-bind:属性名="{属性名1:布尔值,属性名2:布尔值,}"

v-bind:属性名= "[布尔值?属性名1:属性名2]"

缩写

:属性名="{属性名1:布尔值,属性名2:布尔值,}"

:属性名= "[布尔值?属性名1:属性名2]"

v-for:循环渲染数据

v-if/v-else-if/v-else:条件渲染

v-show:控制元素的显隐状态

v-text:渲染普通数据

v-html:渲染普通数据,会解析标签

v-slot:插槽

v-pre 不会解析标签中的特殊语法,比如{{ }}

v-once 只会渲染一次,不会改变数据

v-cloak 用于隐藏尚未完成编译的DOM模版

v-memo 缓存,提升性能的

计算属性:computed

computed 计算属性,是vue中一个较为重要的性能优化的API

对一些依赖现有数据通过计算出来的进行缓存(依赖缓存)

计算属性的使用前提:1、页面需要的数据js中没有 2、但是可以通过js中现有的数据计算出来

计算属性默认是只读无法修改,如果要能修改,使用set函数

在实际项目中计算属性更多的只使用get函数

插槽:v-slot

插槽:就是给父组件预留一个渲染将来才确定结构的位置

默认插槽/匿名插槽:全局只能有一个

具名插槽:可以有多个,就是给slot一个name属性指定一个名字

作用域插槽:子组件内部的数据需要传给父组件的插槽中使用

跨组件通信

provide/inject
provide('name', 'hello world')
provide('user', user.value)
​
import { inject } from "vue";
const name = inject("name");
const user = inject('user')

父传子:在父组件的子组件标签上声明一个自定义属性,指向要传的值,在子组件内部通过defineProps来接收

defineProps 编译器宏 不需要单独引入,直接使用即可

要修改父组件user里的数据,通过emits来发出一个修改的通知

使用defineExpose

在vue3中组件默认是关闭的,意思就是外面无法访问组件内部任何的数据和方法

可以通过defineExpose向外暴露指定的数据和方法

如果给原生的HTML标签绑定ref属性,那么获取到的就是DOM对象

如果给自定义组件绑定ref属性,那么获取到的就是子组件的实例

v-model

v-model的基本使用:v-model是对表单元素进行双向数据绑定的指令

v-model本质上就是v-bind:value和v-on:input的语法糖

v-model的高级使用 可以在自定义组件上使用

在自定义组件上使用的使用其实就是v-bind:modelValue和@update:modelValue的语法糖

Watch

使用Watch来监听输入框的变化,只要变化了就做一些额外的事情

watch(要监听的数据,执行的回调函数)

watch(msg, (newVal, oldVal) => {
  console.log("这里可以拿到新值和旧值,做一下额外的事情", newVal, oldVal);
});

监听响应式数据watchEffect,默认立即执行,自动监听回调函数里面使用到的响应式数据,默认不能监听嵌套的引用数据类型,

watchEffect(() => {
  console.log(msg.value);
});

小结:

在实际项目中优先使用watch对指定数据进行精准的监听,性能更好

watchEffect适合特定的场景下使用,它的性能比watch要更低一些

router:路由

路由配置数组

重定向:地址栏访问的是a页面,会自动跳转到指定页面,这个就是重定向

{
    path: "/",
    redirect: "/login", // 重定向:重新指向其它path,会改变网址
    meta: { show: false },
  },

嵌套路由:

{
    path: "/goods",
    component: GoodsView,
    meta: { title: "商品页", auth: true },
    // 重定向
    redirect: "/goods/list",
    // 嵌套路由
    children: [
      {
        path: "/goods/list", // 推荐这种写法便于查找
        component: () => import("../pages/goods/GoodList.vue"), //路由懒加载
      },
      {
        path: "/goods/type", // 推荐这种写法便于查找
        component: () => import("../pages/goods/GoodType.vue"), //路由懒加载
      },
      {
        path: "/goods/add", // 推荐这种写法便于查找
        component: () => import("../pages/goods/GoodAdd.vue"), //路由懒加载
      },
    ],
  },

动态的路由数组,根据用户登录时获取的角色信息动态判断

const dynamicRoutes = [
  {
    path: "/total/order",
    component: () => import("../pages/sales/OrderTotal.vue"),
    meta: { role: ["super"] },
  },
  {
    path: "/total/sales",
    component: () => import("../pages/sales/SalesTotal.vue"),
    meta: { role: ["super"] },
  },
];

路由模式

const router = createRouter({
  history: createWebHashHistory(), // 路由模式、hash模式、history模式、memory模式
  // history: createWebHistory(), // 历史模式
  // history: createMemoryHistory(),
  routes, // 路由中URL和组件一一对应的映射数组
});

addRoute方法把路由添加到路由实例中

dynamicRoutes.forEach((item) => {
  if (item.meta.role.includes("super")) {
    // 后面的super是用户登录时获取到的
    router.addRoute(item);
  }
});

全局前置路由守卫:页面跳转完成前做一下事情,比如控制页面能够跳转,重定向

router.beforeEach((to, from, next) => {
  console.log(to?.meta?.title, from);
  document.title = to?.meta?.title;
  // to 到哪里去
  // from 从哪里来
  // next 放行,不传入参数代表直接放行,传入的参数为路由配置中的path,代表跳转到指定的路径
  next();

  // 路由拦截
  // 如果用户登录了,就会获取到一个token,此时可以利用token来判断用户是否登录,进而实现跳转
  // if (已经登录有token值) {
  //   if (如果跳转的是登录页) {
  //     next(强制跳转到首页);
  //   } else {
  //     next() // 放行
  //   }
  // } else { // 没有登录
  //   next("/login");
  // }
});

全局路由后置守卫(当你真正进入到某个页面之后才执行)

router.afterEach((to, from) => {
  console.log(to, from);
});

实际使用到两个全局守卫的场景:页面跳转时显示loading动画,页面跳转完成后隐藏loading动画

状态仓库

1、为什么要有状态仓库?

因为组件化的项目中会存在很多数据在多个组件里使用,这些数据使用传统的父子通信非常麻烦,耦合性太高,难以维护。这个时候可以由第三方声明一个空的状态仓库,所有可能会用到的共享数据全部存放在仓库中,组件直接从仓库中取数据或者直接通知仓库修改数据即可。

vue2中一个典型的方案就是vuex,vue3中典型的方案是pinia

2、什么时候用到状态仓库pinia?什么时候不建议使用?

如果项目中有多个组件用到相同的数据了,此时建议把该数据保存到pinia仓库中。如果某数据只在一个组件里使用到,不建议使用pinia

3、pinia的几个核心概念

每个defineStore都是一个独立的模块仓库

defineStore方法有两个参数:仓库id名,配置项对象

每个配置对象有三个核心概念:state、getters、actions

其中state就是仓库中存放数据的位置,getters就是仓库中的计算属性,actions里存放的是仓库中修改数据的方法

import { computed } from 'vue'
import { useCounterStore } from './stores/counter.js'
import TableView from './pages/TableView.vue'
// 可以在组件中的任意位置访问 `store` 变量 ✨
const store = useCounterStore()
console.log('🚀 ~ file: App.vue:11 ~ store:', store)
// 组件本身没有该数据,是从外部获取到的数据,建议使用computed计算属性
const name = computed(() => store.name)
// 修改仓库中的内容
const handleClick = () => {
  store.name = 'insight!!' // 修改仓库状态方式一,更简单一些
  // store.increment() // 修改仓库状态方式二,更规范一些
  store.$patch({
    count: store.count+10
  }) // 修改仓库状态方式三,适合批量修改数据
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值