VUE 3
VUE 3 基本认识
- vue3里面是兼容vue2的,你甚至可以可以直接在vue3里面使用vue2
组合式APi体验
vue3的更多优势
创建一个vue3项目
-
使用create-vue创建项目
**1、**前提环境条件
已经安装了16.0或更高版本的Node.js
node -v //查询本机的node版本
**2、**创建一个vue应用
npm init vue@latest
项目目录和关键文件
script setupt语法糖
-
原始写法
-
vue3 语法糖
-
对比(语法糖就是对之前的复杂的方法封装)
-
setup小结
组合式API
reactive和ref函数
-
reactive函数()
-
ref()函数
//1、导入ref函数
import { ref } from 'vue';
//2、执行函数 传入参数[简单类型 + 对象类型] 变量接受
const count = ref(0)
const setCount = () =>{
//脚本区域修改ref产生的响应式对象数据,必须通过.value属性
count.value++
}
-
小结
computed 计算属性
-
具体例子
<script setup> import {ref} from 'vue' const list = ref ([1,2,3,4,5,6,7,8]) // 1. 导入computed import { computed } from 'vue'; //2.执行函数 return计算后的值 变量接受 const computedList = computed(()=>{ return list.value.filter(item => item >2) }) setTimeout(()=>{ list.value.push(9,10) },3000) </script> <template> <div> 原始数组-{{ list }} </div> <div> 计算属性数组-{{ computedList }} </div> </template>
-
小结
watch函数
-
基本概念
-
基础使用
-
例子
//1、导入ref函数 import { ref ,watch} from 'vue'; //2、执行函数 传入参数[简单类型 + 对象类型] 变量接受 const count = ref(0) const setCount = () =>{ //脚本区域修改ref产生的响应式对象数据,必须通过.value属性 count.value++ } //watch 监听单个数据源 //这里的ref属性不需要加.value watch (count,(newVal,oldVal)=>{ console.log('count变化了',newVal,oldVal) })
-
监听多个数据
-
immediate(立即回调)
-
deep (deep性能损耗 尽量不要开启depp)
精确deep监听某个属性的值
-
depp 小结
生命周期函数
父子传值
父传子
-
具体演示(传过来一个静态的值)
-
具体演示(传过来一个响应式数据,使用到了ref函数)
子传父
- 子组件的的emit里面的第一个参数为触发事件名字,第二个参数为要传递的参数
- defineEmits() 等价于 emit(this.$emit)
小结
模板引用
- 组件挂载完毕后才能获取(onMounted)
-
使用案例
-
defineExpose
- 默认情况下语法糖 组件内部的属性和方法是不开放 给父组件使用的,可以通过defineExpose编译,指定哪些属性和方法允许访问
- 例子1
-
例子2
小结:
provide和inject
跨层传递数据
- 传递静态数据
-
代码示例
页面里面的层级展示
(顶层组件 - > 中间组件 -> 底层组件)
-
传递动态数据
-
代码示例
跨层传递方法
顶层组件可以向底层组件传递方法,底层组件调用方法修改顶层组件中的数据
具体应用场景
小结
pinia
什么是pinia
pinia使用计数器案例
基础使用案例
getters和异步action
例子:
stores里面
//导入一个方法 defineStore
// const {defineStore} = require("pinia")
import { defineStore } from 'pinia'
import { ref ,computed } from 'vue'
import axios from 'axios'
const API_URL = 'http://geek.itheima.net/v1_0/channels'
export const useCounterStore = defineStore('counter', () => {
//定义数据state
const count = ref(0)
//定义修改数据的方法(action 同步加异步)
const increment = () => {
count.value++
}
//getter 定义
const doblueCount = computed(() => count. value * 2 )
//定义异步action
const list = ref([])
const getList = async() =>{
const res = await axios.get(API_URL)
list.value=res.data.data.channels
}
//以对象的方式return供组件使用
return {
count,
doblueCount,
list,
getList,
increment
}
})
具体页面调用
<script setup>
// 1 导入 use开头的方法
import {useCounterStore} from '@/stores/counter'
import { onMounted } from 'vue';
// 2 执行方法得到store实例对象
const counterStore = useCounterStore()
console.log(counterStore);
onMounted(() =>{
counterStore.getList()
})
</script>
<template>
<button @click="counterStore.increment">{{counterStore.count}}</button>
{{counterStore.doblueCount}}
<ul>
<li v-for="item in counterStore.list" :key="item.id">{{item.name}}</li>
</ul>
</template>
storeToRefs
直接解构(会发生响应式丢失)
保持数据响应式
具体页面调用
Rabbit项目
ElementPlus引入
ElementPius主题色替换
scss的自动导入配置
手动导入的繁琐
Pinia 优化网络请求
图片懒加载
- 实现思路
在 main.js 里面定义全局指令
//
aap.directive('img-lazy',{
mounted (el , bingding){
//el : 指令绑定的元素 img
// binding : binding.value 指令等于号后面绑定的表达式的值 图片url
console.log(el,binding.value) 熟悉指令用法无实际意义
useIntersectionObserver(
el,
([{isIntersecting}]) = >{ //isIntersecting判断函数是否进入视口区域
consle.log(isIntersecting) //isIntersecting 是一个布尔类型的数据
if (isIntersecting){
//进入视口区域
el.src = binding.value
}
}
)
}
})
在页面中使用
<img v-img-lazy="item.picture" > //图片懒加载
懒加载优化
问题一
问题二