vue3(基础语法+compositionAPI+vuex4+router4+pinia)

-----------------------------------------------------------------------------
vue3性能更高 体积更小 更利于复用 代码维护方便(compositionAPI)

新特性
1. 数据响应式原理重新实现 (ES6 proxy 替代了 ES5 的 Object.defineProperty)
解决了: 例如数组的更新检测等bug, 大大优化了响应式监听的性能
(原来检测对象属性的变化, 需要一个个对属性递归监听) proxy 可以直接对整个对象劫持
2.虚拟DOM - 新算法 (更快 更小)
3.组合api(compositionAPI)
4.多个根组件
5.源码用 typescript 重写, 有更好的类型推导 (类型检测更为严格, 更稳定)

antdesign常用于react  但是也有vue的版本
vue2中
optionsAPI项目大了难以维护 methods computed 会依赖data中的数据 当使用了该data的功能需要修改的时候 需要拉滚动条去找到对应模块逐个修改data methods computed

vue3中
compositionAPI 组合API

vite(支持vue3 react 不支持vue2 )

新的构建工具vite 
用ESM 无需打包
轻量快速的热重载 模块热重载
丰富的功能 ts jsx css
等等

创建vue3项目
yarn create vite
输入项目名字 不要中文

创建项目简单写法
创建vue3项目
yarn create vite 01-demo --template vue
创建vue3-ts项目
yarn create vite 01-demo --template vue-ts

语法检测插件 标签高亮
vetur(vue2)和volar(vue3)不能同时装

optionsAPI
优点:简单易学 易于使用
缺点:项目大了 逻辑不容易复用
可以复用使用mixins方法(混入)

compositionAPI
更容易维护 提高代码可读性

要用compositionAPI就要写setup

setup函数 compositionAPI的起点
在beforeCreate之前执行
setup中不能用this this指向undefined
模板中使用数据和结构需要在setup返回(return)

其他钩子函数this指的是当前组件实例

reactive函数
要传入一个复杂类型数据 不能传入简单数据类型 
将一个复杂类型数据 变成响应式数据
import { reactive } from 'vue'
 const mouse = reactive({
      x: 0,
      y: 0
    })
const move = e => {
      mouse.x = e.pageX
      mouse.y = e.pageY
    }
document.addEventListener('mousemove', move)
return {
      mouse,
      move,
    }
使用reactive函数之后才可以变成响应式数据

ref函数 将简单数据类型转为响应式数据
ref会返回一个对象 对象有一个值value
ref(100) 会返回一个 {value:100}
而且在模板中这个值会自动解套 不用额外的.value就可以访问

let money= ref(100)
js中访问需要money.value
ref也支持传复杂的类型 转为响应式数据

ref可以用于简单数据类型和复杂数据类型
从vue3.2.0之后更推荐使用ref  性能更好了

SFC单文件组件
script setup vue3中的新语法
在script中写setup 就不用写
export default{ 
setup(){
return {}
}
}

下面两段script可以同时写
<script>
export default {
name:''
}
</script>

<script setup>
import {ref} from 'vue'
let user = ref({
name:'zs',
age:18
})
</script>

顶层的绑定会自动暴露给模板,所以定义的变量,函数和import导入的内容都可以直接在模板中直接使用
顶层的变量里面的变量不可以直接在模板中直接使用

computed也有缓存
也有get set
要接收计算属性的返回值
const age = ref(18)

两种写法 第一种写回调函数只能读
const nextAge = computed(() => {
  console.log('我打印了')
  return +age.value + 1
})
第二种写法写对象 写get set
const nextAge2 = computed({
  get() {
    return +age.value + 2
  },
  set(value) {
    age.value = value - 2
  }
})

侦听器
可以侦听ref reactive响应式数据的变化

import { ref, watch } from 'vue'

const money = ref(100)
const car = ref('小黄车')

const add = () => {
  money.value++
}

money 和 car 可以分开侦听 也可以写到数组里一起侦听
watch三个参数 
第一个:要侦听的数据
第二个:回调函数,有两个参数 newV oldV
第三个:是否开启 深度监听 和 立即执行
watch(
  [money, car],
  (value, oldValue) => {
    console.log(value, oldValue)
  },
  {
    deep: true,
    immediate: true
  }
)

侦听复杂类型要加deep:true
watch(
  user,
  value => {
    console.log(value)
  },
  {
    deep: true
  }
)

侦听复杂类型的某一个值
const user = ref({
  name: 'zs',
  age: 18
})

watch(
  () => user.value.name,
  value => {
    console.log('值变化了', value)
  }
)

eventbus在vue3中没有了

在vue3中导入组件就能用了 不用注册了

父传子
父组件给子组件传值
子组件使用defineProps接收数据
const props = defineProps({
  money: Number,
  car: String
})

console.log(props)
要想接收的数据在js中也可以用 需要定义一个props接收

子传父
子组件
const props = defineProps({
  money: Number,
  car: String
})

const emit = defineEmits(['minus'])

