node -v
npm init vue@latest
组合式API - setup选项
<script>
export default {
setup() {
console.log('setup函数比八大钩子中最早执行的beforeCreate函数还要早一点')
},
beforeCreate() {
console.log('我是beforeCreate函数')
}
}
script>
<script>
export default {
// 在 setup 的最后加上 return,才能使用 数据 和 函数
setup() {
// 数据
const message = 'hello world'
// 函数
const logMessage = () => {
console.log(message)
}
return {
message,
logMessage
}
}
}
script>
<script setup>
// 数据
const message = 'hello world'
// 函数
const logMessage = () => {
console.log(message)
}
script>
<template>
<div>{{ message }}div>
<button @click="logMessage">点我button>
template>
<style>
style>
接收一个对象类型的数据,返回一个响应式的对象
<script setup>
// reactive:接收一个对象类型的数据,返回一个响应式的对象
import { reactive } from 'vue'
// 对象类型
const state = reactive({
count: 100
})
// 进行 +1 的函数
const setCount = () => {
state.count++
}
script>
<template>
<div>{{ state.count }}div>
<button @click="setCount">+1button>
template>
接收简单类型或者对象类型的数据传入并返回一个响应式的对象(推荐统一使用 ref )
<script setup>
// ref:接收简单类型或者对象类型的数据传入并返回一个响应式的对象
import { ref } from 'vue'
// 简单类型 或者 复杂数据类型
const count = ref(100)
// 注意:
// 1. 在脚本中访问数据,需要通过 .value 的形式
// 2. 在template中,.value不需要加
const setCount = () => {
count.value++
}
console.log(count.value)
script>
<template>
<div>{{ count }}div>
<button @click="setCount">+1button>
template>
<style>
style>
计算属性函数
<script setup>
// const 计算属性 = computed(() => {
// return 计算返回结果
// })
import { computed, ref } from "vue";
// 声明数据
const list = ref([1, 2, 3, 4, 5, 6, 7, 8, 9])
console.log(list.value) // 打印list的值
// 过滤 >5 的数据
const computedList = computed(() => {
return list.value.filter(item => item > 5)
})
script>
<template>
<div>
<div>原始数据:{{ list }}div>
<div>计算后的数据:{{ computedList }}div>
div>
template>
作用:监听一个或者多个数据的变化,数据变化时执行回调函数
<script setup>
import { ref, watch } from "vue";
const count = ref(0)
const nickname = ref('张三')
const changeCount = () => {
count.value++
}
const changeNickname = () => {
nickname.value += '哈'
}
// 1. 监视单个数据的变化
// watch(ref对象, (newValue, oldValue) => {...})
// 2. 监视多个数据的变化
// watch([ref对象1, ref对象2], (newArr, oldArr) => {...})
script>
<template>
<div>{{ count }}div>
<button>改数字button>
<div>{{ nickname }}div>
<button>改昵称button>
template>
<script setup>
import { ref, watch } from "vue";
const count = ref(0)
const nickname = ref('张三')
const changeCount = () => {
count.value++
}
const changeNickname = () => {
nickname.value += '哈'
}
// immediate 一进入页面就立即执行
watch(count, (newValue, oldValue) => {
console.log(newValue, oldValue)
}, { immediate: true })
script>
<template>
<div>{{ count }}div>
<button>改数字button>
<div>{{ nickname }}div>
<button>改昵称button>
template>
<script setup>
import { ref, watch } from "vue";
const count = ref(0)
const nickname = ref('张三')
const changeCount = () => {
count.value++
}
const changeNickname = () => {
nickname.value += '哈'
}
// deep 深度监视,默认 watch 进行的是浅层监视
// const ref1 = ref(简单类型) 可以直接监视
// const ref2 = ref(复杂类型) 监视不到复杂类型内部数据的变化
watch(count, (newValue, oldValue) => {
console.log(newValue, oldValue)
}, {
immediate: true,
deep: true
})
script>
<template>
<div>{{ count }}div>
<button>改数字button>
<div>{{ nickname }}div>
<button>改昵称button>
template>
<script setup>
import { ref, watch } from "vue";
const userInfo = ref({
name: 'zs',
age: 18
})
const setUserInfo = () => {
userInfo.value.age++
}
// 深度监视之"精准定位"
watch(() => { userInfo.value.age }, (newValue, oldValue) => {
console.log(newValue, oldValue)
})
script>
<template>
<div>{{ userInfo.age }}div>
<button @click="setUserInfo">改年龄button>
template>
选项式API | 组合式API |
---|---|
beforeCreate/created | setup |
beforeMount | onBeforeMount |
mount | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeUnmount | onBeforeUnmount |
unmounted | onUnmounted |
<script setup>
import { onMounted } from 'vue';
// beforeCreate 和 created 的相关代码一律放在 setup 中
const getList = () => {
console.log('发送请求成功')
}
getList()
// 如果有些代码需要在 mounted 生命周期中执行,就调用对应函数
onMounted(() => { console.log('mounted生命周期函数 - 逻辑1') })
// 可以使用多次 mounted,并不会冲突,它会按顺序执行
onMounted(() => { console.log('mounted生命周期函数 - 逻辑2') })
script>
<template>
<div>div>
template>
<style>
style>
父级内容
<script setup>
// 父传子
// 1. 给子组件,添加属性的方式传值
// 2. 在子组件,通过props接收
import { ref } from "vue";
import SonCom from '@/components/son-com.vue' // 局部组件(导入进来就能用)
const money = ref(100)
const makeMoney = () => {
money.value++
}
const reduce = () => {
money.value--
}
script>
<template>
<div>
<h3>这是父组件的地盘h3>
<hr>
<SonCom info="父组件的余额: " :num="money" @reduceMoney="reduce">SonCom>
<hr>
<h3>还是父组件的地盘h3>
<div>当前余额: {{ money }}div>
<button @click="makeMoney">点击赚钱button>
div>
template>
<style>
style>
子级内容
<script setup>
// 注意:由于写了 setup,所以无法直接配置 props 选项
// 所以:此处需要借助于"编译器宏"函数接收子组件传递的数据
const props = defineProps({
info: String,
num: Number
})
console.log(props.info)
console.log(props.num)
const emit = defineEmits(['reduceMoney'])
const payment = () => {
emit('reduceMoney', 5) // 通过emit触发父组件标签的reduceMoney属性
}
script>
<template>
<div>我是子组件div>
<div>{{ info }}{{ num }}div>
<button @click="payment">点击消费button>
template>
<style>
style>
父级内容
<script setup>
import TestCom from "@/components/test-com.vue";
import { onMounted, ref } from "vue";
// 模板引用 (可以用来获取dom元素,也可以用来获取组件)
// 1. 调用ref函数,生成一个对象
const inp = ref(null)
// 3. 在加载渲染完DOM后,才能访问到绑定的元素
// 这时候我们需要使用到 生命周期钩子函数"onMounted"
onMounted(() => {
console.log(inp.value) // 输出绑定的元素内容
inp.value.focus() // 实现:进入页面立即聚焦输入框
})
// 4. 使用同样的方法,获取组件
const testRef = ref(null)
// 6. 渲染结束后,当用户点击按钮,将触发下面"获取组件的函数"
const getCom = () => {
console.log(testRef.value) // 输出该组件对象
console.log(testRef.value.num) // 输出该组件对象中的一些数据
console.log(testRef.value.sayHi()) // 输出该组件对象中的一些数据
}
script>
<template>
<div>
<input ref="inp" type="text">
<button>点击让输入框聚焦button>
div>
<TestCom ref="testRef">TestCom>
<button @click="getCom">点击获取组件button>
template>
子级内容
<script setup>
const num = 999
const sayHi = () => { console.log('hi') }
// 上面定义的数据或方法,在
emit('update:modelValue', e.target.value)"
>
使用 defineModel
{ script:{ defineModel: true } }
,具体如下所示:vue({
script: {
defineModel: true
}
}),
<script setup>
import MyInput from "@/components//temp.vue"
import { ref } from "vue";
const txt = ref('123456')
script>
<template>
<div>
<MyInput v-model="txt">MyInput>
{{ txt }}
div>
template>
<script setup>
import { defineModel } from "vue";
const modelValue = defineModel()
script>
<template>
<input
type="text"
:value="modelValue"
@input="e => modelValue = e.target.value"
>
template>
Pinia 是 Vue 的最新状态管理工具,是 Vuex 的替代品
回顾 Vuex 涉及哪些概念:
state
mutaions
actions
getters
modules
Pinia 涉及的概念:
state
actions
getters
注意:在实际开发项目的时候,关于Pinia的配置,可以在项目创建时自动添加,而手动添加的方式如下:
npm install pinia
或 npm i pinia
import { createApp } from 'vue'
import { createPinia } from 'pinia' // 导入 Pinia 包
import App from './App.vue'
const pinia = createPinia() // 创建 Pinia 实例
const app = createApp(App) // 创建根实例
app.use(pinia) // pinia 插件的安装配置
app.mount('#app') // 视图的挂载
在 src 文件夹下创建一个 store 文件夹,在 store 里面新建一个 js 文件,这里演示为 counter.js
import { defineStore } from "pinia"
import { computed, ref } from "vue"
// 定义store
// defineStore(仓库的唯一标识,() => { ... })
export const useCounterStore = defineStore('counter', () => {
// 声明数据 state
const count = ref(999)
// 声明操作数据的方法 action
const addCount = () => count.value++
const reduceCount = () => count.value--
// 声明基于数据派生的计算属性 getters
const double = computed(() => count.value * 2)
// 与上面类似
const msg = ref('hello pinia')
const changeMsg = () => { msg.value += '_plus' }
// 返回要被访问的数据
return {
count,
double,
addCount,
reduceCount,
msg,
changeMsg
}
})
<script setup>
import Son1Com from "@/components/Son1Com.vue";
import Son2Com from "@/components/Son2Com.vue";
import { useCounterStore } from "@/store/counter.js"
const counterStore = useCounterStore()
script>
<template>
<div>
<h1>我是App.vue根组件 - {{ counterStore.count }} - {{ counterStore.double }}h1>
<button @click="counterStore.changeMsg">改变button>
{{ counterStore.msg }}
<hr>
<Son1Com>Son1Com>
<Son2Com>Son2Com>
div>
template>
<script setup>
import { useCounterStore } from "@/store/counter.js"
const counterStore = useCounterStore()
script>
<template>
<div>
<h3>我是Son1Com子组件 - {{ counterStore.count }} <button @click="counterStore.addCount">+button>h3>
div>
template>
<script setup>
import { useCounterStore } from "@/store/counter.js"
const counterStore = useCounterStore()
script>
<template>
<div>
<h3>我是Son2Com子组件 - {{ counterStore.count }} <button @click="counterStore.reduceCount">-button>h3>
div>
template>
import { defineStore } from "pinia"
import { ref } from "vue";
import axios from "axios"
export const useChannelStore = defineStore('channel', () => {
const channelList = ref([])
const getList = async () => {
const res = await axios.get('http://geek.itheima.net/v1_0/channels')
// 解构: 在返回的信息中找到真正需要的数据
const { data: { data: { channels } } } = res
channelList.value = channels
}
return {
channelList,
getList
}
})
<script setup>
import { useChannelStore } from "@/store/channel.js"
const channelStore = useChannelStore()
script>
<template>
<div>
<button @click="channelStore.getList">获取数据频道button>
<ul>
<li v-for="item in channelStore.channelList" :key="item.id">{{ item.name }}li>
ul>
div>
template>
官方文档:https://prazdevs.github.io/pinia-plugin-persistedstate/zh/guide/
Github Copilot 插件安装步骤:
Github Copilot 插件使用说明: