Vue3学习笔记

Vue2使用Vue CLI学习笔记
Vue3官方文档

创建项目

官方最新的脚手架工具create-vue,底层将构建工具webpack换成了vite
构建项目速度很快
安装create-vue:node版本16及以上

npm init vue@latest
# 安装一下vite
npm install

初始化项目

提供create函数创建对象(工厂模式)
组合式 API :核心思想是直接在函数作用域内定义响应式状态变量
template中可以不必根节点

setup

关于setup函数

  • beforeCreate方法之前自动执行,实例还没有被创建,this属于undefined
  • 内部代码规则:定义需要的变量和函数,使用组合式API,最后以封装成对象return
  • 可使用setup语法糖简化<script setup>
    声明周期

由上图的生命周期可以看出,之前写在beforeCreate和created都放在setup函数中执行
之前写在distory中的现在是beforeUnmount和unmounted

声明式渲染和响应式ref

声明式渲染:框架封装了一些常用的DOM操作,直接使用提供的API或者指令就能实现需要的效果
响应式:当 JavaScript 中的数据变化时,HTML 视图自动更新

默认声明的数据是不响应式的

<script setup>
import { ref } from 'vue'
 
let count = 1 //  定义了一个普通变量
const add = ()=> {
  count++
}
</script>

<template>
  <h1>{{count}}</h1>
  <button @click="add">
    +1
  </button>
</template>

效果:视图上的数据并没有发生改变
请添加图片描述
vue2实现响应式,通过监听data中的对象和属性,触发dom操作如innerHTML
vue3实现响应式提供两个函数创建响应式对象:

  • reactive():把一个对象传进去变成一个响应式对象,不能传普通类型
  • ref():可以传普通类型,因为会裹一层对象,使用.value暴露值,在template中不写.value

使用reactive获得一个响应式对象

<script setup>
import { reactive } from 'vue'

const counter = reactive({
  count: 0
})

const add = () => {
	counter.count++
}

</script>

<template>
  <h1>{{counter}}</h1>
  <button @click="add">
    +1
  </button>
</template>

响应式效果

使用ref实现相同的功能

<script setup>
import { ref } from 'vue'

const counter = ref({
  count: 0
})

const add = () => {
	counter.value.count++ // 需要使用.value获得数据
}

</script>

<template>
  <h1>{{counter}}</h1>
  <button @click="add">
    +1
  </button>
</template>

组件传值

都遵循单向数据流原则

父子

父传子:
给子组件添加属性,父组件通过v-bind:属性名传值
vue2使用props选项,vue3使用组合函数defineProps(),数组或者是对象注册

传递函数:defineEmits注册函数名,返回一个emit对象,需要传递一个函数名数组声明函数属性
原来vue2中this.$emit('函数名',参数)干了两件事,注册并调用
vue3把注册和调用分开了

// 子组件注册
const emit = defineEmits(['事件名'])

// 子组件调用事件
emit('事件名', 参数)

下面有个简单案例
父组件:

<script setup>
import { ref } from 'vue';
import SonCom from './SonCom.vue';

const money = ref(100)
</script>

<template>
  <div class="parentCom">
    我是老父亲,家底:{{ money }}
    <div>
        <button @click="money++">挣钱 +1</button>
    </div>
    <SonCom @earn="money++" @spend="money--" :money="money"></SonCom>
  </div>
</template>

<style>
    .parentCom {
        height: 200px;
        width: 300px;
        padding: 10px;
        border: 1px black solid;
    }
</style>

子组件:

<template>
    <div class="son">
        我是子组件,余额:{{ money }}
        <div>
            <button @click="emit('spend')" >挥霍 +1</button>
            <button @click="emit('earn')" >打工 +1</button>
        </div>
    </div>
</template>

<script setup>
    defineProps(['money'])
    const emit = defineEmits(['spend','earn']) // 注册了两个事件
</script>

