Vue-组件高级(下)

news2024/11/29 0:51:20

一、目标

  • 能够知道如何使用ref引用DOM和组件实例
  • 能够知道$nextTick的调用时机
  • 能够说出keep-alive元素的作用
  • 能够掌握插槽的基本用法
  • 能够知道如何自定义指令

二、目录

  • ref引用
  • 动态组件
  • 插槽
  • 自定义指令
  • Table案例

ref引用


1.什么是ref引用

ref用来辅助开发者在不依赖于jQuery的情况下,获取DOM元素或组件的引用。

每个vue的组件实例上,都包含一个$refs对象,里面存储着对应的DOM元素或组件的引用。默认情况下,组件的$refs指向一个空对象

 2.使用ref引用DOM元素

如果想要使用ref引用页面上的DOM元素,则可以按照如下的方式进行操作:

 3.使用ref引用组件实例

如果想要使用ref引用页面上的组件实例,则可以按照如下的方式进行操作:

<template>
  <div>
    <h1>这是App.vue根组件</h1>
    <hr />
    <button type="button" class="btn btn-primary" @click="reset">重置</button>
    <ref ref="conterRef"></ref>
  </div>
</template>
<script>
import ref from "./components/ref/ref.vue";
export default {
  components: {},
  name: "MyApp",
  data() {
    return {};
  },
  methods: {
    reset() {
      this.$refs.conterRef.rset();
    },
  },
  components: {
    ref,
  },
};
</script>
<template>
  <div>
    <h1>数字:{{ data }}</h1>
    <button type="button" @click="add">+1</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      data: 0,
    };
  },
  methods: {
    add() {
      this.data++;
    },
    rset() {
      this.data = 0;
    },
  },
};
</script>

4.控制文本框和按钮的按需切换

通过布尔值inputVisible来控制组件中的文本框与按钮的按需切换。示例代码如下:

5.让文本框自动获得焦点

当文本框展示出来之后,如果希望它立即获得焦点,则可以为其添加ref引用,并调用原生DOM对象的.focus()方法即可。示例代码如下: 

 在这里会输出undefined,原因是  DOM元素的更新是异步的,当执行到这行代码的时候,Dom还没有进行更新。

6.this.$nextTick(cd)方法

组件的$nextTick(cb)方法,会把cd回调推迟到下一个DOM更新周期之后执行。通俗的理解是:等b组件的DOM异步地重新渲染完成后,再执行cd回调函数。从而能保证cd回调函数可以操作到最新的DOM元素。

动态组件 


1.什么是动态组件

动态组件指的是动态切换组件的显示与隐藏。vue提供了一个内置的<component>组件,专门用来实现组件的动态渲染。

①<component>是组件的占位符

②通过is属性动态指定要渲染的组件名称

③<component is="要渲染的组件的名称"></component>

2.如何实现动态组件渲染

<template>
  <div>
    <h1>这是App.vue根组件</h1>
    <hr />
    <button type="button" class="btn btn-primary" @click="comName = 'ref'">
      组件一
    </button>
    <button type="button" class="btn btn-primary" @click="comName = 'reff'">
      组件二
    </button>
    <component :is="comName"></component>
  </div>
</template>
<script>
import ref from "./components/ref/ref.vue";
import reff from "./components/ref/reff.vue";

export default {
  components: {},
  name: "MyApp",
  data() {
    return {
      comName: "ref",
    };
  },
  methods: {
    change() {},
  },
  components: {
    ref,
    reff,
  },
};
</script>

 3.使用keep-alive保持状态

默认情况下,切换动态组件时无法保持组件的状态。此时可以使用vue内置的<keep-alive>组件保持动态组件的状态。示例代码如下:

  在切换组件的时,切换组件的时候组件的数据会重置。将component组件用keep-alive包括,可以缓存组件中的数据,切换组件时可以保存数据,不会丢失。 

插槽

1.什么是插槽

插槽(Slot)是vue为组件的封装者提供的能力。允许开发者在封装组件时,把不确定的、希望由用户指定的部分定义为插槽。

 可以把插槽认为是组件封装期间,为用户预留的内容的占位符

2.体验插槽的基础用法

 如果子组件中有内容不确定可以用slot占位,在父组件中使用子组件是插入即可,会自动渲染到子组件预留的位置。

 2.1没有预留插槽的内容会被丢弃

如果在封装组件时没有预留任何<slot>插槽,则用户提供的任何自定义内容会被丢弃。示例代码如下:

 没用slot的,不会被渲染出来

 2.2后备内容(默认内容)

封装组件时,可以为预留的<slot>插槽提供后备内容(默认内容)。如果组件的使用者没有为插槽提供任何内容,则后备内容会生效。示例代码如下:

3.具名插槽

