Vue笔记(六)--响应式

这一节了解一下Vue3中的响应式,响应式是Vue框架重要的特点,常见的是通过数据绑定的方式将变量的值渲染到页面中,当变量发生变化时,页面对应的元素也会更新,简单总结:

API

  1. setup 入口函数

含义:组合式 API 统一入口,组件执行最先触发 作用:声明数据、方法、生命周期、引入 API

javascript 复制代码
<template>
  <view>{{ msg }}</view>
</template>
<script setup>
const msg = 'setup组合式入口'
</script>
  1. ref 基础响应式

含义:创建基本类型响应式数据 作用:处理字符串、数字、布尔值

javascript 复制代码
<template>
  <view>{{ count }}</view>
  <button @click="count++">加一</button>
</template>
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
  1. reactive 对象响应式

含义:创建对象 / 数组类型响应式数据 作用:批量管理表单、复杂对象数据

javascript 复制代码
<template>
  <view>{{ user.name }} {{ user.age }}</view>
</template>
<script setup>
import { reactive } from 'vue'
const user = reactive({ name: '小明', age: 18 })
</script>
  1. toRefs 解构保留响应

含义:把 reactive 对象转为 ref 属性集合 作用:解构取值不丢失响应性

javascript 复制代码
<script setup>
import { reactive, toRefs } from 'vue'
const info = reactive({a:1,b:2})
const {a,b} = toRefs(info)
</script>
  1. computed 计算属性

含义:依赖数据自动计算,自带缓存 作用:数据格式化、派生新数据

javascript 复制代码
<template>
  <view>总和:{{ sum }}</view>
</template>
<script setup>
import { ref, computed } from 'vue'
const n1 = ref(10), n2 = ref(20)
const sum = computed(() => n1.value + n2.value)
</script>
  1. computed 可读写模式

含义:同时配置读取与赋值逻辑 作用:双向联动修改源数据

javascript 复制代码
<script setup>
import { ref, computed } from 'vue'
const num = ref(10)
const double = computed({
  get: () => num.value *2,
  set: val => num.value = val/2
})
</script>
  1. watch 精准监听

含义:指定监听单个 / 多个数据变化 作用:数据变动执行异步、复杂逻辑

javascript 复制代码
<template>
  <input v-model="text"/>
</template>
<script setup>
import { ref, watch } from 'vue'
const text = ref('')
watch(text,(newVal)=>console.log('新值',newVal))
</script>
  1. watch 深度监听 deep

含义:监听对象内部属性变更 作用:监控嵌套对象、数组修改

javascript 复制代码
<script setup>
import { reactive, watch } from 'vue'
const obj = reactive({name:'小红'})
watch(()=>obj,()=>console.log('对象变更'),{deep:true})
</script>
  1. watchEffect 自动依赖监听

含义:自动收集内部依赖,无需指定监听源 作用:简化监听代码,依赖变化自动执行

javascript 复制代码
<script setup>
import { ref, watchEffect } from 'vue'
const num = ref(0)
watchEffect(()=>console.log('数值:',num.value))
</script>
  1. onMounted 挂载生命周期

含义:DOM 渲染完成后执行 作用:操作 DOM、请求接口、初始化业务

javascript 复制代码
<script setup>
import { onMounted } from 'vue'
onMounted(()=>console.log('页面DOM加载完成'))
</script>
  1. onUpdated 视图更新钩子

含义:数据变更页面重新渲染后触发 作用:更新后 DOM 操作、状态同步

javascript 复制代码
<script setup>
import { onUpdated } from 'vue'
onUpdated(()=>console.log('页面视图已更新'))
</script>
  1. onBeforeUnmount 销毁前钩子

含义:组件销毁前瞬间执行 作用:清除定时器、解绑事件

javascript 复制代码
<script setup>
import { onBeforeUnmount } from 'vue'
let timer = setInterval(()=>{},1000)
onBeforeUnmount(()=>clearInterval(timer))
</script>
  1. defineProps 接收父组件参数

含义:组合式专用 props 接收 API 作用:父子组件传参、参数校验

javascript 复制代码
<template>
  <view>{{ title }}</view>
</template>
<script setup>
const props = defineProps({
  title: String
})
</script>
  1. defineEmits 触发子父事件

含义:组合式派发自定义事件 作用:子组件向父组件传递消息数据

javascript 复制代码
<template>
  <button @click="send">提交</button>
</template>
<script setup>
const emit = defineEmits(['submit'])
const send = () => emit('submit','提交数据')
</script>
  1. defineExpose 向外暴露属性

含义:组件主动对外抛出数据方法 作用:父组件直接获取子组件内部值

javascript 复制代码
<script setup>
const msg = '子组件数据'
defineExpose({msg})
</script>
  1. ref 获取 DOM 元素

含义:绑定标签获取真实 DOM 节点 作用:元素聚焦、样式操作

javascript 复制代码
<template>
  <input ref="ipt"/>
</template>
<script setup>
import { ref, onMounted } from 'vue'
const ipt = ref(null)
onMounted(()=>ipt.value.focus())
</script>
  1. provide /inject 跨层传值

含义:祖先提供数据,后代任意层级接收 作用:多层组件便捷传参,避开逐层 props

javascript 复制代码
<!-- 祖先组件 -->
<script setup>
import { provide } from 'vue'
provide('key','全局共享数据')
</script>
<!-- 后代组件 -->
<script setup>
import { inject } from 'vue'
const data = inject('key')
</script>

栗子:

