vue3新用法第二节

[1. 相关资源]

[2. 初始化项目]

  1. 安装 vue-cli3

    npm install -g @vue/cli
    # OR
    yarn global add @vue/cli

[3. setup]

setup() 函数是 vue3 中,专门为组件提供的新属性。它为我们使用 vue3 的 Composition API 新特性提供了统一的入口。

1、setup 函数时,它将接受两个参数:(props、context(包含attrs、slots、emit))

2、setup函数是处于 生命周期函数 beforeCreate 和 Created 两个钩子函数之前的函数

3、执行 setup 时,组件实例尚未被创建(在 setup() 内部,this 不会是该活跃实例的引用,即不指向vue实例,Vue 为了避免我们错误的使用,直接将 setup函数中的this修改成了 undefined)

4、与模板一起使用:需要返回一个对象 (在setup函数中定义的变量和方法最后都是需要 return 出去的 不然无法再模板中使用)

5、使用渲染函数:可以返回一个渲染函数,该函数可以直接使用在同一作用域中声明的响应式状态

注意事项:

1、setup函数中不能使用this。Vue 为了避免我们错误的使用,直接将 setup函数中的this修改成了 undefined)

2、setup 函数中的 props 是响应式的,当传入新的 prop 时,它将被更新。但是,因为 props 是响应式的,你不能使用 ES6 解构,因为它会消除 prop 的响应性。

如果需要解构 prop,可以通过使用 setup 函数中的toRefs 来完成此操作: 父传子,props

import { toRefs } from 'vue'

setup(props) { const { title } = toRefs(props)

console.log(title.value)
 onMounted(() => {
  console.log('title: ' + props.title)
})

}

子传父,事件 - Emitting Events

举例,现在我们想在点击提交按钮时触发一个login的事件。

在 Vue2 中我们会调用到this.$emit然后传入事件名和参数对象。

login () { this.$emit('login', { username: this.username, password: this.password }) }

在setup()中的第二个参数content对象中就有emit,这个是和this.$emit是一样的。那么我们只要在setup()接收第二个参数中使用分解对象法取出emit就可以在setup方法中随意使用了。

然后我们在login方法中编写登陆事件 另外:context 是一个普通的 JavaScript 对象,也就是说,它不是响应式的,这意味着你可以安全地对 context 使用 ES6 解构

setup (props, { attrs, slots, emit }) { // ... const login = () => { emit('login', { username: state.username, password: state.password }) }

// ...

}

3、 setup()内使用响应式数据时,需要通过.value获取

import { ref } from 'vue'

const count = ref(0) console.log(count.value) // 0

4、从 setup() 中返回的对象上的 property 返回并可以在模板中被访问时,它将自动展开为内部值。不需要在模板中追加 .value

5、setup函数只能是同步的不能是异步的

[3.1 执行时机]

setup 函数会在 beforeCreate 之后、created 之前执行

[3.2 接收 props 数据]

  1. props 中定义当前组件允许外界传递过来的参数名称:

    props: {
      p1: String
    }
  2. 通过 setup 函数的第一个形参,接收 props 数据:

    setup(props) {
        console.log(props.p1)
    }
import { reactive } from "@vue/composition-api";
​
export default {
  setup(props, ctx) {
    // console.log("setup");
    // console.log(props);
    // console.log(ctx);
​
    const state = reactive({ count: 0 });
​
    // console.log(state);
    // state.count += 1;
    // console.log(state)
​
    return state;
  },
  beforeCreate() {
    // console.log("beforeCreate");
  },
  created() {
    // console.log("created");
  },
  props: {
    p1: String
  }
};

[3.3 context]

setup 函数的第二个形参是一个上下文对象,这个上下文对象中包含了一些有用的属性,这些属性在 vue 2.x 中需要通过 this 才能访问到,在 vue 3.x 中,它们的访问方式如下:

const MyComponent = {
  setup(props, context) {
    context.attrs
    context.slots
    context.parent
    context.root
    context.emit
    context.refs
  }
}

