当前位置: 首页 > wzjs >正文

比较好的网站建设全媒体运营师培训机构

比较好的网站建设,全媒体运营师培训机构,在工商网站上怎么做电话的变更,长沙房产网签查询系统目录 一、ref和reactive的区别 1. ref 2. reactive 3、核心区别 4、原理差异 1. ref 的实现 2. reactive 的实现 5、常见误区 二、计算属性(Computed) 1. 基本用法 2. 计算属性的 setter 用法 3. 计算属性的特点 三、Watch 的使用 1. 基础监…

目录

一、ref和reactive的区别

1. ref

2. reactive

3、核心区别

4、原理差异

1. ref 的实现

2. reactive 的实现

5、常见误区

二、计算属性(Computed)

1. 基本用法

2. 计算属性的 setter 用法

3. 计算属性的特点

三、Watch 的使用

1. 基础监听(watch 函数)

2. 深度监听(对象属性)

3. 立即执行监听(immediate 选项)

4. watchEffect 自动追踪依赖

四、计算属性 vs Watch 的选择

 五、生命周期API

六、组合式API下的组件间数据传递

一、父传子:通过 props 传递数据

二、子传父:通过 emits 触发事件

三、双向绑定:v-model 语法糖

四、provide/inject:跨层级通信

五、使用 $parent 和 $children(不推荐)

六、使用事件总线或状态管理

总结

七、组合式API下的模板引用

一、组合式 API 中的模板引用

示例:获取 DOM 元素

示例:获取组件实例

二、使用 $refs(选项式 API 风格)

三、动态绑定引用

四、组件引用与跨组件访问

五、注意事项

总结


一、ref和reactive的区别

1. ref

  • 用途:创建一个响应式的值类型(如 numberstringboolean)或引用类型(如对象、数组)。
  • 语法const count = ref(0)
  • 访问方式:通过 .value 访问值(如 count.value)。

2. reactive

  • 用途:创建一个响应式的对象数组(引用类型)。
  • 语法const state = reactive({ count: 0 })
  • 访问方式:直接访问属性(如 state.count)。

3、核心区别