javascript 复制代码
<template>
  <view class="wrap">
    <view>计数:{{ count }}</view>
    <button @click="count++">点击累加</button>
    <view>双倍值:{{ doubleCount }}</view>

    <input v-model="user.name" placeholder="输入姓名"/>
    <view>监听姓名:{{ user.name }}</view>

    <Child :info="user" @child-send="recvMsg"/>
  </view>
</template>

<script setup>
import {ref,reactive,computed,watch,onMounted} from 'vue'

const count = ref(0)

const doubleCount = computed(()=>count.value*2)
const user = reactive({name:''})

// 监听数据
watch(()=>user.name,(val)=>{
  console.log('姓名变化:',val)
},{immediate:true})

onMounted(()=>{
  uni.showToast({title:'页面加载完毕',icon:'none'})
})

// 子组件
const Child = {
  props:['info'],
  emits:['child-send'],
  setup(props,emit){
    const send = ()=>emit('child-send',props.info.name)
    return {send}
  },
  template:`<button @click="send">向父组件传值</button>`
}

// 接收子组件数据
const recvMsg = (val)=>{
  uni.showToast({title:'收到:'+val})
}
</script>

<style scoped>
.wrap{padding:30rpx;}
input{border:1rpx solid #eee;padding:20rpx;border-radius:10rpx;margin:20rpx 0;}
button{margin:10rpx 0;}
</style>
javascript 复制代码
<template>
  <view class="container">
    <view class="title">Demo</view>

    <view class="section">
      <text class="label">1. ref 响应式计数</text>
      <button type="primary" @click="add">点击 +1</button>
      <view>当前数值:{{ count }}</view>
    </view>

    <view class="section">
      <text class="label">2. reactive 响应式对象</text>
      <input v-model="task.title" class="input" placeholder="输入任务标题" />
      <input v-model="task.desc" class="input" placeholder="输入任务描述" />
      <view>标题:{{ task.title }}</view>
      <view>描述:{{ task.desc }}</view>
    </view>

    <view class="section">
      <text class="label">3. computed 计算属性(字数统计)</text>
      <view>标题字数:{{ titleLength }}</view>
    </view>

    <view class="section">
      <text class="label">4. watch 监听任务标题</text>
    </view>

    <view class="section">
      <text class="label">5. watchEffect 自动监听</text>
    </view>

    <view class="section">
      <text class="label">6. ref 获取DOM(自动聚焦)</text>
      <input ref="inputRef" class="input" placeholder="我会自动聚焦" />
    </view>

    <view class="section">
      <text class="label">7. 子组件通信</text>
      <TaskItem 
        :item="task" 
        @delete="handleDelete"
      />
    </view>
  </view>
</template>

<script setup>
import { 
  ref, 
  reactive, 
  computed, 
  watch, 
  watchEffect, 
  onMounted 
} from 'vue'

const count = ref(0)
const add = () => count.value++

const task = reactive({
  title: '',
  desc: ''
})


const titleLength = computed(() => {
  return task.title.length
})

watch(
  () => task.title,
  (newVal) => {
    console.log('watch 监听标题变化:', newVal)
  }
)

watchEffect(() => {
  console.log('watchEffect 自动监听:', task.desc)
})


const inputRef = ref(null)


onMounted(() => {
  console.log('页面挂载完成:onMounted')
  // 自动聚焦
  if (inputRef.value) {
    inputRef.value.focus()
  }
})


const TaskItem = {
  // 接收父组件参数
  props: {
    item: {
      type: Object,
      required: true
    }
  },

 
  emits: ['delete'],

  setup(props, { emit }) {
    const deleteTask = () => {
      emit('delete', '删除成功')
    }
    return { deleteTask }
  },

  template: `
    <view class="task-box">
      <view>子组件接收:{{ item.title }}</view>
      <button @click="deleteTask" size="mini">通知父组件删除</button>
    </view>
  `
}


const handleDelete = (msg) => {
  uni.showToast({ title: msg })
}
</script>

<style scoped>
.container {
  padding: 30rpx;
}
.title {
  font-size: 36rpx;
  font-weight: bold;
  text-align: center;
  margin-bottom: 40rpx;
}
.section {
  margin-bottom: 40rpx;
}
.label {
  font-weight: bold;
  font-size: 28rpx;
  margin-bottom: 15rpx;
  display: block;
}
.input {
  border: 1rpx solid #eee;
  padding: 20rpx;
  border-radius: 10rpx;
  margin-bottom: 10rpx;
}
.task-box {
  padding: 20rpx;
  background: #f9f9f9;
  border-radius: 10rpx;
}
</style>
相关推荐
threelab8 小时前
Three.js 黑洞引力效果着色器 | 三维可视化 / AI 提示词
开发语言·javascript·着色器
心中有国也有家8 小时前
CANN 算子开发完全指南——从 TBE DSL 到算子上线全流程
人工智能·经验分享·笔记·分布式·算法
Sahadev_8 小时前
GitMemo 安卓版发布了:现在可以随时随地查看和记录自己的笔记
android·笔记·创业创新
会编程的土豆8 小时前
消息队列(MQ)入门笔记
java·笔记·spring
atomicmaker8 小时前
进程/线程?并发/并行?
经验分享·笔记·其他
এ慕ོ冬℘゜8 小时前
JS 前端基础高频面试题
开发语言·前端·javascript
放下华子我只抽RuiKe58 小时前
React 从入门到生产(八):测试与部署
前端·javascript·深度学习·react.js·前端框架·ecmascript·集成学习
Dxy12393102168 小时前
JS列表获取指定范围值的 N 种方法
开发语言·javascript·ecmascript
蜡笔小电芯8 小时前
【Electron】第2章—BrowserWindow 与 Electron 窗口机制
前端·javascript·electron