如果在封装组件时需要预留多个插槽节点,则需要为每个<slot>插槽指定具体的name名称。这种带有具体名称的插槽叫做“具名插槽”。示例代码如下: 

 注意:没有指定name名称的插槽,会有隐含的名称叫做"default"。

3.1为具名插槽提供内容

在向具名插槽提供内容的时候,我们可以在一个<template>元素上使用v-slot指令,并以v-slot的参数的形式提供其名称。示例代码如下:

必须使用template包裹,才能用v-slot指定具体的插槽

3.2具名插槽的简写形式

跟v-on和v-bind一样,v-slot也有缩写,即把参数之前的所有内容(v-slot:)替换为字符 #。例如v-slot:header可以被重写为#header 

4.作用域插槽

通过插槽由子组件向父组件传递数据,子组件用:info=‘数据’,父组件v-slot:插槽名字=“接收数据”

在封装组件的过程中,可以为预留的<slot>插槽绑定props数据,这种带有props数据的<slot>叫做“作用域插槽”。示例代码如下:

 无论子组件传递几个数据,父组件只需要用一个数据接收即可,这个数据是以对象的形式包裹。

4.1解构作用域插槽的Prop

案例一:

案例二:

将prop向父组件传递的数据结构出来{数据1,数据2}

自定义指令

 1.什么是自定义指令

vue官方提供了V-for、v-model、v-if等常用的内置指令。除此之外vue还允许开发者自定义指令

vue中的自定义指令分为两类,分别是:

  • 私有自定义指令
  • 全局自定义指令

2.声明私有自定义指令的语法

在每个vue组件中,可以在directives节点下声明私有自定义指令。示例代码如下:

 4.声明全局自定义指令的语法

全局共享的自定义指令需要通过“单页面应用程序的实例对象”进行声明,示例代码如下:

5.updated函数

mounted函数只在元素第一次插入DOM时被调用,当DOM更新时mounted函数不会被触发。updated函数会在每次DOM更新完成后被调用。示例代码如下:

 注意:在vue2的项目中使用自定义指令时,【mounted->bind】【updated->update

6.函数简写

如果mounted和updated函数中的逻辑完全相同,则可以简写成如下格式:

 7.指令的参数值

在绑定指令时,可以通过“等号”的形式为指令绑定具体的参数值,示例代码如下:

Table案例 


1.案例效果

 2.用到的知识点

  • 组件封装
  • 具名插槽
  • 作用域插槽
  • 自定义指令

3.实现步骤

①搭建项目的基本结构

②请求商品列表的数据

封装MyTable组件

④实现删除功能

实现添加标签的功能

 

 

 

 

 

 

 

 

 

 

 

 

 main.js

import { createApp } from 'vue'
import App from './App.vue'
import './index.css'
import './assets/css/bootstrap.css'
import axios from 'axios'
const app = createApp(App)

axios.defaults.baseURL = 'https://applet-base-api-t.itheima.net';
app.config.globalProperties.$http = axios

app.mount('#app')

App.vue

<template>
  <div>
    <h1>这是App根组件</h1>
    <MyTable :data="goodslist">
      <template #header>
        <th>#</th>
        <th>商品名称</th>
        <th>价格</th>
        <th>标签</th>
        <th>操作</th>
      </template>
      <template v-slot:body="{ row, index }">
        <td>{{ index + 1 }}</td>
        <td>{{ row.goods_name }}</td>
        <td>¥{{ row.goods_price }}</td>
        <td>
          <input
            type="text"
            class="form-control form-control-sm form-ipt"
            v-if="row.inputVisible"
            v-focus
            v-model.trim="row.inputValue"
            @blur="onInputConfirm(row)"
            @keyup.enter="onInputConfirm(row)"
            @keyup.esc="row.inputValue = ''"
          />
          <button
            type="button"
            class="btn btn-primary btn-sm"
            v-else
            @click="row.inputVisible = true"
          >
            +Tag
          </button>
          <!-- 循环渲染标签信息 -->
          <span
            class="badge badge-warning ml-2"
            v-for="item in row.tags"
            :key="item"
            >{{ item }}</span
          >
        </td>
        <td>
          <button
            type="button"
            class="btn btn-danger"
            @click="deleteGoods(row.id)"
          >
            删除
          </button>
        </td>
      </template>
    </MyTable>
  </div>
</template>

