Vue3全家桶 - Vue3 - 【8】模板引用【ref】(访问模板引用 + v-for中的模板引用 + 组件上的ref)

模板引用【ref

  • Vue3官网-模板引用;
  • 如果我们需要直接访问组件中的底层DOM元素,可使用vue提供特殊的ref属性来访问;

一、 访问模板引用

  • 在视图元素上采用ref属性来设置需要访问的DOM元素:
    • ref 属性可采用 字符串 值的执行设置;
    • ref 属性可采用v-bind::ref的形式来绑定 函数,其函数的第一个参数则为该元素;
  • 如果元素的ref属性值采用的是字符串形式:
    • 在组合式API JS 中,我们需要声明一个同名的ref变量,来获得该模板的引用;
    • 在选项式API JS 中,可通过this.$refs来访问模板的引用;
  • 示例代码:
    • 组合式API:
      <template><!-- 字符串形式的 ref -->账号输入框:<input type="text" ref="account"><button @click="accountInputStyle">改变账号输入框的样式</button><!-- 函数形式的 ref ,必须采用 v-bind 或 : 的形式来给ref绑定属性值 -->密码输入框:<input type="password" :ref="passwordFn"><button @click="passwordInputStyle">改变密码输入框的样式</button>
      </template><script setup>
      import { ref, reactive, computed, onMounted, nextTick } from 'vue'// EXPLAIN 响应式数据
      // ref 变量名 和 对应DOM元素的ref属性值 相等
      let account = ref(null)
      let password = ref(null)// EXPLAIN 函数
      const accountInputStyle = () => {// NOTE 此处设置的 style 均为行内样式account.value.style.padding = '15px'account.value.style.caretColor = 'red'account.value.className = 'rounded'account.value.focus()
      }
      // NOTE 采用函数给ref绑定属性值,该函数的第一个参数为该元素
      // NOTE 在页面渲染的时候会自动执行
      // NOTE 函数式生命的 ref,不会在 this.$refs 中获取
      const passwordFn = (el) => {// el 元素是密码输入框password.value = elconsole.log(password.value)
      }
      const passwordInputStyle = () => {password.value.style.border = '4px solid green'password.value.style.padding = '15px'password.value.focus()
      }onMounted(() => {});
      </script><style scoped>
      .rounded {border: 4px solid purple;
      }
      </style>
      
    • 选项式API:
      <script>
      export default {data: () => ({accountEl: null,passwordEl: null}),methods: {changeAccountInputStyle() {this.accountEl = this.$refs.account // 获取账号输入框的 DOMconsole.log(this.accountEl)this.accountEl.style = "padding: 15px"this.accountEl.className = "rounded"this.accountEl.focus()},passwordRef(el) { this.passwordEl = el  // el 元素是密码输入框},changePasswordInputStyle() {console.log(this.passwordEl) console.log(this.$refs) // 函数式声明的 ref,不会在this.$refs中获取this.passwordEl.style = "padding: 15px"this.passwordEl.className = "rounded"this.passwordEl.focus()},}
      }
      </script><template><!-- ref 字符串值形式 -->账号输入框:<input type="text" ref="account"><button @click="changeAccountInputStyle">改变账号输入框的样式</button><hr><!-- ref 函数形式:元素渲染后,会立即执行该函数 -->密码输入框:<input type="password" :ref="passwordRef"><button @click="changePasswordInputStyle">改变密码输入框的样式</button>
      </template><style>
      .rounded {border-radius: 15px;
      }
      </style>
      

二、 v-for中的模板引用

  • 当在v-for中使用模板引用时:

    • 如果 ref 值是 字符串 形式,在元素被渲染后包含对应整个 列表的所有元素【数组】
    • 如果 ref 值是 函数 形式,则会每渲染一个列表元素就会执行对应的函数【不推荐使用】;
  • 注意:需要 v3.2.25 及以上的版本;

  • 示例代码:

    • 组合式API:
      <script setup>
      import { onMounted, ref } from "vue";// 书本
      let books = ref([{ id: 1, name: "海底两万里" },{ id: 2, name: "骆驼祥子" },{ id: 3, name: "老人与海" },{ id: 4, name: "安徒生童话" },
      ]);let bookList = ref(null);onMounted(() => {console.log(bookList.value); // 获取引用的 DOM 对象,并打印,发现那么是数组,bookList.value[2].className = "error";
      });
      </script><template><ul><li v-for="b in books" :key="b.id" ref="bookList">{{ b.name }}</li></ul>
      </template><style>
      .error {border: 1px solid red;
      }
      </style>
      
    • 选项式API:
      <script>
      export default {data: () => ({books: [{ id: 1, name: "红楼梦" },{ id: 2, name: "三国演义" },{ id: 3, name: "水浒传" },{ id: 4, name: "西游记" },],students: [{ id: 1, name: "Jack" },{ id: 2, name: "Annie" },{ id: 3, name: "Tom" },],}),methods: {changeBookListStyle() {console.log(this.$refs.bookList);this.$refs.bookList[2].style = "color: red";},studentsRef(el) {console.log(el);},},
      };
      </script><template><ul><!-- 如果 ref 值是字符串形式,在元素被渲染后包含对应整个列表的所有元素【数组】 --><li v-for="b in books" :key="b.id" ref="bookList">{{ b.name }}</li></ul><button @click="changeBookListStyle">点我查看 bookList</button><hr /><!-- 如果ref值是函数形式,则会每渲染一个列表元素则会执行对应的函数【不推荐使用】 --><ul><li v-for="s in students" :key="s.id" :ref="studentsRef">{{ s.name }}</li></ul>
      </template>
      
  • 运行效果:

    • 选项式API:
      image.png
    • 组合式API:
      image.png

三、 组件上的ref

  • 模板引用也可以被用在一个子组件上;这种情况下引用中获得的值是组件实例;

    • 如果子组件使用的选项式API,默认情况下父组件可以随意访问该子组件的数据和函数,除非在子组件使用expose选项来暴露特定的数据或函数,expose值为字符串数组;
    • 如果子组件使用的是组合式API<script setup>,那么该子组件默认是私有的,则父组件无法访问该子组件,除非子组件在其中通过defineExpose宏采用对象形式显示暴露特定的数据或函数;
  • 示例代码:

    • 组合式API:
      • 父组件:

        <script setup>
        // NOTE 组合式API中,默认情况下,子组件中的数据、函数等等都是私有的,不能访问
        // NOTE 如果 子组件 通过 defineExpose 宏采用对象形式显式暴露特定的数据或函数等等
        import Vue1 from '@/components/27-组件上的ref - 组合式API/1.vue'
        import { ref, onMounted } from 'vue'
        const login_vue = ref(null)
        const showSonData = () => {console.log(login_vue.value.account)console.log(login_vue.value.password)login_vue.value.toLogin()
        }
        onMounted(() => {});
        </script><template><h3>登录页面</h3><hr><!-- 组件上的 ref 的值为该组件的实例 --><Vue1 ref="login_vue"></Vue1><hr><button @click="showSonData">查看子组件的信息</button>
        </template>
        
      • 子组件:

        <script setup>
        import { ref } from 'vue'
        const account = ref('admin')
        const password = ref('123456')
        const toLogin = () => {alert('登录中……')
        }
        // TODO 采用 defineExpose 将指定数据、函数等等暴露出去
        defineExpose({account,toLogin
        });
        </script><template>账号:<input type="text" v-model="account"><br>密码:<input type="text" v-model="password"><hr><button @click="toLogin">登录</button>
        </template>
        
      • 效果展示:

        • 默认情况下(没有使用defineEpxose):
          image.png
        • 通过defineExpose暴露特定的属性或方法:
          image.png
    • 选项式API:

      • 父组件:
        <script>
        // NOTE 选项式API中,默认情况下,父组件可以随意访问子组件的数据和函数、计算属性等等
        // NOTE 如果 子组件 增加 expose 选项之后,就只能访问 expose 暴露的属性和函数等等
        import Vue1 from '@/components/27-组件上的ref - 选项式API/1.vue'
        export default {name: 'App',components: { Vue1 },data: () => ({login_vue: null}),methods: {showSonData () {console.log(this.login_vue.account)console.log(this.login_vue.password)this.login_vue.toLogin()}},mounted () {// 打印出来的式子组件的ref对象this.login_vue = this.$refs.loginVueconsole.log(this.login_vue)}
        }
        </script><template><h3>登录页面</h3><hr><!-- 组件上的 ref 的值为该组件的实例 --><Vue1 ref="loginVue"></Vue1><hr><button @click="showSonData">查看子组件的信息</button>
        </template>
        
      • 子组件:
        <script>
        export default {name: 'Vue1',data: () => ({account: 'admin',password: '123456'}),methods: {toLogin () {alert('登录中……')}},// TODO 向外暴露属性函数,增加这个选项之后,父组件只能访问该组件暴露的属性或方法等等expose: ['account', 'password']
        }
        </script><template>账号:<input type="text" v-model="account"><br>密码:<input type="text" v-model="password"><hr><button @click="toLogin">登录</button>
        </template><style scoped lang='scss'>
        </style>
        
      • 运行展示:
        • 未增加 expose
          image.png
        • 增加 epxose
          • 子组件没有暴露 toLogin 方法,所以此处访问不了;
            image.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/739670.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RabbitMQ - 02 - 基本消息模型

目录 部署demo项目 什么是基本消息模型 实现基本消息模型 部署demo项目 首先配置好一个mq的练习demo,并配置好相关依赖 链接&#xff1a;https://pan.baidu.com/s/1oXAqgoz9Y_5V7YxC_rLa-Q?pwdv2sg 提取码&#xff1a;v2sg 如图 父xml文件已经配置好了 AMQP依赖了 什么…

计算机408炸了给25考研人的几点警示

25年408考研&#xff0c;如果只用王道的复习资料&#xff0c;最多考100-120分 就是这么的现实&#xff0c;王道的资料虽然好&#xff0c;但是并不能覆盖全部的知识点和考点&#xff0c;而且24年的408真题考的很怪&#xff0c;总结起来就是下面这些特点&#xff1a; 偏&#xff…

安装PyTorch详细过程

安装anaconda 登录anaconda的官网下载&#xff0c;anaconda是一个集成的工具软件不需要我们再次下载。anaconda官网 跳转到这个页面如果你的Python版本正好是3.8版&#xff0c;那便可以直接根据系统去选择自己相应的下载版本就可以了。 但是如果你的Python版本号不是当前页面…

seata入门到实战三

seata datasourceProxy connectionProxy statementProxy和PreparedStatementProxy abstractStatementProxy SqlRecognizer Executor AT模式二阶段提交 一阶段 二阶段提交 全部事务执行成功 释放锁 提交并删除undo日志 二阶段回滚

【LeetCode: 380. O(1) 时间插入、删除和获取随机元素 + 数据结构设计】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

【maven下载、安装、配置教程】

一、下载 maven 官网&#xff1a;Maven – Download Apache Maven 注意&#xff1a;idea 和 maven 的版本问题&#xff0c;不然 idea 启动项目会发生兼容性错误。如 2020 版本 idea 支持 3.6.3 左右的 maven 版本&#xff0c;用 3.9版本的 maven 会报错。 二、配置maven全局配置…

JS-06-数组

一、数组的创建与访问 见&#xff1a;JS-04-javaScript数据类型和变量 JavaScript的Array可以包含任意数据类型&#xff0c;并通过索引来访问每个元素。 要取得Array的长度&#xff0c;直接访问length属性&#xff1a; let arr [1, 2, 3.14, Hello, null, true]; console.l…

​LeetCode解法汇总1261. 在受污染的二叉树中查找元素

目录链接&#xff1a; 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目&#xff1a; https://github.com/September26/java-algorithms 原题链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 给出一个满足下述规则的二叉树&#xff1…

京东商品详情接口数据采集—价格,库存,支持高并发

初识API调用 为帮助商家及开发者快速掌握京东API调用方法&#xff0c;本文为大家提供的万邦API工具为例&#xff0c;为读者演示一例API调用过程&#xff0c;并做相应讲解。 item_get-获得JD商品详情 1、API公共参数示例 请求地址: https://api-gw.onebound.cn/jd/item_get …

【汇编】#2 寄存器相关与实模式下的8086存储器寻址

文章目录 前言一、什么是寄存器二、8086寄存器1. 8086通用寄存器2. 段寄存器3.专用寄存器3.1 标志寄存器内部具体标志及其作用 tips: 不同尺寸数据在存储器中存储 三、 实模式存储器寻址逻辑段与小段物理地址计算方式 前言 本文以清华大学出版社的《80x86汇编语言设计》和李忠…

docker + nginx打包前端镜像

项目场景&#xff1a; 前端使用angular开发&#xff0c;Dockerfile如下&#xff1a; FROM nginx:1.16.1 AS base WORKDIR /app COPY nginx.conf.template /etc/nginx/ CMD ["/bin/bash", "-c", "envsubst ${APP_VERSION} < /app/index.html > …

day2 员工管理 分类管理

文章目录 新增员工RequestBody方法参数注解 接受json数据两个对象之间属性的拷贝MD5加密 新增员工 DTO 用来接收前端传来的参数 vo用于返回数据 pojo和数据库对应 RequestBody方法参数注解 接受json数据 PostMapping("/")public Result save(RequestBody EmployeeD…

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:Rating)

提供在给定范围内选择评分的组件。 说明&#xff1a; 该组件从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 无 接口 Rating(options?: { rating: number, indicator?: boolean }) 从API version 9开始&#…

双场板功率型GaN HEMT中用于精确开关行为的电容建模

来源:Capacitance Modeling in Dual Field-Plate Power GaN HEMT for Accurate Switching Behavior (TED 16年) 摘要 本文提出了一种基于表面电势的紧凑模型&#xff0c;用于描述具有栅极和源极场板&#xff08;FP&#xff09;结构的AlGaN/GaN高电子迁移率晶体管&#xff08;…

嵌入式驱动学习第三周——设备号与字符设备的注册、分配、释放

前言 这一篇博客来谈谈字符设备的注册、分配与释放。 嵌入式驱动学习专栏将详细记录博主学习驱动的详细过程&#xff0c;未来预计四个月将高强度更新本专栏&#xff0c;喜欢的可以关注本博主并订阅本专栏&#xff0c;一起讨论一起学习。现在关注就是老粉啦&#xff01; 目录 前…

盲盒抽卡机小程序——开启神秘之旅!

亲爱的朋友们&#xff0c;欢迎来到盲盒抽卡机小程序&#xff01;这里&#xff0c;是一个充满神秘与惊喜的世界&#xff0c;让你随时随地体验抽卡的乐趣。在这里&#xff0c;你可以轻松尝试各种盲盒&#xff0c;发现隐藏的宝藏&#xff0c;感受心跳加速的刺激。 【丰富多样的盲…

小程序学习 1

pages/goods/search/home.wxml首页功能设定 1. loading入场 2. 下拉刷新 3. 搜索栏 4. 分类切换 5. 商品列表 6. 规格弹层 7. 加载更多 <view style"text-align: center; color: #b9b9b9" wx:if"{{pageLoading}}"><t-loading theme"circula…

利用ffmpeg对两个音频文件进行混音处理

前言 最近&#xff0c;拿到了一个语音识别程序&#xff0c;想测试一下它识别的准确性。原本程序有一段自己的测试音频&#xff0c;准确性还可以&#xff0c;但是&#xff0c;自己想增加一下测试素材的复杂性。想到了在原本的测试音频中引入干扰数据&#xff08;噪点&#xff…

python+realsense

单目相机(RGB影像):分辨率&#xff1a;320180,320240,424240,640360,640480,848480,960540,1280720,19201080&#xff1b;帧率&#xff1a;6,15,30,60 按照博文Python实战之Realsense_realsense python-CSDN博客的代码显示如下&#xff08;我更改了分辨率和帧率&#xff0c;大…