注意:在 setup() 函数中无法访问到 this

context :上下文,包括 attrs 、 emit 、slots。 ① attrs :在此部分,接收在父组件传递过来的,并且没有在props中声明的参数参数。

② emit:子组件对父组件发送事件 在vue2中,子对父发送事件采用this.$emit对父组件发送事件,在vue3中子组件对父组件发送事件采用context.emit发送事件

// 在子组件中
<button @click="postMsg">
    我是子组件,我要向父组件发送事件了
</button>
​
// js 部分
setup(props,context){
    function postMsg(){
        console.log('我发送了')
        context.emit('pMSg',{msg:'我是子组件发送的信息'})
    }
    return {postMsg}
}
​
// 父组件中进行接收
<test @pMSg="func" />
    
// js 部分
setup(props,context){
    const func = (e)=>{
      console.log('子组件发送过来的信息',e)
    }
    return { func } 
 }
​

点击按键

[4. reactive]

reactive() 函数接收一个普通对象,返回一个响应式的数据对象。

[4.1 基本语法]

等价于 vue 2.x 中的 Vue.observable() 函数,vue 3.x 中提供了 reactive() 函数,用来创建响应式的数据对象,基本代码示例如下:

import { reactive } from '@vue/composition-api'
​
// 创建响应式数据对象,得到的 state 类似于 vue 2.x 中 data() 返回的响应式对象
const state = reactive({ count: 0 })

[4.2 定义响应式数据供 template 使用]

  1. 按需导入 reactive 函数:

    import { reactive } from '@vue/composition-api'
  2. setup() 函数中调用 reactive() 函数,创建响应式数据对象:

    setup() {
         // 创建响应式数据对象
        const state = reactive({count: 0})
    ​
         // setup 函数中将响应式数据对象 return 出去,供 template 使用
        return state
    }
  3. template 中访问响应式数据:

    <p>当前的 count 值为:{{count}}</p>

[5. ref]

5.1 基本语法

ref() 函数用来根据给定的值创建一个响应式数据对象ref() 函数调用的返回值是一个对象,这个对象上只包含一个 .value 属性:

import { ref } from '@vue/composition-api'
​
// 创建响应式数据对象 count,初始值为 0
const count = ref(0)
​
// 如果要访问 ref() 创建出来的响应式数据对象的值,必须通过 .value 属性才可以
console.log(count.value) // 输出 0
// 让 count 的值 +1
count.value++
// 再次打印 count 的值
console.log(count.value) // 输出 1

[5.2 在 template 中访问 ref 创建的响应式数据]

  1. setup() 中创建响应式数据:

    import { ref } from '@vue/composition-api'
    ​
    setup() {
        const count = ref(0)
    ​
         return {
             count,
             name: ref('zs')
         }
    }
  2. template 中访问响应式数据:

    <template>
      <p>{{count}} --- {{name}}</p>
    </template>

[5.3 在 reactive 对象中访问 ref 创建的响应式数据]

当把 ref() 创建出来的响应式数据对象,挂载到 reactive() 上时,会自动把响应式数据对象展开为原始的值,不需通过 .value 就可以直接被访问,例如:

const count = ref(0)
const state = reactive({
  count
})
​
console.log(state.count) // 输出 0
state.count++ // 此处不需要通过 .value 就能直接访问原始值
console.log(count) // 输出 1

注意:新的 ref 会覆盖旧的 ref,示例代码如下:

// 创建 ref 并挂载到 reactive 中
const c1 = ref(0)
const state = reactive({
  c1
})
​
// 再次创建 ref,命名为 c2
const c2 = ref(9)
// 将 旧 ref c1 替换为 新 ref c2
state.c1 = c2
state.c1++
​
console.log(state.c1) // 输出 10
console.log(c2.value) // 输出 10
console.log(c1.value) // 输出 0

5.4ref获取节点

一;获取单个绑定了ref属性的标签结点
1.给想要获取DOM元素的标签加上 ref 属性,并自定义一个名称