<script>
import MyTable from "./components/my-table/MyTable.vue";
export default {
  name: "MyApp",
  data() {
    return {
      //商品列表的数据
      goodslist: [],
    };
  },
  created() {
    //发起请求
    this.getGoodsList();
  },
  components: { MyTable },
  methods: {
    async getGoodsList() {
      const { data: res } = await this.$http.get("/api/goods");
      if (res.status !== 0) {
        return console.log("获取商品列表数据失败!");
      }
      this.goodslist = res.data;
    },
    //根据id删除商品
    deleteGoods(id) {
      this.goodslist = this.goodslist.filter((x) => x.id !== id);
    },
    onInputConfirm(row) {
      const val = row.inputValue;
      row.inputValue = "";
      row.inputVisible = false;
      if (!val || row.tags.indexOf(val) !== -1) {
        return;
      }
      row.tags.push(val);
    },
  },
  directives: {
    focus(el) {
      el.focus();
    },
  },
};
</script>

<style lang="less" scoped>
.form-ipt {
  width: 80px;
  display: inline;
}
</style>

MyTable.vue

<template>
  <table class="table table-bordered table-striped">
    <!-- 标题区域 -->
    <thead>
      <tr>
        <slot name="header"></slot>
      </tr>
    </thead>
    <!-- 内容主题区域 -->
    <tbody>
      <tr v-for="(item, index) in data" :key="item.id">
        <slot name="body" :row="item" :index="index"></slot>
      </tr>
    </tbody>
  </table>
</template>

<script>
export default {
  name: "MyTable",
  props: {
    data: {
      type: Array,
      require: true,
      default: [],
    },
  },
  Date() {
    return {};
  },
};
</script>

<style lang="less" scoped>
</style>

总结


①能够知道如何使用ref引用DOM和组件实例

  • 通过ref属性指令引用的名称、使用this.$refs访问引用实例

②能够知道$nextTick的调用时机

  • 组件的DOM更新之后,才执行$nextTick中的回调

③能够说出keep-alive元素的作用

  • 保持动态组件的状态

④能够掌握插槽的基本用法

  • <slot>标签、具名插槽、作用域插槽、v-slot:简写为#

⑤能够知道如何自定义指令

  • 私有自定义指令、全局自定义指令

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

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

相关文章

基于Android的自助导游系统的设计与实现(论文+源码)_kaic

摘 要 随着人们的生活水平的提高&#xff0c;外出旅游已经成为人们放松休闲的主要活动之 一。传统的旅游方式都是团队组织&#xff0c;这在很大程度上制约了游客游玩的自主性。 本文充分利用无线互联网技术的优点&#xff0c;以智能手机作为移动终端&#xff0c;设计一款自助 …

react实现路由跳转动画

下载插件 npm i react-transition-group 配置路由 import { createBrowserRouter as ReactRouter,Navigate } from "react-router-dom";import App from ../App.js import Login from "../view/login.js"; import Home from "../home.js"; co…

Django笔记之in查询及date日期相关过滤操作

这一篇介绍关于范围&#xff0c;日期的筛选 inrangedateyearweekweekdayquarterhour 1、in in 对应于 MySQL 中的 in 操作&#xff0c;可以接受数组、元组等类型数据作为参数&#xff1a; Blog.objects.filter(id__in[1,2,3])对应的 SQL 是&#xff1a; select * from blo…

Linux Shell 脚本编程学习之【第4章 awk命令最详细(第二部分)】

第4章 awk命令最详细 &#xff08;第二部分&#xff09; 1 awk编程1.1 awk模式匹配 2 awk编程示例2.1 第一种调用方式2.2 第二种调用方式2.3 第三种调用方式2.4 记录和域2.5 变量运算2.6 改变分隔符 3 关系和布尔运算符3.1 匹配正则表达式~符号 1 awk编程 awk 是一种编程语言&…

【C++11】智能指针的定义 和 种类 及 使用

智能指针 定义 为什么需要智能指针 在C中&#xff0c;动态分配内存是一项常见的任务&#xff0c;但手动管理分配和释放内存可能会导致很多问题&#xff0c;如内存泄漏、悬垂指针以及多次释放同一块内存等。为了避免这些问题&#xff0c;引入了智能指针的概念&#xff0c;它们…

MySQL主从复制原理及配置

目录 一、MySQL主从复制原理 1、什么是主从复制 2、主从复制原理 二、主从复制配置 1、主服务器数据库配置 &#xff08;1&#xff09;设置server-id值并开启binlog参数&#xff0c;启用二进制日志功能后&#xff0c;重启数据库。 &#xff08;2&#xff09;建立同步账号&a…

LabVIEW基础-lvlib库

文章目录 lvlib库llb库lvlib与llb的区别lvlib常见错误断开vi与库之间的连接 lvlib库 文件-新建-库&#xff0c;创建一个项目库文件。能在项目中创建的文件类型&#xff0c;都可以在库中创建。 在lvlib上右键-添加-文件&#xff0c;将被选中的文件放到lvlib中。被添加进lvlib的…

【PostgreSQL内核学习(八)—— 查询执行(查询执行策略)】

