项目场景:

在父组件上provide(ref对象) 子组件无法通过computed完成响应的问题,并进行v-bind 进行项目绑定的问题

下面是我遇到的问题

<!-- eslint-disable vue/multi-word-component-names -->

<template>
  <div class="app">
    <h2>多状态表单切换系统</h2>
    <select v-model="selectValue">
    <option value="red">深色模式</option>
    <option value="black">浅色模式</option>
    </select>
    
    <!-- 切换按钮组 -->
    <div class="btn-group">
      <button @click="currentForm = LoginForm" class="switch-btn">登录</button>
      <button @click="currentForm = RegisterForm" class="switch-btn">注册</button>
      <button @click="currentForm = ForgotPwdForm" class="switch-btn">忘记密码</button>
    </div>
    <!-- KeepAlive包裹动态组件:实现状态缓存 -->
    <KeepAlive include="logn,register">
      <component :is="currentForm">
        <!-- 具名插槽:为不同表单传递自定义标题 -->
        <template #title v-if="currentForm === LoginForm">
          <h3 class="form-title">用户登录</h3>
        </template>
        <template #title v-else-if="currentForm === RegisterForm">
          <h3 class="form-title">账号注册</h3>
        </template>
        <template #title v-else>
          <h3 class="form-title">密码重置</h3>
        </template>
      </component>
    </KeepAlive>
  </div>
</template>

<script setup>
import { shallowRef,ref, provide } from 'vue'
// 导入子组件:setup语法糖下自动局部注册
import LoginForm from './logn.vue'
import RegisterForm from './register.vue'
import ForgotPwdForm from './forget1.vue'

// 响应式组件引用:使用shallowRef避免深层响应式开销
const currentForm = shallowRef(LoginForm)
const selectValue = ref('red')

//使用watch来监视值得变化然后我使用provide来发送change
//我操了本来很简单但provide只能用在setup 中

 provide("change",selectValue)
</script>

<style scoped>
.app {
  padding: 30px;
  max-width: 400px;
  margin: 0 auto;
}
.app h2 {
  color: #2c3e50;
  text-align: center;
  margin-bottom: 20px;
}
.btn-group {
  display: flex;
  gap: 10px;
  margin-bottom: 20px;
}
.switch-btn {
  flex: 1;
  padding: 10px;
  background-color: #ecf0f1;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 16px;
}
.switch-btn:hover {
  background-color: #bdc3c7;
}
.form-title {
  color: #2c3e50;
  margin-top: 0;
  margin-bottom: 15px;
}
</style>

在父组件中我使用 provide(ref对象)放送了一个ref对象给它的子组件,如下所示,上面的是完整father.vue

const selectValue = ref('red')
//使用watch来监视值得变化然后我使用provide来发送change
//我操了本来很简单但provide只能用在setup 中
 provide("change",selectValue)

那我在子组件中如何接收

下面是我错误的做法,以及son.vue 的完整代码

<template>
 <div class="form-container" :style="{'background-color':color1}">
   <!-- 标题插槽:支持父组件自定义标题 -->
   <slot name="title">默认登录标题</slot>
   <div class="form-content" >
     <input v-model="username" placeholder="请输入用户名" class="form-input" />
     <input v-model="password" type="password" placeholder="请输入密码" class="form-input" />
     <div class="form-checkbox">
       <input type="checkbox" v-model="rememberMe" id="remember" />
       <label for="remember">记住我</label>
     </div>
     <button class="form-btn">登录</button>
   </div>
 </div>
</template>

<script setup>
import { ref, onMounted, onActivated, onDeactivated,inject, computed, onUpdated} from 'vue'

// 表单绑定数据
const username = ref('')
const password = ref('')
const rememberMe = ref(false)

// 生命周期监听:打印组件状态
onMounted(() => {
 console.log('登录表单组件已挂载')
})
onActivated(() => {
 console.log('登录表单组件被激活')
})
onDeactivated(() => {
 console.log('登录表单组件已缓存')
})
//下面我使用
// const injectedColor = inject('change', 'red') // 默认值 'red'

// 如果父组件提供的是 ref,则直接使用;如果是普通值,则创建 ref
// const color = ref(injectedColor)
const color =ref('red')
color.value= inject('change')
// 计算属性:返回颜色值
const color1 = computed(() => {
 return color.value
})


</script>

<style scoped>
.form-container {
 border: 1px solid #eee;
 border-radius: 8px;
 padding: 20px;
 width: 350px;
}
.form-input {
 width: 100%;
 padding: 10px;
 margin: 8px 0;
 border: 1px solid #ddd;
 border-radius: 4px;
 box-sizing: border-box;
}
.form-checkbox {
 margin: 10px 0;
 font-size: 14px;
}
.form-btn {
 width: 100%;
 padding: 10px;
 background-color: #42b983;
 color: #fff;
 border: none;
 border-radius: 4px;
 cursor: pointer;
}
.dlight{
 background-color: red;
}
</style>

错误的点在于下面,如果我接收了父组件传来的ref对象我这个代码就会无法响应

const color =ref('red')
 color.value= inject('change')
// 计算属性:返回颜色值
const color1 = computed(() => {
  return color.value
})

如何解决

1. 父组件直接传递数据而不是传递ref 对象

就可以直接使用原方法的方法

2. 父组件传递 ref对象的解决方法

  1. 既然是ref 对象 然后你又封装了一个ref对象给父组件传递的ref对象就相当于两个ref了,这个时候我们使用ref对象.value.value就可以解决了
const color =ref('red')
 color.value= inject('change')
// 计算属性:返回颜色值
const color1 = computed(() => {
  return color.value.value
})
  1. 直接使用 const 来接收 ref对象,如何就可以直接color.value 也可以直接解决问题
 const color= inject('change')
// 计算属性:返回颜色值
const color1 = computed(() => {
  return color.value
})
const injectedColor = inject('change', 'red') // 默认值 'red'

// 如果父组件提供的是 ref,则直接使用;如果是普通值,则创建 ref
const color = ref(injectedColor)

// 计算属性:返回颜色值
const color1 = computed(() => {
  return color.value
})
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