const minus = () => {
  emit('minus', 500)
}

父组件
<Son :money="money" :car="car" @minus="minus"></Son>

const minus = m => {
  money.value = money.value - m
}

provide 和 inject
跨层级的简单组件通信 所有后代组件 例如父子 爷孙
复杂的还是用vuex vue3中是pinia

父组件
let money = ref(1000)
let car = ref('宏光mini')
const changeMoney = m => {
  money.value = money.value - m
}

provide('money', money)
provide('car', car)
provide('changeMoney', changeMoney)

孙组件
const money = inject('money')
const car = inject('car')
const changeMoney = inject('changeMoney')
<h5>孙组件-----{{ money }}-----{{ car }}</h5>
<button @click="changeMoney(10)">-10</button>

ref也可以操作dom 也可以操作组件  调用组件的方法
import { ref } from 'vue'
const h1Ref = ref(null)
const change = () => {
  //  h1Ref.value就可以操作dom元素 再.innerHTML还可以修改元素
  console.log(h1Ref.value)
}

  <h1 ref="h1Ref">根组件</h1>
  <button @click="change">修改</button>

ref操作组件
将组件的通用方法和属性通过defineExopse暴露出去
通过ref默认是访问不到获取到的组件的属性和方法的
需要被访问的组件 script setup 中 defineExopse的暴露几个属性 方法,外面就能用几个属性 方法
父组件
import { ref } from 'vue'
import Form from './components/Form.vue'

const h1Ref = ref(null)
//  这里定义子组件的ref
const formRef = ref(null)
const fn = () => {
  console.log(h1Ref.value)
  //  这里使用子组件的方法
  console.log(formRef.value)
  formRef.value.validate()
}

  <div>根组件</div>
  <h1 ref="h1Ref">根组件</h1>
  <button @click="fn">修改</button>
  <hr />
  <Form ref="formRef"></Form>

子组件
import { ref } from 'vue'

const count = ref(0)
const validate = () => {
  console.log('表单校验方法')
}
// 暴露属性给外部组件使用
defineExpose({
  count,
  validate,
})

vue3废弃了过滤器  过滤器本质就是个函数

如果对一个响应式对象进行解构 解构出来的数据会丢失响应式能力 有响应式的是那个对象
通过toRefs和toRef可以保留响应式能力

错误案例:
import { reactive, ref } from 'vue'

const user = reactive({
  name: 'zs',
  age: 18
})

const { name, age } = user

  <div>{{ name }}------{{ age }}</div>
  <input type="text" v-model="name" />
  <input type="text" v-model="age" />

正确案例如下:
const { name, age } = toRefs(user)
或者
const name = toRef(user, 'name')
const age = toRef(user, 'age')
或者
const user = ref({
  name: 'zs',
  age: 18
})

const { name, age } = toRefs(user.value)

下面两行是一样的 只是写了delTodo的话 会在下面的第四行有提示
const emit = defineEmits()
const emit = defineEmits('delTodo')

emit('delTodo',id)

vue3的钩子函数
beforeCreate 和 created没了 变成了 setup
beforeMount 变成了 onBeforeMount
mounted 变成了 onMounted
beforeUpdate 变成了 onBeforeUpdate
updated 变成了 onUpdated
beforeUnmount(beforeDestroy) 变成了 onBeforeUnmount
unmounted(destroyed) 变成了 onUnmounted

-----------------------------------------------------------------------------
vue2全家桶 vue2配合路由3和vuex3
vue@2 + vue-router@3 + vuex@3 optionsAPI

vue3全家桶 vue3配合路由4和vuex4 compositionAPI
vue@3 + vue-router@4 + vuex@4(pinia 比 vuex4更好)


router4
yarn add vue-router
新建文件夹router/index.js
const router = createRouter({
// vue3中必须要写
history: createWebHashHistory(),
routes:[]
})
export  default router

main.js中
import router from '路径'
app.use(router)

.vue中使用
路由信息对象
const route = useRoute()
路由实例对象
const router = useRouter()

vuex4在vue3中能用 但是不好用

vuex4可以和pinia一起用但是不建议这么做

pinia没有模块的概念了  它可以有任意多的store(例如在store创建car.js money.js)

参数一:模块名
参数二:对象 用于pinia的核心概念 state actions getters 没有mutations
state中也要写成函数的形式() => {} 不要写成对象{},防止变量污染
defineStore返回的是一个函数 在外面调用的话还要加一个() 例如:useCountStore()

import { defineStore } from 'pinia'
const useCountStore = defineStore('', {
    state: () => {
        return {
            count: 0
        }
    }
})

exportdefault useCounterStore

import {storeToRefs} from 'pinia'
const { count, double, money } = storeToRefs(counter)
可以解构pinia中的state和getters中的值

pinia模块化思想
在store下建一个modules文件夹 同级建一个index.js js都写到modules中  最后全部导入到index.js中

这里的todos是一个module
侦听 pinia中的数组变化
todos.$subscribe(()=>{

})

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值