2.在 setup 中使用 ref 声明一个变量名与标签中 ref 属性名称相同的变量

3.之后这个通过 ref 声明的变量中存储的就是 ref 属性标记了的元素DOM结点
 

<template>
  <div ref="getDom"> Ref属性获取dom </div>
</template>
 
<script>
import { ref } from 'vue'
export default {
    name: 'Ref',
    setup () {
        // 先定义一个空的响应式数据ref定义的
        // setup中返回该数据,你想获取那个dom元素,在该元素上使用ref属性绑定该数据即可
        let getDom= ref(null)
        return {
            getDom
        }
    }
}
</script>

二;获取 v-for 循环的多个 ref 结点

1.获取 v-for 循环的结点,需要动态绑定 ref 属性,并定义一个获取对应DOM元素的回调函数。

<template>
  <h3 :ref="getlist" v-for="index in 3">我是一组元素{{index}}</h3>
</template>
 
<script>
import { ref, onMounted } from 'vue'
export default {
    name: 'Ref',
    setup () {
        // 获取v-for遍历的元素
        // 定义一个空数组,准备接收循环的DOM元素
        // 定义动态 ref 所对应的回调函数,往空数组push Dom
        let listDom = []
        const getlist = (el) => {
            listDom.push(el)
        }
        return {
            getlist
        }
    }
}
</script>

[6. isRef]

isRef() 用来判断某个值是否为 ref() 创建出来的对象;应用场景:当需要展开某个可能为 ref() 创建出来的值的时候,例如:

import { isRef } from 'vue'
​
const unwrapped = isRef(foo) ? foo.value : foo

[7. toRefs]

toRefs() 函数可以将 reactive() 创建出来的响应式对象,转换为普通的对象,只不过,这个对象上的每个属性节点,都是 ref() 类型的响应式数据,最常见的应用场景如下:

import { toRefs } from '@vue/composition-api'
​
setup() {
    // 定义响应式数据对象
    const state = reactive({
      count: 0
    })
​
    // 定义页面上可用的事件处理函数
    const increment = () => {
      state.count++
    }
​
    // 在 setup 中返回一个对象供页面使用
    // 这个对象中可以包含响应式的数据,也可以包含事件处理函数
    return {
      // 将 state 上的每个属性,都转化为 ref 形式的响应式数据
      ...toRefs(state),
      // 自增的事件处理函数
      increment
    }
}

页面上可以直接访问 setup() 中 return 出来的响应式数据:

<template>
  <div>
    <p>当前的count值为:{{count}}</p>
    <button @click="increment">+1</button>
  </div>
</template>

[8. computed]

computed() 用来创建计算属性,computed() 函数的返回值是一个 ref 的实例。使用 computed 之前需要按需导入:

import { computed } from '@vue/composition-api'

[8.1 创建只读的计算属性]

在调用 computed() 函数期间,传入一个 function 函数,可以得到一个只读的计算属性,示例代码如下:

// 创建一个 ref 响应式数据
const count = ref(1)
​
// 根据 count 的值,创建一个响应式的计算属性 plusOne
// 它会根据依赖的 ref 自动计算并返回一个新的 ref
const plusOne = computed(() => count.value + 1)
​
console.log(plusOne.value) // 输出 2
plusOne.value++ // error

[8.2 创建可读可写的计算属性]

在调用 computed() 函数期间,传入一个包含 getset 函数的对象,可以得到一个可读可写的计算属性,示例代码如下:

// 创建一个 ref 响应式数据
const count = ref(1)
​
// 创建一个 computed 计算属性
const plusOne = computed({
  // 取值函数
  get: () => count.value + 1,
  // 赋值函数
  set: val => {
    count.value = val - 1
  }
})
​
// 为计算属性赋值的操作,会触发 set 函数
plusOne.value = 9
// 触发 set 函数后,count 的值会被更新
console.log(count.value) // 输出 8

[9. watch]

watch() 函数用来监视某些数据项的变化,从而触发某些特定的操作,使用之前需要按需导入:

import { watch } from '@vue/composition-api'

