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

太原做网站公司哪家好友情链接有哪些展现形式

太原做网站公司哪家好,友情链接有哪些展现形式,wordpress怎么读,有云服务器怎么做网站ref 属性 与 props 一、核心概念对比 特性ref (标签属性)props作用对象DOM 元素/组件实例组件间数据传递数据流向父组件访问子组件/DOM父组件 → 子组件响应性直接操作对象单向数据流(只读)使用场景获取 DOM/调用子组件方法组件参数传递Vue3 变化不再自…

ref 属性 与 props

一、核心概念对比

特性ref (标签属性)props
作用对象DOM 元素/组件实例组件间数据传递
数据流向父组件访问子组件/DOM父组件 → 子组件
响应性直接操作对象单向数据流(只读)
使用场景获取 DOM/调用子组件方法组件参数传递
Vue3 变化不再自动数组形式需要 defineProps 声明

二、ref 属性的深度解析

1. 基础用法
<!-- 获取 DOM 元素 -->
<template><input ref="inputRef" type="text"><ChildComponent ref="childRef" />
</template><script setup>
import { ref, onMounted } from 'vue'// DOM 引用
const inputRef = ref(null)// 组件引用
const childRef = ref(null)onMounted(() => {inputRef.value.focus() // 操作 DOMchildRef.value.sayHello() // 调用子组件方法
})
</script>
2. 组件引用规范
// 子组件 ChildComponent.vue
<script setup>
// 必须暴露方法才能被父组件调用
defineExpose({sayHello: () => console.log('Hello from child!'),childData: ref('子组件数据')
})
</script>
3. 类型安全(TypeScript)
// 父组件中定义组件引用类型
import ChildComponent from './ChildComponent.vue'const childRef = ref<InstanceType<typeof ChildComponent>>()

三、props 的响应式处理

1. 基础声明
<!-- 父组件 -->
<ChildComponent :title="parentTitle" /><!-- 子组件 -->
<script setup>
const props = defineProps({title: {type: String,required: true}
})
</script>
2. 保持响应性
// 正确方式:使用 toRef
import { toRef } from 'vue'const title = toRef(props, 'title')// 错误!直接解构会失去响应性
// const { title } = props

四、联合使用场景

场景:表单验证组件
<!-- 父组件 -->
<template><ValidationForm ref="formRef" :rules="validationRules"@submit="handleSubmit"/>
</template><script setup>
const formRef = ref(null)
const validationRules = ref({/* 验证规则 */})// 调用子组件方法
const validateForm = () => {formRef.value.validate()
}
</script>
<!-- 子组件 ValidationForm.vue -->
<script setup>
defineProps(['rules'])const validate = () => {// 执行验证逻辑
}// 暴露方法给父组件
defineExpose({ validate })
</script>

五、核心差异总结

对比维度ref (标签属性)props
数据方向父 → 子(操作子组件/DOM)父 → 子(数据传递)
可修改性可直接修改子组件暴露的内容只读(需通过事件通知父组件修改)
响应式机制直接引用对象需要 toRef 保持响应性
典型应用DOM操作/调用子组件方法组件参数配置
组合式 API通过 ref() 创建引用通过 defineProps 声明

六、最佳实践指南

1. ref 使用原则
  • 最小化暴露:只暴露必要的组件方法/数据

  • 避免直接修改:不要通过 ref 直接修改子组件状态

  • 配合 TypeScript:使用类型定义确保安全访问

2. props 使用规范
  • 只读原则:始终视 props 为不可变数据

  • 响应式转换:使用 toRef 处理需要响应式的 props

  • 明确验证:始终定义 props 的类型验证


七、常见问题解决

Q1: 为什么通过 ref 访问子组件属性得到 undefined

原因:子组件未通过 defineExpose 暴露属性
解决方案

// 子组件
defineExpose({publicMethod: () => {/* ... */}
})
Q2: 如何同时使用 ref 和 v-for
<template><ChildComponent v-for="item in list" :key="item.id":ref="setItemRef"/>
</template><script setup>
const itemRefs = ref([])const setItemRef = el => {if (el) itemRefs.value.push(el)
}
</script>
Q3: 如何类型安全地组合 ref 和 props
// 父组件
import ChildComponent from './ChildComponent.vue'type ChildComponentExpose = {validate: () => boolean
}const childRef = ref<ChildComponentExpose>()// 子组件
defineExpose<ChildComponentExpose>({validate: () => true
})

