当前位置: 首页 > 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/281166.html

相关文章:

  • 深圳南山 网站建设福建键seo排名
  • 交互设计师工资一般多少周口网站seo
  • 男女做暖暖网站广州网站营销推广
  • 娱乐网站后缀是什么windows优化大师电脑版
  • 网站二维码收费怎么做推广代理平台
  • 郑州做食用菌配送的网站广东广州网点快速网站建设
  • wordpress当前文章id邯郸seo优化
  • 网站制作网站建网站优化方案
  • 安徽美丽乡村建设网站全媒体广告投放平台
  • 签约网站做PPT深圳推广公司哪家好
  • 网站买东西第三方怎么做aso搜索排名优化
  • 如何把做的网站与域名连接泰安网站推广优化
  • 制冷 网站建设 中企动力重庆seo整站优化
  • 云服务器多网站解析推广接单平台
  • 咸宁网站建设哪家好夜夜草
  • 湖北广水最新疫情最新消息seo论坛
  • 凡人网站建设sem是什么缩写
  • 做电影网站会违法吗百度搜索引擎广告位的投放
  • 百度快照网站怎么做虚拟主机搭建网站
  • 苏州网站建设价格短视频推广策略
  • 中国人民解放军战略支援部队长沙官网seo推广
  • 杭州做网站哪家好广州网站维护
  • 网站制作要多少钱上海做推广的引流公司
  • 中国的网站域名是什么百度竞价排名的优缺点
  • 创建站点如何做网站武汉网站排名推广
  • 临时工找工作网站做美缝百度怎么注册公司网站
  • 大连网站的优化网络推广需要花多少钱
  • 买网站源码的网站域名注册商怎么查
  • 打开网站代码怎么做百度推广平台
  • 网站需要续费吗百度的广告