Vue2基础七、refnextTick自定义指令

news2024/9/23 21:31:59

零、文章目录

Vue2基础七、ref&nextTick&自定义指令

1、ref

  • **作用:**利用 ref 和 $refs 可以用于 获取 dom 元素, 或 组件实例
  • **特点:**查找范围 → 当前组件内 (更精确稳定),用document.querySelect(‘.box’) 获取的是整个页面中的盒子

(1)获取 dom

  • 目标标签 – 添加 ref 属性
<div ref="chartRef">我是渲染图表的容器</div>
  • 恰当时机, 通过 this.$refs.xxx, 获取目标标签
mounted () {
   console.log(this.$refs.chartRef)
},

(2)获取组件

  • 目标组件 – 添加 ref 属性
<BaseForm ref="baseForm"></BaseForm>
  • 恰当时机, 通过 this.$refs.xxx, 获取目标组件,就可以调用组件对象里面的方法
this.$refs.baseForm.组件方法()

(3)代码演示

  • 安装echart
yarn add echarts
  • 父组件App.vue
<template>
  <div class="app">
    <div class="base-chart-box">
      这是一个捣乱的盒子
    </div>
    <BaseChart></BaseChart>
  </div>
</template>

<script>
import BaseChart from './components/BaseChart.vue'
export default {
  components:{
    BaseChart
  }
}
</script>

<style>
.base-chart-box {
  width: 300px;
  height: 200px;
}
</style>
  • 子组件BaseChart.vue
<template>
  <div class="base-chart-box" ref="baseChartBox">子组件</div>
</template>

<script>
import * as echarts from 'echarts'

export default {
  mounted() {
    // 基于准备好的dom,初始化echarts实例
    // document.querySelector 会查找项目中所有的元素
    // $refs只会在当前组件查找盒子
    // var myChart = echarts.init(document.querySelector('.base-chart-box'))
    var myChart = echarts.init(this.$refs.baseChartBox)
    // 绘制图表
    myChart.setOption({
      title: {
        text: 'ECharts 入门示例',
      },
      tooltip: {},
      xAxis: {
        data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子'],
      },
      yAxis: {},
      series: [
        {
          name: '销量',
          type: 'bar',
          data: [5, 20, 36, 10, 10, 20],
        },
      ],
    })
  },
}
</script>

<style scoped>
.base-chart-box {
  width: 400px;
  height: 300px;
  border: 3px solid #000;
  border-radius: 6px;
}
</style>
  • 效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WmBy90dR-1690447474327)(https://bluecusliyoupicrep.oss-cn-hangzhou.aliyuncs.com/202307131641861.png)]

2、nextTick

(1)异步更新问题

  • 需求:编辑标题, 编辑框自动聚焦

    • 点击编辑,显示编辑框
    • 让编辑框,立刻获取焦点
    this.isShowEdit = true // 显示输入框
    this.$refs.inp.focus() // 获取焦点
    
  • 问题:“显示之后”,立刻获取焦点是不能成功的!

  • 原因:Vue 是 异步更新 DOM (提升性能)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1BdzLqJY-1690447474329)(https://bluecusliyoupicrep.oss-cn-hangzhou.aliyuncs.com/202307131654743.png)]

(2)$nextTick解决问题

  • $nextTick:等 DOM 更新后, 才会触发执行此方法里的函数体
  • 语法: this.$nextTick(函数体)
this.$nextTick(() => {
this.$refs.inp.focus()
})
  • 注意:$nextTick 内的函数体 一定是箭头函数,这样才能让函数内部的this指向Vue实例

(3)代码实现

<template>
  <div class="app">
    <div v-if="isShowEdit">
      <input type="text" v-model="editValue" ref="inp" />
      <button>确认</button>
    </div>
    <div v-else>
      <span>{{ title }}</span>
      <button @click="editFn">编辑</button>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      title: '大标题',
      isShowEdit: false,
      editValue: '',
    }
  },
  methods: {
    editFn() {
        // 显示输入框
        this.isShowEdit = true  
        // // 获取焦点
        // this.$refs.inp.focus() 
        this.$nextTick(() => {
          this.$refs.inp.focus()
        })
    }  },
}
</script> 

3、自定义指令