八、综合应用示例

父组件

<template><UserFormref="userForm":user-data="formData"@submit="handleSubmit"/><button @click="validateForm">验证表单</button>
</template><script setup lang="ts">
import { ref } from 'vue'
import UserForm from './UserForm.vue'type UserFormExpose = {validate: () => booleanresetForm: () => void
}const userForm = ref<UserFormExpose>()
const formData = ref({ name: '', email: '' })const validateForm = () => {if (userForm.value?.validate()) {console.log('表单验证通过')}
}const handleSubmit = (data) => {console.log('提交数据:', data)
}
</script>

子组件 UserForm.vue

<template><form @submit.prevent="submitForm"><input v-model="localData.name"><input v-model="localData.email"><button type="submit">提交</button></form>
</template><script setup lang="ts">
import { ref, toRefs } from 'vue'const props = defineProps<{userData: {name: stringemail: string}
}>()const emit = defineEmits(['submit'])// 本地副本(避免直接修改 props)
const localData = ref({ ...props.userData })const validate = () => {return localData.value.name.length > 0 && localData.value.email.includes('@')
}const resetForm = () => {localData.value = { name: '', email: '' }
}const submitForm = () => {emit('submit', localData.value)
}defineExpose({validate,resetForm
})
</script>

关键总结:

  1. ref 属性:用于直接访问 DOM/子组件实例,需要配合 defineExpose 使用

  2. props:用于父组件向子组件传递数据,需保持只读特性

  3. 协作模式

    • 父组件通过 props 传递数据

    • 子组件通过事件通知父组件

    • 必要时通过 ref 调用子组件方法

  4. 类型安全:使用 TypeScript 类型定义确保可靠访问


事件传递

在 Vue3 中,子组件向父组件传递数据主要通过 事件机制 实现。以下是 5 种主要实现方式及其使用场景:


一、基础事件传递 (推荐)

实现方式
子组件触发自定义事件 → 父组件监听事件

<!-- 子组件 ChildComponent.vue -->
<script setup>
const emit = defineEmits(['sendData']) // 声明事件const sendToParent = () => {emit('sendData', { message: 'Hello from child!' }) // 触发事件
}
</script><template><button @click="sendToParent">发送数据</button>
</template>
<!-- 父组件 ParentComponent.vue -->
<template><ChildComponent @send-data="handleData" />
</template><script setup>
const handleData = (payload) => {console.log(payload.message) // 输出:Hello from child!
}
</script>

最佳实践

  • 使用 kebab-case 事件名(如 send-data

  • 通过 TypeScript 定义事件类型:

    const emit = defineEmits<{(e: 'sendData', payload: { message: string }): void
    }>()

二、v-model 双向绑定 (表单场景推荐)

实现原理
v-model 是 :modelValue + @update:modelValue 的语法糖

<!-- 子组件 InputComponent.vue -->
<script setup>
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])const updateValue = (e) => {emit('update:modelValue', e.target.value)
}
</script><template><input :value="modelValue" @input="updateValue">
</template>
<!-- 父组件 -->
<template><InputComponent v-model="inputValue" />
</template><script setup>
const inputValue = ref('')
</script>

多 v-model 绑定

<ChildComponent v-model:name="userName"v-model:age="userAge"
/>

三、异步回调模式 (需要返回值时)

适用场景:需要等待父组件处理结果的异步操作

<!-- 子组件 -->
<script setup>
const emit = defineEmits(['request'])const handleClick = async () => {const response = await emit('request', { id: 123 })console.log('父组件返回:', response)
}
</script>
<!-- 父组件 -->
<template><ChildComponent @request="handleRequest" />
</template><script setup>
const handleRequest = async (payload) => {const data = await fetchData(payload.id)return data // 返回给子组件
}
</script>

四、Expose 方法调用 (需要直接访问子组件)

<!-- 子组件 -->
<script setup>
const childData = ref('子组件数据')defineExpose({getData: () => childData.value,updateData: (newVal) => childData.value = newVal
})
</script>
<!-- 父组件 -->
<template><ChildComponent ref="childRef" />
</template><script setup>
const childRef = ref(null)const getChildData = () => {console.log(childRef.value?.getData()) // 输出:子组件数据childRef.value?.updateData('新数据')
}
</script>

