黑马 Vue3教程

一、组合式API

  1. setup选项
    • 执行时机:比 beforeCreate更早
    • setup函数中,获取不到 this (this是undefined)
    • 数据和函数,需要在 setup 最后return,才能模板中应用
    • 通过 setup 语法糖简化代码
    // 不使用 setup 语法糖的写法,每个数据,方法都需要在 return 中声明,否则无法使用
    <script>
    	export default {
    	  setup() {
    	    // 数据
    	    const message = 'hello'
    	    const logMessage = () => {
    	      console.log('方法被调用了')
    	    }
    	    return {
    	      message,
    	      logMessage
    	    }
    	    // console.log('setup函数');
    	  },
    	  beforeCreate() {
    	    console.log('beforeCreate函数');
    	  },
    	}
    </script>
    
    <template>
      {{ message }}
      <button @click="logMessage">按钮</button>
    </template>
    
    // 使用 setup 语法糖,大大的简化了代码书写
    <script setup>
    	const message = 'hello Vue3'
    	const logMessage = () => {
    	  console.log('log')
    	}
    </script>
    <template>
      {{ message }}
      <button @click="logMessage">按钮</button>
    </template>
    
  2. reactive 和 ref
    • reactive:接收一个对象类型的数据,返回一个响应式对象
    • ref:接收简单类型 或 复杂类型,返回一个响应式的对象
      • 本质: 在原有传入数据的基础上,外层包了又包了一层对象,包成了复杂类型
      • 底层,包成复杂类型之后,再借助 reactive 实现的响应式
      • 注意点:访问数据,在脚本中需要通过 xxx.value,在模板中可以直接使用
<script setup>
	import { reactive, ref } from 'vue'
	const count = reactive({ number: 0 })
	const addCount = () => {
	  count.number++
	}
	const a = ref(1)
	console.log(a.value)
</script>

<template>
  {{ count.number }}
  {{ a }}
  <button @click="addCount">+1</button>
</template>
  1. 计算属性(computed)
    • 语法:const 计算属性 = computed( () => { return 计算返回的结果 } )
    • 计算属性中不应该有”副作用“,如:异步请求,操作DOM…
    • 避免直接修改计算属性的值,虽然提供了get、set,除非是特殊情况(全选/反选)
<script setup>
import { computed, reactive } from 'vue';