[9.1 基本用法]

const count = ref(0)
​
// 定义 watch,只要 count 值变化,就会触发 watch 回调
// watch 会在创建时会自动调用一次
watch(() => console.log(count.value))
// 输出 0
​
setTimeout(() => {
  count.value++
  // 输出 1
}, 1000)

// Vue2使用watch
<template>
  <div>总合:{{ sum }}<button @click="sum++">点击累加</button></div>
</template>
<script>
import { ref } from "vue";
export default {
  // vue2中使用watch
  watch: {
    sum: {
      deep: true,
      handler(newValue, oldValue) {
        console.log("总合 sum 变化:", newValue, oldValue);
      },
    },
  },
  setup() {
    let sum = ref(0);
    return {
      sum,
    };
  },
};
</script>

<style>
</style>

// Vue3使用watch
// watch有三个参数:
// 参数1:监听的参数
// 参数2:监听的回调函数
// 参数3:监听的配置(immediate)

// =============================情况1
// 监视ref所定义的一个响应式数据
<template>
  <div>总合:{{ sum }}<button @click="sum++">点击累加</button></div>
</template>
// 监视ref所定义的一个响应式数据
<script>
import { ref, watch } from "vue";
export default {
  setup() {
    let sum = ref(0);
    // 监视ref所定义的一个响应式数据
    watch(sum, (newValue, oldValue) => {
      console.log("sum ==> ", newValue, oldValue);
    });
    return {
      sum,
    };
  },
};
</script>
// result
// sum ==> 1  0
// sum ==> 2  1
// sum ==> 3  2
// sum ==> 4  3
// sum ==> 5  4
// sum ==> 6  5



// ==========================情况2
// 监视ref所定义的多个响应式数据
<template>
  <div>总合:{{ sum }}<button @click="sum++">点击累加</button></div>
  <hr />
  <div>
    msg:{{ msg }}
    <button @click="msg += '~'">改变msg</button>
  </div>
</template>
<script>
import { ref, watch } from "vue";
export default {
  setup() {
    let sum = ref(0);
    let msg = ref("watch使用"):
    // 情况2:监视ref所定义的多个响应式数据
    watch([sum, msg], (newValue, oldValue) => {
      console.log("sum/msg ==> ", newValue, oldValue);
    },{immediate:true});
    return {
      sum,
      msg,
    };
  },
};
</script>



// ===========================情况3
// 监视reactive所定义的一个响应式数据
// 注意:

// 这里无法正确获取oldValue
// 强制开启了深度监听(deep配置不生效)
<template>
  <div>
     <h3>情况3::监视reactive所定义的一个响应式数据</h3>
      <div>姓名:{{person.name}}</div>
      <div>年龄:{{person.age}}</div>
    <button @click="person.name += '~'">修改姓名</button>
    <button @click="person.age ++">修改年龄</button>
  </div>
 </template>
<script>
import { ref, watch,reactive } from "vue";
export default {
  setup() {
    let person = reactive({
      name: "lisa",
      age: 18,
      job: {
        joblist: {
          money: 10,
        },
      },
    });
        // 情况3、监视reactive所定义的一个响应式数据
    /* 
      若watch监视的是reactive定义的响应式数据,则无法正确获得oldvalue! 
      若watch监视的是reactive定义的响应式数据,则强制开启了深度监视
    */
    watch(person,(newValue, oldValue) => {
        console.log("person ==> ", newValue, oldValue);
      },{immediate:true,deep:false}//这里的deep配置不再奏效
    );
    return {
      person,
    };
  },
};
</script>


// ======================情况4
// 监视reactive所定义的一个响应式数据中的某个属性

<template>
  <div>
     <h3>情况4::监视reactive所定义的一个响应式数据中的某个属性</h3>
      <div>姓名:{{person.name}}</div>
      <div>年龄:{{person.age}}</div>
    <button @click="person.name += '~'">修改姓名</button>
    <button @click="person.age ++">修改年龄</button>
  </div>
 </template>