特性refreactive
适用类型任意类型(值类型或引用类型)仅对象或数组(引用类型)
创建方式ref(initialValue)reactive(object)
访问方式通过 .value 访问(如 count.value直接访问属性(如 state.count
响应式原理使用 Object.defineProperty() 或 Proxy仅使用 Proxy
深层响应式引用类型(对象 / 数组)自动深层响应式自动深层响应式
解构后响应性解构后失去响应性,需使用 toRefs 保留解构后仍保持响应性
性能基本类型(值类型)更高效对象 / 数组的操作更高效

4、原理差异

1. ref 的实现

  • 本质是一个对象,包含 value 属性:
    class RefImpl {constructor(value) {this._value = value; // 原始值this.value = value;  // 响应式值// 通过 getter/setter 拦截 value 的读写}
    }
    
  • 对于基本类型,使用 Object.defineProperty() 拦截 value 的读写。
  • 对于引用类型,内部调用 reactive() 转为深层响应式对象。

2. reactive 的实现

  • 使用 ES6 的 Proxy 拦截整个对象的属性读写:
    function reactive(target) {return new Proxy(target, {get(target, key) {// 依赖收集return target[key];},set(target, key, value) {// 触发更新target[key] = value;return true;}});
    }
    
  • 自动深层响应式:访问嵌套对象时,递归创建 Proxy。

5、常见误区

  1. ref 在模板中无需 .value
    Vue 3 模板会自动解包 ref,直接使用 {{ count }} 即可。

  2. reactive 不能替代 ref
    reactive 无法处理基本类型(如 number),必须使用 ref

  3. 解构 reactive 的注意事项
    解构后属性的响应性依赖于原始对象,若重新赋值会失去响应性。

二、计算属性(Computed)

计算属性是 Vue3 中用于处理复杂数据逻辑的重要特性,基于响应式依赖进行缓存,只有当依赖的值发生变化时才会重新计算。

1. 基本用法

计算属性通过 computed 来定义,接受一个 getter 函数或包含 getter/setter 的对象:

<template><div><p>原值: {{ firstName }} {{ lastName }}</p><p>计算属性值: {{ fullName }}</p><p>计算属性(缓存演示): {{ cachedComputed }}</p><p>普通函数: {{ getFullName() }}</p></div>
</template><script setup>
import { ref, computed } from 'vue';const firstName = ref('John');
const lastName = ref('Doe');
const age = ref(30);// 基础计算属性(getter 形式)
const fullName = computed(() => {return firstName.value + ' ' + lastName.value;
});// 带缓存的计算属性演示
const cachedComputed = computed(() => {console.log('计算属性被调用');return age.value > 18 ? '成年人' : '未成年人';
});// 普通函数(非响应式缓存)
const getFullName = () => {console.log('普通函数被调用');return firstName.value + ' ' + lastName.value;
};
</script>

2. 计算属性的 setter 用法

计算属性不仅可以读取,还可以通过对象形式定义 setter 实现双向绑定:

<template><div><input v-model="fullName" /><p>名: {{ firstName }}</p><p>姓: {{ lastName }}</p></div>
</template><script setup>
import { ref, computed } from 'vue';const firstName = ref('');
const lastName = ref('');// 带 setter 的计算属性
const fullName = computed({get() {return firstName.value + ' ' + lastName.value;},set(value) {const [first, last] = value.split(' ');firstName.value = first;lastName.value = last;}
});
</script>

3. 计算属性的特点

  • 响应式依赖:只在依赖的响应式数据变化时重新计算
  • 缓存机制:避免重复计算,提升性能
  • 简洁语法:相比函数调用更直观,适合处理模板中的复杂逻辑

三、Watch 的使用

Watch(监听器)用于监听数据变化,并在变化时执行回调函数,适用于需要在数据变化时触发副作用的场景。

1. 基础监听(watch 函数)

<template><div><input v-model="message" /><p>输入内容: {{ message }}</p></div>
</template><script setup>
import { ref, watch } from 'vue';const message = ref('');// 监听单个 ref 类型数据(注意ref对象在watch中不用加.value)
watch(message, (newValue, oldValue) => {console.log('值变化了:', newValue, '旧值:', oldValue);// 执行副作用操作
});// 监听多个数据(数组形式)
const count = ref(0);
watch([message, count], ( [newcount, newmessage], [oldcount, oldmessage]) => {console.log('message 或 count 变化了');
});
</script>

2. 深度监听(对象属性)

对于对象类型的数据,需要深度监听才能捕获属性变化:

<template><div><input v-model="user.name" /><input v-model="user.age" /></div>
</template><script setup>
import { ref, reactive, watch } from 'vue';const user = reactive({name: '张三',age: 18
});// 深度监听对象属性(方法一:开启 deep 选项)
watch(() => user,(newValue, oldValue) => {console.log('用户信息变化了');},{ deep: true }
);// 深度监听对象属性(方法二:直接监听属性)
watch(() => user.name,(newName) => {console.log('用户名变化了:', newName);}
);
</script>

注意当监听的是reactive对象时,watch的第一个参数 需要写为函数的形式。

当监听的是ref对象时,watch的第一个参数为普通的变量名的形式。

监听目标第一个参数写法是否需要 deep 选项
ref 变量count

ref 对象的单个属性(精确监听)() => user.value.age
reactive 对象的属性() => user.name
整个 reactive 对象() => user
多个数据源[count, () => user.age]部分情况需要
计算属性式的监听值() => obj.a * obj.b

3. 立即执行监听(immediate 选项)

<template><div><p>当前状态: {{ status }}</p></div>
</template><script setup>
import { ref, watch } from 'vue';const status = ref('init');// 组件挂载后立即执行一次监听回调
watch(status,(newStatus) => {console.log('状态变化:', newStatus);},{ immediate: true }
);
</script>

4. watchEffect 自动追踪依赖

watchEffect 会自动追踪回调函数中的响应式依赖,适用于需要立即执行且自动追踪依赖的场景:

<template><div><input v-model="count" /><p>计算结果: {{ result }}</p></div>
</template><script setup>
import { ref, watchEffect } from 'vue';const count = ref(0);
let result = 0;// 自动追踪 count 的变化
watchEffect(() => {result = count.value * 2;console.log('依赖变化,重新计算');
});
</script>

四、计算属性 vs Watch 的选择

场景计算属性Watch
数据转换✅(推荐)
异步操作✅(推荐)
副作用(如 API 调用)✅(推荐)
多依赖组合✅(推荐)
立即执行✅(通过 immediate 选项)

 五、生命周期API

阶段选项式 API组合式 API触发时机
创建阶段beforeCreate相当于setup实例创建之前,数据观测和事件配置尚未初始化。
created实例创建完成,数据观测和事件已配置,但 DOM 尚未生成。
挂载阶段beforeMountonBeforeMount模板编译完成,即将开始渲染 DOM 前。
mountedonMountedDOM 挂载完成后触发,可访问 DOM 元素。
更新阶段beforeUpdateonBeforeUpdate数据更新导致组件重新渲染前,此时 DOM 尚未更新。
updatedonUpdated组件更新完成,DOM 已同步更新后触发。
卸载阶段beforeUnmountonBeforeUnmount组件即将卸载前,可用于清理定时器、事件监听等资源。
unmountedonUnmounted组件已卸载,所有子组件也已卸载完成。
错误处理errorCapturedonErrorCaptured捕获到组件或子组件的错误时触发,可用于错误日志记录。
服务器渲染serverPrefetchonServerPrefetch(仅服务端渲染)组件在服务器端渲染前触发,用于数据预获取。

六、组合式API下的组件间数据传递

一、父传子:通过 props 传递数据

父组件通过 defineProps 声明并传递数据,子组件通过 defineProps 接收。

父组件

<!-- Parent.vue -->
<template><Child :message="parentMessage" :count="parentCount" />
</template><script setup>
import { ref } from 'vue';
import Child from './Child.vue';const parentMessage = ref('Hello from parent');
const parentCount = ref(100);
</script>

子组件

<!-- Child.vue -->
<template><div><p>Received message: {{ message }}</p><p>Received count: {{ count }}</p></div>
</template><script setup>
//import { defineProps } from 'vue'; 可以不引入// 定义 props 类型和默认值
const props = defineProps({message: String,//定义类型count: {type: Number,default: 0}
});// 使用 props
console.log(props.message); // "Hello from parent"
</script>

二、子传父:通过 emits 触发事件

子组件通过 defineEmits 声明事件,通过 emit 触发,父组件监听事件并处理。

子组件

<!-- Child.vue -->
<template><button @click="sendDataToParent">Send to Parent</button>
</template><script setup>
//import { defineEmits } from 'vue'; 可以不用引入// 定义可触发的事件
const emit = defineEmits(['updateData', 'customEvent']);// 触发事件并传递数据
const sendDataToParent = () => {emit('updateData', 'Data from child');emit('customEvent', { key: 'value' });
};
</script>

父组件

<!-- Parent.vue -->
<template><Child @updateData="handleUpdate" @customEvent="handleCustom" />
</template><script setup>
import Child from './Child.vue';// 处理子组件事件
const handleUpdate = (data) => {console.log('Received from child:', data); // "Data from child"
};const handleCustom = (payload) => {console.log('Custom event payload:', payload); // { key: 'value' }
};
</script>

三、双向绑定:v-model 语法糖

通过 v-model 实现父子组件的双向数据流动,子组件通过 update:propName 事件更新父组件数据。

父组件

<!-- Parent.vue -->
<template><!-- 默认 v-model --><Child v-model="parentValue" /><!-- 自定义 prop 和事件名 --><Child v-model:title="parentTitle" />
</template><script setup>
import { ref } from 'vue';
import Child from './Child.vue';const parentValue = ref('Initial value');
const parentTitle = ref('Initial title');
</script>

子组件

<!-- Child.vue -->
<template><input type="text" :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" /><input type="text" :value="title" @input="$emit('update:title', $event.target.value)" />
</template><script setup>
import { defineProps, defineEmits } from 'vue';// 默认 v-model 对应 modelValue prop
const props = defineProps({modelValue: String,title: String
});const emit = defineEmits(['update:modelValue', 'update:title']);
</script>

四、provide/inject:跨层级通信

父组件通过 provide 提供数据,任意层级的子组件通过 inject 获取数据,无需逐级传递。

祖先组件

<!-- Ancestor.vue -->
<template><ChildComponent />
</template><script setup>
import { provide, ref } from 'vue';
import ChildComponent from './ChildComponent.vue';// 提供响应式数据
const sharedData = ref('Shared data from ancestor');// 提供方法
const updateSharedData = (newValue) => {sharedData.value = newValue;
};// 注入 provide
provide('sharedData', sharedData);
provide('updateSharedData', updateSharedData);
</script>

任意层级子组件

<!-- AnyChild.vue -->
<template><div><p>Shared data: {{ sharedData }}</p><button @click="updateData">Update Shared Data</button></div>
</template><script setup>
import { inject } from 'vue';// 注入数据
const sharedData = inject('sharedData');
const updateSharedData = inject('updateSharedData');const updateData = () => {updateSharedData('New value from child');
};
</script>

如果想让子孙组件修改父组件中的参数,可以把方法写在父组件中,通过provide和inject把方法传递给子孙组件,子孙组件调用这个方法来修改参数 

五、使用 $parent 和 $children(不推荐)

通过 $parent 访问父组件实例,通过 $children 访问子组件实例。这种方式破坏了组件封装性,不推荐在大型项目中使用。

子组件

<!-- Child.vue -->
<script setup>
import { getCurrentInstance } from 'vue';const instance = getCurrentInstance();// 访问父组件数据或方法
const parentData = instance.parent.data;
instance.parent.someMethod();
</script>

六、使用事件总线或状态管理

对于复杂场景,可使用第三方库(如 Pinia、Vuex)或自定义事件总线实现组件通信。

总结

通信方式适用场景优点缺点
props父 → 子单向数据流简单直观,类型安全只能单向传递
emits子 → 父事件触发语义明确,便于调试多层级时需逐级传递
v-model双向数据绑定语法简洁,代码量少依赖特定事件名(update:propName)
provide/inject跨层级数据共享无需逐级传递,支持响应式依赖注入键,调试困难
\(parent/\)children直接访问组件实例(不推荐)快速获取实例破坏封装性,耦合度高

在实际开发中,推荐优先使用 props 和 emits 实现单向数据流,复杂场景使用 provide/inject 或状态管理库。

七、组合式API下的模板引用

模板引用允许在 JavaScript 中直接访问 DOM 元素或组件实例,通常用于

  • 手动操作 DOM(如聚焦、滚动)
  • 调用子组件的方法
  • 获取组件状态

一、组合式 API 中的模板引用

在组合式 API 中,模板引用通过 ref() 创建,并通过 v-bind 绑定到元素或组件上。

示例:获取 DOM 元素

<template><div><input ref="inputRef" type="text" /><button @click="focusInput">聚焦输入框</button></div>
</template><script setup>
import { ref, onMounted } from 'vue';// 创建模板引用
const inputRef = ref(null);// 访问 DOM 元素
const focusInput = () => {inputRef.value.focus(); // 调用 DOM 方法
};// 在 mounted 钩子中访问 DOM
onMounted(() => {console.log(inputRef.value); // <input type="text">
});
</script>

示例:获取组件实例

<template><ChildComponent ref="childRef" /><button @click="callChildMethod">调用子组件方法</button>
</template><script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';// 获取子组件实例
const childRef = ref(null);const callChildMethod = () => {childRef.value.someMethod(); // 调用子组件方法
};
</script>

二、使用 $refs(选项式 API 风格)

在组合式 API 中,也可以通过 getCurrentInstance 访问 $refs

<template><div ref="container">容器</div>
</template><script setup>
import { getCurrentInstance, onMounted } from 'vue';const instance = getCurrentInstance();onMounted(() => {console.log(instance.refs.container); // 访问 $refs
});
</script>

三、动态绑定引用

模板引用可以动态绑定到不同元素:

<template><div><button @click="changeRef">切换引用</button><div v-if="showA" ref="currentRef">元素 A</div><div v-else ref="currentRef">元素 B</div></div>
</template><script setup>
import { ref } from 'vue';const currentRef = ref(null);
const showA = ref(true);const changeRef = () => {showA.value = !showA.value;// 切换后,currentRef 会指向新的元素
};
</script>

四、组件引用与跨组件访问

在子组件中暴露方法供父组件调用:

<!-- ChildComponent.vue -->
<script setup>
//import { defineExpose } from 'vue'; 可以不引入const count = ref(0);const increment = () => {count.value++;
};// 暴露方法和属性给父组件
defineExpose({increment,count
});
</script>
<!-- ParentComponent.vue -->
<template><ChildComponent ref="childRef" /><button @click="childRef.value.increment()">调用子组件方法</button>
</template><script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';const childRef = ref(null);
</script>

五、注意事项

  1. 引用值的延迟
    模板引用在初始渲染时为 null,只有在组件挂载后才会指向实际元素。建议在 onMounted 或之后访问。

  2. 与响应式数据的区别
    模板引用不是响应式的,其值变化不会触发重新渲染。

  3. 组合式 API 与选项式 API 的区别

    • 组合式 API:通过 ref() 创建引用变量。
    • 选项式 API:通过 this.$refs 访问引用。
  4. 函数式组件的引用
    函数式组件需要显式接受 ref 参数并通过 forwardRef 转发。

总结

特性说明
创建引用使用 ref(null) 创建,初始值为 null
绑定到元素使用 ref="refName" 绑定到 DOM 元素或组件。
访问引用通过 refName.value 访问实际元素或组件实例。
组件暴露使用 defineExpose() 暴露子组件的方法和属性。
动态引用支持动态绑定到不同元素,值会自动更新。
http://www.dtcms.com/wzjs/190906.html

相关文章:

  • 网站建设 域名 服务器百度下载安装最新版
  • 给人做代工的网站百度推广代理公司
  • 泉州做网站价格百度竞价返点开户
  • app网站开发书籍下载太原百度seo
  • 做网站普洱百度如何快速收录网站
  • 做网站主页图片一般多少m免费域名注册服务网站
  • 中卫市住房和城乡建设局网站免费推广app软件下载
  • 网站 百度搜不到淘宝推广工具
  • 给传销做网站线下推广都有什么方式
  • 开发动态网站有哪些技术东莞百度网站排名优化
  • 怎么做单页网站百度云盘网官网
  • 商务网站开发网站管理与维护
  • 搭建网站钱西安百度关键词排名服务
  • 做调研的网站有哪些快速优化排名公司推荐
  • 一台vps可以做几个网站seo研究学院
  • 网站制作平台seo是什么意思知乎
  • cms 做网站模板seo sem是什么意思
  • 宁波信誉好品牌网站设计地址市场调研表模板
  • 怎样做营销型网站推广seo站长工具平台
  • 遵义网站建设哪家好广州新闻最新消息今天
  • 免费网站服务器安全做小程序公司哪家好
  • 天津做网站贵吗互联网项目推广平台有哪些
  • 确定网站的主题与风格如何创建一个app
  • 黑龙江建设教育信息网官网内部优化
  • 郑州模板建站系统视频号链接怎么获取
  • 怎么样在网站文章最后做超链接seo网络培训学校
  • 北京网络公司网站谷歌浏览器2021最新版
  • 网站建设业务越做越累百度浏览器下载官方免费
  • 网站建设zvge网址导航浏览器下载
  • 安卓手机编程软件疫情二十条优化措施