const list = reactive([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
const listFilter = computed(() =>
  list.filter(item => item > 2)
)

const listAddOneNumber = () => {
  list.push(Math.floor(Math.random() * 100))
}
</script>

<template>
  {{ list }}
  <br>
  {{ listFilter }}

  <button @click="listAddOneNumber">加一个数字</button>
</template>
  1. 监听(watch)
    • 语法:watch( ref 对象,(newValue, oldValue) => {})
    • 可以监听单个数据,也可以监听多个数据
    • 监听多个数据:同时监听多个响应式数据的变化,不管哪个数据发生了变化都会触发回调
    • immediate
      • 说明:在监听器创建立即触发回调,响应式数据变化后继续执行回调
    • deep
      • 语法: watch( ref 对象,(newValue, oldValue) => {}, {deep: true, immediate})
      • 深度监视,默认watch 进行的是 浅层监视
      • const ref1 = ref(简单类型) 可以直接监视
      • const ref2 = ref(复杂类型) 监视不到复杂类型内部数据的变化
    • 对于对象中的单个属性,进行监视
      • 语法:watch( () => userInfo.age, (newValue, oldValue) => {})
<script setup>
	import { ref, watch } from 'vue';
	
	const count = ref(0)
	const name = ref('张三')
	
	const addCount = () => {
	  count.value++
	}
	
	const changeName = () => {
	  name.value = name.value === '李四' ? '张三' : '李四'
	}
	
	// 监视单个数据的变化
	watch(count, (newValue, oldValue) => {
	  console.log('数据变化了')
	  console.log(newValue, oldValue)
	})
	
	// 监视多个数据的变化
	// watch([ref对象1,ref对象2], (newValue, oldValue)=>{})
	watch([count, name], (newValue, oldValue) => {
	  console.log('数据变化了')
	  console.log(newValue, oldValue)
	})
</script>

<template>
	  {{ count }}
	  <br>
	  <button @click="addCount">count+1</button>
	  <br>
	  {{ name }}
	  <br>
	  <button @click="changeName">changeName</button>
</template>
  1. 生命周期API
    在这里插入图片描述
  2. 组合式API下的父传子
    • 给子组件,以添加属性的方式传值
    • 在子组件中,通过 props 接收
      • 在子组件中:
        • 由于写了 setup,所以无法直接配置 props 选项
        • 所以: 此处需要借助于 ”编译器宏“ 函数 接收 子组件传递的数据
// 父组件
<script setup>
// 父传子
// 1. 给子组件,添加属性的方式传值
// 2. 在子组件,通过 props 接收
import son from './components/Son.vue';

let car = '宝马'
</script>

<template>
  <div class="contain">
    <h3>父组件</h3>
     <!-- 1. 给子组件,添加属性的方式传值 -->
    <son :car="car"></son>
  </div>
</template>

<style scoped>
 .contain {
  border: 5px solid;
  padding: 50px;
 }
</style>
// 子组件
<script setup>
// 子组件
// 由于写了 setup,所以无法直接配置 props 选项
// 所以: 此处需要借助于 ”编译器宏“ 函数 接收 子组件传递的数据
const props = defineProps({
    car: String
})
</script>


<template>
    <div class="son">我是子组件,{{ car }}</div>
</template>

<style scoped>
.son {
    border: 1px solid;
    padding: 30px;
}
</style>
  1. 组合式 API 下的子传父
  • 父组件中给子组件通过 @ 绑定事件
  • 子组件内部通过 emit 方法触发事件
    • 在子组件内部,需要通过defineEmits编译器宏生成 emit 方法
      在这里插入图片描述
      在这里插入图片描述
  1. 模板引用以及defineExpose宏函数
    • 模板引用:通过 ref 标识获取真实的 dom 对象或组件实例对象
    • defineExpose()
      • 默认情况下在 <script setup> 语法糖下 组件内部的属性和方法是不开放给父组件访问的,可以通过 defineExpose编译宏指定哪些属性和方法允许访问
    • 获取模板引用的时机最早也得在 组件挂载完毕后才能获取
// 父组件
<script setup>
import { onMounted, reactive, ref } from 'vue';
import testRef from './components/testRef.vue';

const inp = ref(null)

onMounted(() => {
  inp.value.focus()
})

const getFocus = () => {
  inp.value.focus()
  console.log(inp.value)
}

const childrenEle = ref(null)
const getChild = () => {
  console.log(childrenEle.value.count)
}

</script>

<template>
  <input type="text" ref="inp">
  <br>
  <button @click="getFocus">点击获取焦点</button>
  <br>
  <testRef ref="childrenEle"></testRef>
  <br>
  <button @click="getChild">点击获取子节点</button>
</template>

// 子组件
<script setup>
    const count = 999
    defineExpose({
        count
    })
</script>
<template>
    {{ count }}
</template>
  1. 跨层传递普通数据
    • 顶层组件通过 provide函数提供数据
    • 底层组件通过 inject函数获取 数据
    • 在调用 provide函数时,第二个参数设置为 ref 对象
    • 顶层组件可以向底层组件传递方法,底层组件调用方法可以修改顶层组件中的数据
// 顶层组件
<script setup>
	import { provide, ref } from 'vue';
	import CenterCom from './components/center-com.vue';
	let count = ref(50)
	const changeCount = (newValue) => {
	  count.value = newValue
	}
	provide('TopCount', count)
	provide('changeCount',changeCount)
</script>

<template>
  <h1>我是顶层组件</h1>
  <CenterCom />
</template>

// 底层组件
<script setup>
	import { inject } from 'vue';
	const TopCount = inject('TopCount')
	const changeCount = inject('changeCount')
	
	const myChangeCount = () => {
	    changeCount(20)
	}
</script>

<template>
    <h3>底层组件 | {{ TopCount }}</h3>
    <button @click="myChangeCount">点击修改Count</button>
</template>

二、Vue3.3版本新特性 - defineOptions

在 Vue 3.3 中新引入了 defineOptions 宏,顾名思义,主要是用来定义 Options API 的选项。可以用 defineOptions 定义任意的选项,props,emits,expose,slots除外(因为这些都可以使用 defineXXX 来做到)
在这里插入图片描述

三、Vue3 中的 v-model 和 defineModel

在 Vue3 中,自定义组件上使用 v-model,相当于传递一个 modelValue 属性,同时触发 update:modelValue事件

<Child v-model="isVisible"/>
// 相当于
<Child :modelValue="isVisable" @update:modelValue = "isVisible = $event"
// 原始写法
// 父组件
<script setup>
   import ModelTest from './components/model-test.vue';
   import { ref } from 'vue';
   let count = ref(999)
</script>

<template>
 <ModelTest v-model="count" />
 {{ count }}
</template>

// 子组件
<script setup>
/* let count = defineModel()
++count.value */
   defineProps({
       modelValue: Number
   })

   const emit = defineEmits(['update:modelValue'])
</script>

<template>
   <input type="text" 
   :value="modelValue"
   @input="e => emit('update:modelValue',+e.target.value)"
   >
</template>

在这里插入图片描述

Pinia

  1. 什么是Pinia 在这里插入图片描述
  2. 如何使用 Pinia
import {defineStore} from 'pinia';
import { computed, ref } from 'vue';

// 组合式API写法
export const useCounterStore = defineStore('counter',()=> {
	// 定义 state
    const count = ref(10)
    const msg = ref('hello pinia')

	// 定义 actions
    const addCount = () => count.value++
    const subCount = () => count.value--

	// 定义getters
    const doubleCount = computed(()=> count.value * 2)

	// 必须对外暴露
    return {
        count,
        msg,
        addCount,
        subCount,
        doubleCount
    }
})
  1. Pinia 的持久化

    • 安装插件 npm i pinia-plugin-persistedstate
    • 在main.js中导入并 给 pinia 使用该插件
    import { createApp } from 'vue'
    import { createPinia } from 'pinia';
    // 导入持久化插件
    import piniaPlugin from 'pinia-plugin-persistedstate';
    import './style.css'
    import App from './App.vue'
    
    
    const pinia  = createPinia() // 创建pinia实例
    pinia.use(piniaPlugin)
    const app = createApp(App) // 创建根实例
    
    app.use(pinia) // pinia插件的安装配置
    app.mount('#app') // 试图的挂载
    
    
    • 在 store中,配置属性,使用该插件
    import { defineStore } from 'pinia';
    import { computed, ref } from 'vue';
    
    export const useCounterStore = defineStore('counter', () => {
        const count = ref(10)
        const msg = ref('hello pinia')
    
        const addCount = () => count.value++
        const subCount = () => count.value--
    
        const doubleCount = computed(() => count.value * 2)
    
        return {
            count,
            msg,
            addCount,
            subCount,
            doubleCount
        }
    },
    // 使用 持久化 插件 
    {
        persist: true
    })
    
  2. 总结:
    在这里插入图片描述

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值