<script>
import { ref, watch,reactive } from "vue";
export default {
  setup() {
    let person = reactive({
      name: "lisa",
      age: 18,
      job: {
        joblist: {
          money: 10,
        },
      },
    });
    // 情况4、监视reactive所定义的一个响应式数据中的某个属性
    watch(()=>person.name,(newValue, oldValue) => {
        console.log("person.name ==> ", newValue, oldValue);
      });

    return {
      person,
    };
  },
};
</script>



// ================情况5
// 监视reactive所定义的一个响应式数据中的某些属性

<template>
  <div>
     <h3>情况4::监视reactive所定义的一个响应式数据中的某个属性</h3>
      <div>姓名:{{person.name}}</div>
      <div>年龄:{{person.age}}</div>
    <button @click="person.name += '~'">修改姓名</button>
    <button @click="person.age ++">修改年龄</button>
  </div>
 </template>

<script>
import { ref, watch,reactive } from "vue";
export default {
  setup() {
    let person = reactive({
      name: "lisa",
      age: 18,
      job: {
        joblist: {
          money: 10,
        },
      },
    });
    // 情况5、监视reactive所定义的一个响应式数据中的某些属性
    watch([()=>person.name,()=>person.age],(newValue, oldValue) => {
        console.log("person.name/person.age ==> ", newValue, oldValue);
    });
    return {
      person,
    };
  },
};
</script>


// =================特殊情况
// watch监听reactive中对象的嵌套对象

<template>
  <div>
      <div>姓名:{{person.name}}</div>
      <div>年龄:{{person.age}}</div>
      <div>薪资:{{person.job.joblist.money}} K</div>
    <button @click="person.name += '~'">修改姓名</button>
    <button @click="person.age ++">修改年龄</button>
    <button @click="person.job.joblist.money ++">提薪</button>
  </div>
 </template>

<script>
import { ref, watch,reactive } from "vue";
export default {
  setup() {
    let person = reactive({
      name: "lisa",
      age: 18,
      job: {
        joblist: {
          money: 10,
        },
      },
    });
    // 特殊情况、监视reactive所定义嵌套对象
    watch(()=>person.job,(newValue, oldValue) => {
        console.log("person.job对象发生变化 ==> ", newValue, oldValue);
    },{deep:true});//此处由于监视的是reactive素定义的对象中的某个属性,所以deep配置有效

    return {
      person,
    };
  },
};
</script>

[9.2 清除监视]

setup() 函数内创建的 watch 监视,会在当前组件被销毁的时候自动停止。如果想要明确地停止某个监视,可以调用 watch() 函数的返回值即可,语法如下:

// 创建监视,并得到 停止函数
const stop = watch(() => {
  /* ... */
})
​
// 调用停止函数,清除对应的监视
stop()

[9.3 在 watch 中清除无效的异步任务]

有时候,当被 watch 监视的值发生变化时,或 watch 本身被 stop 之后,我们期望能够清除那些无效的异步任务,此时,watch 回调函数中提供了一个 cleanup registrator function 来执行清除的工作。这个清除函数会在如下情况下被调用:

  • watch 被重复执行了

  • watch 被强制 stop

Template 中的代码示例如下

/* template 中的代码 */ <input type="text" v-model="keywords" />

Script 中的代码示例如下

// 定义响应式数据 keywords
const keywords = ref('')

// 异步任务:打印用户输入的关键词
const asyncPrint = val => {
  // 延时 1 秒后打印
  return setTimeout(() => {
    console.log(val)
  }, 1000)
}

// 定义 watch 监听
watch(
  keywords,
  (keywords, prevKeywords, onCleanup) => {
    // 执行异步任务,并得到关闭异步任务的 timerId
    const timerId = asyncPrint(keywords)

    // 如果 watch 监听被重复执行了,则会先清除上次未完成的异步任务
    onCleanup(() => clearTimeout(timerId))
  },
  // watch 刚被创建的时候不执行
  { lazy: true }
)

// 把 template 中需要的数据 return 出去
return {
  keywords
}