(1)指令分类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YJamBXtu-1690447474330)(https://bluecusliyoupicrep.oss-cn-hangzhou.aliyuncs.com/202307141042338.png)]

(2)自定义指令

  • 自定义指令:自己定义的指令, 可以封装一些 dom 操作, 扩展额外功能

  • 自定义指令语法:

    • 全局注册
    //在main.js中
    // 1. 全局注册指令
    Vue.directive('focus', {
      // inserted 会在 指令所在的元素,被插入到页面中时触发
      inserted (el) {
        // el 就是指令所绑定的元素
        // console.log(el);
        el.focus()
      }
    })
    
    • 局部注册
    //在Vue组件的配置项中
    directives: {
      "指令名": {
        inserted () {
          // 可以对 el 标签,扩展额外功能
          el.focus()
        }
      }
    }
    
    • 使用指令

      • 在使用指令的时候,一定要先注册,再使用,否则会报错
      • 使用指令语法: v-指令名。如:<input type="text" v-focus/>
      • 注册指令时不用加v-前缀使用时要加v-前缀
      <input v-focus type="text">
      
    • 指令中的配置项介绍

      • inserted:被绑定元素插入父节点时调用的钩子函数
      • el:使用指令的那个DOM元素
  • 完整代码实现:

    • 需求:当页面加载时,让元素获取焦点(autofocus在safari浏览器有兼容性
<template>
  <div>
    <h1>自定义指令</h1>
    <input v-focus type="text">
  </div>
</template>

<script>
export default {
  // 2. 局部注册指令
  directives: {
    // 指令名:指令的配置项
    focus: {
      inserted (el) {
        el.focus()
      }
    }
  }
}
</script>

<style>

</style>

(3)自定义指令的值

  • 需求:实现一个 color 指令 - 传入不同的颜色, 给标签设置文字颜色

  • 语法:

    • v-指令名 = "指令值" ,通过 等号 可以绑定指令的值
    <div v-color="color">我是内容</div>
    
    • 通过 binding.value 可以拿到指令值,通过 update 钩子,可以监听指令值的变化,进行dom更新操作
    directives: {
      color: {
        inserted (el, binding) {
          el.style.color = binding.value
        },
        update (el, binding) {
          el.style.color = binding.value
        }
      }
    }
    
  • 完整代码实现:

<template>
  <div>
    <h1 v-color="color1">指令的值1测试</h1>
    <h1 v-color="color2">指令的值2测试</h1>
  </div>
</template>

<script>
export default {
  data () {
    return {
      color1: 'red',
      color2: 'orange'
    }
  },
  directives: {
    color: {
      // 1. inserted 提供的是元素被添加到页面中时的逻辑
      inserted (el, binding) {
        // console.log(el, binding.value);
        // binding.value 就是指令的值
        el.style.color = binding.value
      },
      // 2. update 指令的值修改的时候触发,提供值变化后,dom更新的逻辑
      update (el, binding) {
        console.log('指令的值修改了');
        el.style.color = binding.value
      }
    }
  }
}
</script>

<style>

</style>

(4)v-loading 指令封装

  • 场景:实际开发过程中,发送请求需要时间,在请求的数据未回来时,页面会处于空白状态 => 用户体验不好
  • 需求:封装一个 v-loading 指令,实现加载中的效果

image-20230714110226535

  • 分析:

    • 本质 loading 效果就是一个蒙层,盖在了盒子上
    • 数据请求中,开启loading状态,添加蒙层
    • 数据请求完毕,关闭loading状态,移除蒙层
  • 实现思路:

    • 准备一个 loading 类,通过伪元素定位,设置宽高,实现蒙层
    • 开启关闭 loading 状态(添加移除蒙层),本质只需要添加移除类即可
    • 结合自定义指令的语法进行封装复用
  • 代码实现:

<template>
  <div class="main">
    <div class="box" v-loading="isLoading">
      <ul>
        <li v-for="item in list" :key="item.id" class="news">
          <div class="left">
            <div class="title">{{ item.title }}</div>
            <div class="info">
              <span>{{ item.source }}</span>
              <span>{{ item.time }}</span>
            </div>
          </div>
          <div class="right">
            <img src="./assets/img/news.png" alt="">
          </div>
        </li>
      </ul>
    </div>
  </div>
</template>

<script>
export default {
  data () {
    return {
      list: [],
      isLoading: true
    }
  },
  created () {
      // 更新到 list 中,用于页面渲染 v-for
      this.list = [
        {
          id:1,
          title:'testtitle1',
          source:'testsource1',
          time:'testtime1'
        },
        {
          id:2,
          title:'testtitle2',
          source:'testsource2',
          time:'testtime2'
        }]

        //三秒后loading移除
        setTimeout(()=>{
            this.isLoading = false
         }, 3000);
  },
  directives: {
    loading: {
      inserted (el, binding) {
        binding.value ? el.classList.add('loading') : el.classList.remove('loading')
      },
      update (el, binding) {
        binding.value ? el.classList.add('loading') : el.classList.remove('loading')
      }
    }
  }
}
</script>

<style>
.loading:before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background: #fff url('./assets/img/loading.gif') no-repeat center;
}

.box2 {
  width: 400px;
  height: 400px;
  border: 2px solid #000;
  position: relative;
}

.box {
  width: 800px;
  min-height: 500px;
  border: 3px solid orange;
  border-radius: 5px;
  position: relative;
}
.news {
  display: flex;
  height: 120px;
  width: 600px;
  margin: 0 auto;
  padding: 20px 0;
  cursor: pointer;
}
.news .left {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding-right: 10px;
}
.news .left .title {
  font-size: 20px;
}
.news .left .info {
  color: #999999;
}
.news .left .info span {
  margin-right: 20px;
}
.news .right {
  width: 160px;
  height: 120px;
}
.news .right img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
</style>

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

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

相关文章

Ubuntu Server版 之 mysql 系列(-),安装、远程连接,mysql 创建用户、授权等

Ubuntu 分 桌面版 和 服务版 桌面版 &#xff1a;有额外的简易界面 服务版&#xff1a;是纯黑框的。没有任何UI界面的可言 安装mysql 安装位置 一般按照的位置存放在 /usr/bin 中 sudo apt-get install mysql-server查看mysql的状态 service mysql status mysql 安全设置…

【C语言课程设计】图书管理系统

引言&#xff1a; 图书管理系统是一个重要的信息管理系统&#xff0c;对于图书馆和书店等机构来说&#xff0c;它能够方便地管理图书的录入、显示、查询、修改和删除等操作。本实验基于C语言开发了一个简单的图书管理系统&#xff0c;通过账户名和密码进行系统访问和权限控制&a…

java数组对象初始化分析

分析代码 public static void main(String[] args) {int a10,b20,c30,d 40,e 50,f60;int aa[] {a,b,c,d,e,f};aa[2] 100;}代码的字节码 图解分析 refs https://docs.oracle.com/javase/specs/jvms/se19/html/jvms-6.html#jvms-6.5.aloadhttps://docs.oracle.com/javase/sp…

WebServer

socket是啥&#xff1f; 网络套接字&#xff08;Socket&#xff09;通常被表示为一个类或类似于类的数据结构。网络套接字类封装了网络通信的细节&#xff0c;并提供了用于建立、发送和接收网络数据的方法和属性。常见的成员有源端口&#xff0c;目标端口&#xff0c;源IP,目…

C语言:结构体,联合体

文章目录 一、结构体1.结构体的声明和结构体变量的定义2.结构体变量初始化3. 访问结构体成员4.结构体的内存对齐 二、联合(共用体)总结 一、结构体 结构体是一组元素类型不同的元素的集合 1.结构体的声明和结构体变量的定义 结构体的声明包含三个部分&#xff0c;标记名(tag…

uniapp 微信小程序:页面+组件的生命周期顺序

uniapp 微信小程序&#xff1a;页面组件的生命周期顺序 首页页面父组件子组件完整顺序参考资料 这个uniapp的微信小程序项目使用的是 VUE2 首页 首页只提供了一个跳转按钮。 <template><view><navigator url"/pages/myPage/myPage?namejerry" hov…

Vue中使用Typescript及Typescript基础

准备工作 新建一个基于ts的vue项目 通过官方脚手架构建安装 # 1. 如果没有安装 Vue CLI 就先安装 npm install --global vue/cli最新的Vue CLI工具允许开发者 使用 TypeScript 集成环境 创建新项目。 只需运行vue create my-app 然后选择选项&#xff0c;箭头键选择 Manuall…

国产芯片架构再下一城,ARM或被彻底抛弃,外媒:自作自受

有消息指出特定厂商的5G手机芯片将采用RISC-V架构&#xff0c;这是国产芯片彻底抛弃ARM的标志&#xff0c;毕竟ARM如今对中国芯片越来越不友好&#xff0c;最新款的ARM V9架构就未对多家中国芯片企业授权&#xff0c;抛弃ARM在情理之中。 据悉特定企业的5G手机芯片为RISC-V架构…

Vue项目中强制刷新页面的方法

我们在动态切换组件的过程中&#xff0c;导航栏和底栏不动&#xff0c;动态切换中间区域的情况&#xff0c;在首页可以进行跳转任意组件&#xff0c;在组件与组件之间不能相互跳转&#xff0c;路由发生了变化&#xff0c;但是页面未改变&#xff0c;这时我们就需要强制刷新页面…

窗口透明丨窗口透明度设置控件透明以及窗体透明源码

透明窗口&#xff08;窗口上面文字图片等内容不透明&#xff09;的实现&#xff08;使用SetLayeredWindowAttributes API函数&#xff09; SetLayeredWindowAttributes的实现必须将窗口设置为WS_EX_LAYERED的扩展风格。 然而&#xff0c;只有WS_POPUP窗口才能设置WS_EX_LAYER…

SG函数Nim游戏博弈论

移棋子游戏 题目 https://vjudge.csgrandeur.cn/problem/LibreOJ-10243 给定一个有 N 个节点的有向无环图&#xff0c;图中某些节点上有棋子&#xff0c;两名玩家交替移动棋子。 玩家每一步可将任意一颗棋子沿一条有向边移动到另一个点&#xff0c;无法移动者输掉游戏。 对…

中国撤销3000亿订单,美芯质问还能卖给谁?Intel或暂停工厂

过去两年多来&#xff0c;美国芯片行业的收入大幅减少&#xff0c;然而这还不是低点&#xff0c;近期传出中国或撤销3200亿美元的芯片订单&#xff0c;这更是让美国芯片行业震惊&#xff0c;美芯巨头因此质问美国芯片卖给谁&#xff1f; 中国这几年一直都在稳步减少芯片进口&am…

PHP高校二手物品交易系统【纯干货分享,免费领源码04827】

目 录 摘要 1 绪论 1.1 研究背景 1.2国内外研究现状 1.3论文结构与章节安排 2 高校二手物品交易系统系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 数据流程 3.3.2 业务流程 2.3 系统功能分析 2.3.1 功能性分析 2.3.2 非功能性分析 2.4 系统用例分析 2.5本章…

Java开发基础系列(十四):集合对象(Map)

&#x1f60a; 作者&#xff1a; 一恍过去 &#x1f496; 主页&#xff1a; https://blog.csdn.net/zhuocailing3390 &#x1f38a; 社区&#xff1a; Java技术栈交流 &#x1f389; 主题&#xff1a; Java开发基础系列(十三)&#xff1a;集合对象(Map) ⏱️ 创作时间&…

zlog日志库的使用

代码仓库&#xff1a;https://github.com/HardySimpson/zlog1、zlog 库的默认安装位置是 /usr/local/lib&#xff0c;头文件的安装位置是 /usr/local/include&#xff1b;若需要更改安裝位置&#xff0c;可以修改src/makefile文件下第50行的PREFIX&#xff1f; /usr/local 改为…

当Dubbo遇到高并发:探究流量控制解决方案

系列文章目录 面试Dubbo &#xff0c;却问我和Springcloud有什么区别&#xff1f; 超简单&#xff0c;手把手教你搭建Dubbo工程&#xff08;内附源码&#xff09; 【收藏向】从用法到源码&#xff0c;一篇文章让你精通Dubbo的SPI机制 Dubbo最核心功能——服务暴露的配置、使用…

Doris注意事项,Doris部署在阿里云,写不进去数据

1.Doris官网 Doris官网https://doris.apache.org/ 2.根本原因 本地idea访问FE&#xff0c;FE会返回BE的地址&#xff0c;但是在服务器上通过ip addr查看&#xff0c;发现只有局域网IP&#xff0c;所以FE返回了局域网的IP&#xff0c;导致idea连接不上BE 3.解决办法 重写Ba…

leetcode刷题常用代码片段

Vscode是常用的开发工具&#xff0c;代码插入能够把常见的代码嵌入智能提醒&#xff0c;减轻了很大的工作量&#xff0c;下面是我刷题的配置&#xff0c;直接复制黏贴到自己的cpp.json里就可以用了 左下角&#xff0c;打开设置&#xff0c;选择用户代码片段&#xff0c;选择自…

智慧农业:科技赋能农村发展

智慧农业发展前景灿烂多彩&#xff0c;正为农业带来新的转型升级。随着科技的不断发展&#xff0c;数字化、自动化和智能化技术逐渐渗透进农业领域&#xff0c;为农民提供了更多高效便捷的农业管理方式。智慧农业通过物联网、大数据、人工智能等先进技术&#xff0c;实现对农田…

如何跳出Java中的多层嵌套循环?

在Java中&#xff0c;要跳出多层嵌套循环&#xff0c;可以使用带有标签的break语句。通过在外层循环前加上一个标签&#xff0c;然后在内层循环中使用break语句后跟标签名称&#xff0c;可以实现跳出多层循环的目的。 以下是使用标签和break语句跳出多层嵌套循环的示例代码&…