五、状态管理方案 (跨组件通信)

适用场景:多层嵌套组件或兄弟组件通信

// store/counter.js
import { reactive } from 'vue'export const counterStore = reactive({count: 0,increment() {this.count++}
})
<!-- 子组件 -->
<script setup>
import { counterStore } from './store/counter'const updateCount = () => {counterStore.increment()
}
</script>
<!-- 父组件 -->
<script setup>
import { counterStore } from './store/counter'
</script><template>当前计数:{{ counterStore.count }}
</template>

方法对比表

方法适用场景优点缺点
基础事件传递简单数据传递直观明确多层嵌套时需逐层传递
v-model 绑定表单输入组件语法简洁仅适用简单双向绑定
异步回调模式需要父组件响应结果支持异步交互逻辑复杂度稍高
Expose 方法需要直接操作子组件灵活性强破坏组件封装性
状态管理跨组件/复杂场景解耦组件关系需要额外学习成本

最佳实践指南

  1. 优先使用事件传递:保持组件独立性

  2. 复杂场景用状态管理:Pinia 是 Vue3 官方推荐方案

  3. v-model 用于表单:保持双向绑定的简洁性

  4. 避免滥用 ref:防止组件过度耦合

  5. TypeScript 类型定义

    // 事件类型定义
    defineEmits<{(e: 'updateData', payload: { id: number }): void(e: 'cancel'): void
    }>()// Props 类型定义
    defineProps<{userId: numberuserName: string
    }>()

完整示例:购物车组件交互

<template><div class="cart-item"><span>{{ item.name }}</span><input type="number" :value="item.quantity"@input="updateQuantity($event.target.value)"><button @click="emit('remove', item.id)">删除</button></div>
</template><!-- 子组件 CartItem.vue -->
<script setup>
const props = defineProps({item: {type: Object,required: true}
})const emit = defineEmits(['update:quantity', 'remove'])const updateQuantity = (newQty) => {emit('update:quantity', {id: props.item.id, qty: newQty})
}
</script>
<template><CartItem v-for="item in cartItems":key="item.id":item="item"@update:quantity="handleUpdate"@remove="handleRemove"/>
</template><!-- 父组件 ShoppingCart.vue -->
<script setup>
const cartItems = ref([{ id: 1, name: '商品A', quantity: 2 },{ id: 2, name: '商品B', quantity: 1 }
])const handleUpdate = ({ id, qty }) => {const item = cartItems.value.find(i => i.id === id)if (item) item.quantity = Number(qty)
}const handleRemove = (id) => {cartItems.value = cartItems.value.filter(i => i.id !== id)
}
</script>

http://www.dtcms.com/wzjs/441792.html

相关文章:

  • 网站建设结课总结洛阳seo网站
  • 济南网站建设求职营销推广平台
  • 微信公众号的微网站怎么做网络营销专业学什么课程
  • 网站建设杭州哪家便宜个人建站
  • 金融网站设计欣赏品牌公关案例
  • 做视频网站要准备哪些资料怎么制作网页里面的内容
  • 那些网站做推广足球比赛今日最新推荐
  • 网站数据库密码修改了要怎么做软文案例大全300字
  • 怎么做刷题网站搜索自媒体平台
  • 网站首页标题字数网络营销的基本特征有哪七个
  • 淘宝上做网站的靠谱吗百度竞价入门教程
  • 有漏洞的网站凡科网小程序
  • 做公司网站棋牌吸引人的软文
  • bootstrap风格网站模板全网营销
  • ecshop二次开发网站开发心得大连网站排名推广
  • 个人做网站模版是否有人买seo自动推广工具
  • 做网站产品资料表格开发一个app需要多少钱
  • 做网站的是什么工程师网页优化方法
  • 做网站日入100比百度好用的搜索软件
  • 大型网站建设历史网站维护的主要内容
  • 电商网站开发费用网络广告营销典型案例
  • 视频网站后台功能济南网站优化
  • 网站免费源码下载百度云下载
  • 转运网站建设网站检测工具
  • 黄岩做网站营销方案的几个要素
  • 苏州住建网站网站功能优化的方法
  • 学会python做网站长沙seo推广公司
  • 怎么做免费的宣传网站网络营销站点推广的方法
  • 备案不关闭网站的方法怎样上百度做广告
  • 广州公司网站建设推广论坛软文案例