<think>首先,用户查询是:“我想查找Vue 3中ref的使用方法 请问Vue 3 ref的使用方法”。我需要基于提供的引用内容来回答。引用[1]到[5]是关于Vue 3中ref使用的讨论。 关键点从引用中提取: - 引用[1]:解释ref用于访问DOM元素,Vue 3改进了它。 - 引用[2]:指出在Vue 3中获取元素的方式不同于Vue 2,没有$和refs;需要使用ref函数。 - 引用[3]:描述ref用于基本数据类型,reactive用于对象/数组;ref是响应式API的一部分。 - 引用[4]:展示ref用于定义响应式数据(如count)和获取元素。 - 引用[5]:提供代码示例,如何用ref获取元素和访问子组件。 用户的问题是关于“ref的使用方法”,所以我需要覆盖两个主要方面: 1. 使用ref定义响应式数据。 2. 使用ref访问DOM元素或子组件。 根据系统指令: - 所有行内数学表达式用$...$,但这里没有数学内容,所以可能不需要。 - 独立公式用$$...$$,但同样不适用。 - LaTeX语法正确:确保代码块正确。 - 使用中文回答。 - 生成相关问题:在回答末尾添加相关问题。 - 引用的段落末尾添加引用标识,例如[^1]。 回答结构: - 清晰、逐步解释。 - 参考引用内容。 - 确保真实可靠。 大纲回答: 1. **介绍ref**:简要说明ref在Vue 3中的作用(响应式状态和DOM访问)。 2. **使用ref定义响应式数据**: - 解释如何导入和使用ref。 - 示例代码。 - 引用[4]:const count = ref(1); update函数更值。 3. **使用ref访问DOM元素**: - 如何在模板中添加ref属性。 - 在setup函数中使用ref。 - 示例代码:引用[5]:inputRef.value.value。 4. **访问子组件**: - ref用于组件引用。 - 访问子组件的属性和方法。 5. **关键注意事项**: - 在onMounted钩子中访问DOM以确保元素存在。 - ref.value的使用。 6. **相关问题**:在末尾生成相关问题。 生成相关问题: - 类似示例中的格式:1. ... 2. ... 3. ... - 基于主题:Vue 3 ref的高级用法、常见问题、比较等。 确保中文回答。 最终回答结构: - 开头:直接回答问题。 - 主体:分段解释。 - 代码块:用Markdown格式。 - 引用标识:添加在相关解释后。 - 相关问题:在末尾以“§§相关问题§§”开始。 </think>### Vue 3 ref 的使用方法 在 Vue 3 中,`ref` 是一个核心 API,主要用于处理响应式数据和访问 DOM 元素。它通过 `ref()` 函数创建响应式引用,允许您在组件中管理状态或直接操作原生 DOM。下面我将分步解释其使用方法,包括定义响应式数据和访问 DOM 元素,并提供代码示例。内容基于引用资料[^1][^2][^3][^4][^5],确保真实可靠。 #### 1. **使用 ref 定义响应式数据** `ref` 适用于基本数据类型(如数字、字符串),它会将值包装在响应式对象中,通过 `.value` 属性访问和修改数据。主要步骤: - **第一步:导入 ref 函数**:从 Vue 库中导入 `ref`。 - **第二步:在 setup() 函数中定义 ref 变量**:使用 `const variable = ref(initialValue)` 创建响应式引用。 - **第三步:修改数据**:通过 `.value` 属性更值,Vue 会自动触发视图更。 - **第四步:返回变量**:在 `setup()` 函数中返回变量,以便在模板中使用。 示例代码(引用自[^4]): ```vue <template> <h2>{{ count }}</h2> <hr> <button @click="update">更</button> </template> <script> import { ref } from &#39;vue&#39; export default { setup() { // 定义响应式数据,初始值为 1 const count = ref(1) // 更数据的函数 function update() { count.value = count.value + 1 // 通过.value修改值 } return { count, update } // 返回变量和函数 } } </script> ``` 在这个示例中: - `count` 是一个响应式引用,初始值为 1。 - 点击按钮时调用 `update` 函数,`count.value` 递增,视图自动更的值。 注意:`ref` 适合处理简单数据类型,对于对象或数组,建议使用 `reactive` API(引用自[^3])。 #### 2. **使用 ref 访问 DOM 元素** 在 Vue 3 中,`ref` 也用于获取原生 DOM 元素(如 input 或 div),这在需要操作元素属性或方法时非常实用。主要步骤: - **第一步:在模板中添加 ref 属性**:给元素设置 `ref="refName"`。 - **第二步:在 setup() 函数中创建 ref 变量**:使用 `const refVariable = ref(null)` 初始化引用。 - **第三步:在生命周期钩子中访问元素**:通常在 `onMounted` 钩子中确保 DOM 已完成渲染,再通过 `refVariable.value` 访问元素。 - **第四步:操作元素**:使用 DOM API 如 `.value`(针对 input)或 `.focus()` 等。 示例代码(引用自[^5]): ```vue <template> <div> <input type="text" ref="inputRef" value="1111" /> <input type="text" ref="input2Ref"> <span>123</span> </div> </template> <script> import { ref, onMounted } from "vue"; export default { setup() { // 创建 ref 变量,初始为 null const inputRef = ref(null); // 在组件挂载后访问 DOM 元素 onMounted(() => { console.log(inputRef.value); // 输出 input 元素(DOM 节点) console.log(inputRef.value.value); // 输出 "1111"(input元素的value属性) }); return { inputRef }; // 返回 ref 变量 } }; </script> ``` 在这个示例中: - 模板中为 input 元素设置了 `ref="inputRef"`。 - `onMounted` 钩子确保在 DOM 渲染完成后访问 `inputRef.value`,避免空指针错误。 - 通过 `inputRef.value.value` 获取 input 的值(初始为 "1111")。 注意:Vue 3 移除了 Vue 2 中的 `$refs`,必须通过 `ref()` 函数和 `setup()` 实现(引用自[^2])。 #### 3. **使用 ref 访问子组件** `ref` 可以用于引用子组件实例,从而访问其属性和方法,实现父子组件通信。 - **第一步:在父组件模板中引用子组件**:给子组件标签添加 `ref` 属性。 - **第二步:在父组件的 setup() 中创建 ref**:类似 DOM 访问。 - **第三步:通过 ref 调用子组件方法或访问数据**:在钩子函数中操作。 示例代码(引用自[^5]): ```vue <!-- 子组件 ChildComponent.vue --> <script> export default { methods: { childMethod() { console.log("子组件方法被调用"); } } } </script> <!-- 父组件 ParentComponent.vue --> <template> <ChildComponent ref="childRef" /> </template> <script> import { ref, onMounted } from "vue"; import ChildComponent from "./ChildComponent.vue"; export default { components: { ChildComponent }, setup() { const childRef = ref(null); onMounted(() => { childRef.value.childMethod(); // 调用子组件方法 }); return { childRef }; } }; </script> ``` 在这个示例中: - 父组件通过 `childRef.value` 访问子组件实例,并调用其 `childMethod`。 - 这适用于组件间通信,如触发子组件的函数(引用自[^5])。 #### 关键注意事项 - **访问时机**:DOM 元素或子组件必须在生命周期钩子(如 `onMounted`)中访问,确保组件已渲染完成(引用自[^5])。 - **使用 .value**:所有 `ref` 变量必须通过 `.value` 属性读取或修改值,这是 Vue 3 的响应式机制核心(引用自[^3])。 - **数据类型**:`ref` 适合基本类型(如数字、字符串),而对象/数组应使用 `reactive`(引用自[^3])。 - **性能优化**:避免过度使用 `ref` 访问 DOM,仅在必要时(如表单验证或动画)操作,以减少渲染开销(引用自[^1])。 通过以上方法,您可以灵活运用 `ref` 在 Vue 3 中管理状态和DOM操作。如果需要更深入的示例,可参考官方文档或相关教程。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值