<style>
.son {
    height: 100px;
    width: 150px;
    margin-top: 10px;
    border: 1px black solid;
}
</style>

组件传值

跨层级

多层嵌套
vue2中的provide&inject使用方式较为复杂,一般都直接使用vuex了
vue3中的provide&inject使用极为方便

provide(key,value) // 提供数据
inject(key) // 获得数据

key是字符串,value可以是变量,响应式变量,或者修改函数

模版引用ref

就是给dom元素对象或者是组件对象添加唯一标识
类似于id,作用范围在当前组件中

1 声明一个 ref 来存放该元素的引用,规则就是要用ref()

const 引用名 = ref(null)

2 给dom元素(组件)添加ref属性

<div ref="引用名" .../>

3 在onMounted函数中操作获得的元素对象,要等对象挂载完成才能获取得到

关于引用现象
子组件:

<template>
    <div>
        我是B组件
    </div>
</template>

<script setup>

let count = 100 // 普通变量
const sayHi = function() {
    console.log('hi'+ count);
}

defineExpose({
    count,
    sayHi
})

</script>

父组件:

<script setup>
import { onMounted, ref } from 'vue';
import BCom from './BCom.vue';

const bcom = ref(null)

onMounted(()=> {
    console.log(bcom.value.count); // 外部访问
    bcom.value.count = 10 // 修改了值
    bcom.value.sayHi()
    console.log(bcom.value.count);
})

</script>

结果:子组件中的count没变
结果
暴露一个响应式变量,外部组件正常访问,不要.value

<template>
    <div>
        我是B组件
    </div>
</template>

<script setup>
import { ref } from 'vue';

const count = ref(100) // 响应式变量,外面裹了一层对象
const sayHi = function() {
    console.log('hi'+count.value);
}

defineExpose({ // 暴露属性
    count,
    sayHi
})

</script>

结果:子组件中的值被修改了
显示结果

Vue3.3新特性

1、defineOptions
可以在setup函数中添加平级属性,如name

defineOptions({
	name: 'Index'
})

2、defineModel 实验性的父子组件的双向绑定

Pinia

状态管理,vuex的vue3官方替代方案
pinia官方文档

# 使用 npm
npm install pinia

组合式API使用就正常定义需要共享的数据,包括同步异步的方法

export const useCounterStore = defineStore('counter', () => {
  const count = ref(0)
  const doubleCount = computed(() => count.value * 2)
  function increment() {
    count.value++
  }

  return { count, doubleCount, increment } // 直接暴露
})

pinia的响应式是通过reactive实现的
即维护的状态发生改变,组件中引用的状态也会跟着改变

为了从 store 中提取属性时保持其响应性,你需要使用 storeToRefs()
方法的话就直接解构

<script setup>
import { storeToRefs } from 'pinia'
const store = useCounterStore()
// `name` 和 `doubleCount` 是响应式的 ref
// 同时通过插件添加的属性也会被提取为 ref
// 并且会跳过所有的 action 或非响应式 (不是 ref 或 reactive) 的属性
const { name, doubleCount } = storeToRefs(store)
// 作为 action 的 increment 可以直接解构
const { increment } = store
</script>

pinia自动持久化插件

官方文档

安装插件:

npm i pinia-plugin-persistedstate

将插件注入到pinia对象中

import { createApp } from 'vue'
import { createPinia } from 'pinia'
// 导入插件
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
import App from './App.vue'

const pinia = createPinia()
pinia.use(piniaPluginPersistedstate) // 注入pinia
const app = createApp(App)

app.use(pinia)
app.mount('#app')

在store中添加新参数,开启持久化
默认保存整个store,方式是localStorage

import { defineStore } from 'pinia'
import { ref } from 'vue'

export const useStore = defineStore(
  'main',
  () => {
    const someState = ref('hello pinia')
    return { someState }
  },
  {
    persist: true, // 开启持久化
  },
)

可以配置key修改键名,配置path保存指定数据
persist

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值