查询执行 查询执行概述查询执行策略可优化语句和数据定义语句四种执行策略策略选择实现Portal执行的过程 声明&#xff1a;本文的部分内容参考了他人的文章。在编写过程中&#xff0c;我们尊重他人的知识产权和学术成果&#xff0c;力求遵循合理使用原则&#xff0c;并在适用的…

大数据分析案例-基于LightGBM算法构建乳腺癌分类预测模型

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

即时通信的方法和webSocket的具体使用

前言 之前遇到过需要即时通讯的场景&#xff0c;刚开始使用的是通过轮询的方式&#xff0c;定时器3秒向服务器请求一次数据&#xff0c;后面发现如果在手机端长时间打开使用此功能的页面&#xff0c;可能会发生手机发热&#xff0c;甚至卡顿的现象。最后改用webSocket&#xf…

js 过滤两个数组中的相同元素

1. filter 和 find 、some ,includes结合使用 let arr [1, 2, 3, 4, 5]; let arr2 [3, 4, 5, 6, 7];const arr3 arr.filter((item) > arr2.includes(item)); const arr4 arr.filter((item) > arr2.find((item2) > item2 item)); const arr5 arr.filter((item)…

Vue3+ElementPlus+TS实现右上角消息数量实时更新

Vue3ElementPlusTS实现右上角消息数量实时更新 背景 项目需求&#xff0c;前端右上角铃铛图标 显示接收到的消息通知&#xff0c;并且显示消息数量以及实时更新。&#xff08;一般是点击操作按钮后增加一条消息通知&#xff0c;图标上的数字也随之更新&#xff09; 【原来的想…

uniapp 微信小程序 姓名脱敏 substring报错问题:Cannot read property ‘substring‘ of undefined

效果图&#xff1a; 刘德华----------刘* 加v-if判断是因为如果是后台数据返回的字段&#xff0c;如果不加判断&#xff0c;substring的时候有可能数据还没渲染完&#xff0c;会报错 <text v-if"userName">{{userName.substring(0, 1) *}}</text>

【Duilib】错误:红色波浪线,无法打开源文件“stdafx.h”

问题 Duilib工程可以编译&#xff0c;但是智能提示&#xff1a;错误&#xff1a;红色波浪线&#xff0c;无法打开源文件“stdafx.h”。 解决方法 1、确认stdafx.h文件位置在vcxproj文件同一目录&#xff0c;并且stdafx.h已添加至DUILIB工程。 2、DUILIB项目属性\C/C\常规 页面…

(css)原生html实现遮罩层弹窗

(css)原生html实现遮罩层弹窗 效果&#xff1a; html <div class"overlay"><div class"content"><!-- 需要遮罩的内容 --> <el-table :data"tableData" size"mini" class"table-class" border stripe…

AutoSAR系列讲解(实践篇)7.4-实验:配置SWCRTE

注意: 实验篇是重点,有条件的同学最好跟着做一遍,然后回头对照着7.1-7.3理解其配置的目的和意义。实验下篇将在7.7节中继续做 一、实验概览 1、实验目的 通过本次实验,主要是让大家对Dev的配置有一个全流程的学习。这里会用到前两节的内容,将其串联起来,让大家能完整的…

【git基本使用】

初识git 一、git安装 1.1 Linux-centos 如果你的的平台是centos&#xff0c;安装git相当简单&#xff0c;以我的centos7.6为例&#xff1a; ⾸先&#xff0c;你可以试着输⼊Git&#xff0c;看看系统有没有安装Git&#xff1a; git-bash: git: command not found 出现像上⾯…

linux同时安装JDK8和JDK11并指定默认版本

1、安装OpenJDK11 yum install java-11-openjdk2、安装OpenJDK 8 yum install java-8-openjdk3.查看Java版本列表 alternatives --list4、查看当前Java版本 java -version5、更改Java版本 alternatives --config java6、设置JAVA_HOME环境变量 vi /etc/profile.d/java.sh…

多线程(JavaEE初阶系列3)

目录 前言&#xff1a; 1.中断一个线程 2.等待一个线程-join() 2.1join()无参调用的使用 2.2join()有参调用的使用 3.线程的状态 3.1观察线程的所有状态 4.多线程带来的风险—线程安全 4.1观察线程不安全 4.2该问题出现的原因 4.3线程不安全问题的解决 4.3.1synchro…

【PostgreSQL内核学习(九)—— 查询执行(数据定义语句执行)】

数据定义语句执行 概述数据定义语句执行流程执行示例 声明&#xff1a;本文的部分内容参考了他人的文章。在编写过程中&#xff0c;我们尊重他人的知识产权和学术成果&#xff0c;力求遵循合理使用原则&#xff0c;并在适用的情况下注明引用来源。 本文主要参考了《PostgresSQL…