vue.js组件详解

2023-11-01

一、组件的概念及复用

1.1 为什么要使用组件

组件(component)是vue.js最核心的功能,用来实现局部(特定)功能效果的代码集合(html/css/js/image…..)。

组件是可复用的 Vue 实例, 把一些公共的模块抽取出来,然后写成单独的的工具组件或者页面,在需要的页面中就直接引入即可那么我们可以将其抽出为一个组件进行复用。例如页面头部、侧边、内容区,尾部,上传图片,等多个页面要用到一样的就可以做成组件,提高了代码的复用率

非单文件组件:一个文件中包含多个组件。(真正开发中几乎不用)

单文件组件:一个文件中只包含1个组件。

单文件组件由一个xxx.vue 文件的组成(3 个部分):

1. 模板页面

<template>
页面模板
</template>

2. JS 模块对象

<script>
export default {
data() {return {}}, methods: {}, computed: {}, components: {}
}
</script>

3. 样式

<style>
样式定义
</style>

二、使用props传递数据

2.1 基本用法

组件不仅仅是把模板的内容进行复用,更重要的是组件间的通信,通常父组件的模板中包含子组件,父组件要正向地向子组件传递数据以及参数,子组件接收到参数后再根据参数的不同来渲染不同的内容或执行操作。这个正向传递数据的过程就是通过props来实现的。

父组件:vue-cli创建的项目结构中的App.vue为组件之根(父组件)

通过列表页(父组件)与列表项目组件(子组件)为例子,演示props的使用。

父组件示例代码(App.vue):

<template>
  <div id="app">
    <h1>这是列表页</h1>
    <!-- 3.组件调用,并向子组件传递了参数message -->
    <ListItem message="来自列表页的数据"></ListItem>
  </div>
</template>

<script>
 //1.引入子组件ListItem
import ListItem from '@/components/ListItem'
export default {
  name: 'App',
  data(){
    return{
    }
  },
 //2.注册子组件ListItem
  components:{ListItem}  
}
</script>

<style>
</style>

子组件(列表项目组件)接收父组件传递过来的数据,子组件列表项目代码(ListItem.vue):

<template>
  <div class="list">
      <ul>
          <li>这是第一条数据</li>
      </ul>
      <!-- 在页面中把父组件传递过来的数据显示出来 -->
      <p>{{message}}</p>
      <p>{{msg}}</p>
  </div>
</template>

<script>
export default {
    name:'ListItem',
    data(){
        return{
            msg:'我是组件本身的数据'

        }
    },
    //通过props接收父组件传递过来的数据
    props:["message"]
}
</script>

<style scoped>
.list{
    color:#f00;
}
.list p{
    font-weight: 700;
}
</style>

 props中声明的数据与组件data函数返回的数据的主要区别:

  • props中声明的数据来自父级,而data中是组件自己的数据,作用域是组件本身;
  • 这两种数据都可以在模板(template)及方法(method)中使用;

 使用v-bind指令动态绑定props值:

父组件示例代码(App.vue):

<template>
  <div id="app">
    <h1>这是列表页</h1>
    <!-- 3.组件调用,并向子组件动态传递了参数message -->
    <button @click="change()">改变数据</button>
    <ListItem :message="listdata"></ListItem>
  </div>
</template>

<script>
 //1.引入子组件ListItem
import ListItem from '@/components/ListItem'
export default {
  name: 'App',
  data(){
    return{
      listdata:'原始数据'
    }
  },
  methods:{
    change(){
      this.listdata='单击按钮之后的数据'
    }
  },
 //2.注册子组件ListItem
  components:{ListItem}  
}
</script>

<style>
</style>

子组件(列表项目组件)接收父组件动态传递过来的数据,子组件列表项目代码(ListItem.vue)不变。

 初始状态下,listdata设置的字符串为“原始数据”,如左图,单击改变数据的按钮之后,listdata值改变为“单击按钮之后的数据”,如右图所示。

2.2 单向数据流

上一节我们讲到父组件数据变化可以传递给子组件,但是反过来是不成立的,所以props传递数据是单向的。之所以这么设计,就是尽可能将父子组件解耦,避免子组件无意间修改父组件的状态。

业务中经常会遇到两种需要改变props传递过来数据的情况:

父组件传递初始值,子组件将其初始值保存起来,再自己作用域内可以随意使用和更改,这个时候可以在子组件的data中再声明一个数据来引用父组件传递过来的数据。

父组件代码示例:(App.vue)

<template>
  <div id="app">
    <h1>这是列表页</h1>
    <!-- 3.组件调用,并向子组件动态传递了参数message -->
    <ListItem :message="count"></ListItem>
  </div>
</template>

<script>
 //1.引入子组件ListItem
import ListItem from '@/components/ListItem'
export default {
  name: 'App',
  data(){
    return{
      count:'100'
    }
  },
 //2.注册子组件ListItem
  components:{ListItem}  
}
</script>

<style>
</style>

子组件代码: (ListItem.vue)

<template>
  <div class="list">
      <ul>
          <li>这是第一条数据</li>
      </ul>
      <!-- 在页面中把父组件传递过来的数据显示出来 -->
      <p>{{receive}}</p>
      <p style="color:green">{{msg}}</p>
  </div>
</template>

<script>
export default {
    name:'ListItem',
    data(){
        return{
            msg:'我是组件本身的数据',
            receive:this.message
        }
    },
    //通过props接收父组件传递过来的数据
    props:["message"]
}
</script>

<style scoped>
.list{
    color:#f00;
}
.list p{
    font-weight: 700;
}
</style>

子组件中声明了receive,在组件初始化的时候就会获得来自父组件的message,之后就与message无关了,只需要维护receive,这样就避免了直接操作message。

三、组件通信

通过前面的学习,我们已经知道父组件与子组件通信通过props传递数据就可以,但是vue组件通信的场景远不止这一种,最容易想到的还有子组件传给父组件。组件之间传值可以用下图表示:

 组件通信流程图

3.1 自定义事件及$emit方法

Vue.js允许正向传值,也就是父组件传值给子组件。正向传值不需要条件触发,是主动的,逆向传值则是不允许的,需要主动触发,需要主动抛出自定义事件去监听。

语法:

this.$emit('event',val)

$emit为实例方法,用来触发事件监听。其中,参数event代表自定义事件名称,参数val代表通过自定义事件传递的值,注意这里的val为可选参数。

示例代码:(父组件App.vue)

<template>
  <div id="app">
    <h1>父组件</h1>
    <p>子组件传递的数据:{{message}}</p>
    <!-- 通过父组件给子组件绑定一个自定义事件change,实现子给父传数据 -->
    <ListItem @change='getVal'></ListItem>
  </div>
</template>

<script>
 //1.引入子组件ListItem
import ListItem from '@/components/ListItem'
export default {
  name: 'App',
  data(){
    return{
      message:""
    }
  },
  methods:{
    getVal(val){
      this.message=val
    }
  },
 //2.注册子组件ListItem
  components:{ListItem}  
}
</script>

<style>
</style>

示例代码:(子组件ListItem.vue)

<template>
  <div class="list">
      <h1>子组件</h1>
      <button @click="fn()">单击子组件传值父组件</button>
  </div>
</template>

<script>
export default {
    name:'ListItem',
    data(){
        return{
            cMsg:"子组件要传递给父组件的数据信息"
        }
    },
    methods:{
        fn(){
            this.$emit("change",this.cMsg)
        }
    }
}
</script>
<style scoped>

</style>

 

    emit初始显示状态                                             单击按钮之后传值父组

3.2 兄弟组件通信的处理方式

兄弟组件之间的传值最容易想到的解决方案是通过共同的父组件进行中转,这里假设一个场景,组件1中的某个数量需要在组件2中同步展示,这个时候就会涉及到兄弟组件之间的传值。通过一个案例来看一下具体代码的实现方式:

示例代码:(App.vue)

<template>
  <div id="app">
    <h1>父组件</h1>
    <p>{{message}}</p>
    <child-one @change='getVal'></child-one>
    <child-two :count="message"></child-two>
  </div>
</template>

<script>
 //1.引入子组件ListItem
import ChildOne from './components/ChildOne.vue'
import ChildTwo from './components/ChildTwo.vue'
export default {
  name: 'App',
  data(){
    return{
      message:0
    }
  },
  methods:{
    getVal(val){
      this.message=val
    }
  },
 //2.注册子组件ListItem
  components:{ChildOne,ChildTwo}  
}
</script>

<style>
</style>

示例代码:(ChildOne.vue

<template>
  <div class="one">
      <h3>子组件</h3>
      <button @click="fn">传值到父组件</button>
  </div>
</template>

<script>
export default {
    name:'ChildOne',
    data(){
        return{
            num:'10'
        }
    },
    methods:{
        fn(){
            this.$emit('change',this.num);
        }
    }

}
</script>

<style>
.one{
    border: 1px solid #000;
    padding: 10px;
    margin-bottom: 10px;

}
</style>

示例代码:(ChildTwo.vue

<template>
  <div class="two">
      <h3>子组件2</h3>
      <P>{{count}}</P>
  </div>
</template>
<script>
export default {
    name:'ChildTwo',
    data(){
        return{

        }
    },
    props:["count"]
}
</script>
<style>
.two{
    border: 1px solid #000;
    padding: 10px;
    margin-bottom: 10px;
}
</style>

兄弟组件传值初始显示

 兄弟组件传值之后显示

四、slot分发内容

4.1 什么是slot

slot的官方定义是用于组件内容分发,slot还有一个形象的名字“插槽”。简单通俗的解释就是在组件化开发中,虽然组件是一样的,但是在不同的使用场景,组件的某一部分需要有不同的内容显示。

4.2 匿名slot

匿名slot从字面理解就是没有名字的插槽,特点是可以放任何内容。

假设场景:设想一个弹出提示框的场景,提示框都包括头部、中间内容和底部内容三部分,头部和底部都是固定不变的,改变的知识中间内容,所以我们在定义组件时可以将中间内容定义为插槽

示例代码:(子组件popup.vue)

<template>
  <div>
      <p>头部区域</p>
      <!-- 在变化内容区域定义一个插槽 -->
      <slot>如果没有分发内容,则显示默认提示</slot>
      <p>底部区域</p>
  </div>
</template>

<script>
export default {
    data(){
        return{

        }
    }

}
</script>
<style>
</style>

示例代码:(父组件App.vue)

<template>
  <div id="app">
    <popup>
      <!-- 插槽显示的具体内容 -->
      <h1>显示弹出框内容</h1>
    </popup>
  </div>
</template>

<script>
 //1.引入子组件popup
import Popup from './components/popup.vue'
export default {
  name: 'App',
  data(){
    return{
      message:0
    }
  },
  methods:{
  
  },
 //2.注册子组件ListItem
  components:{Popup}  
}
</script>

<style>
</style>

 4.3 具名slot

具名slot可以用一个特殊属性name来配置如何分发内容,多个slot可以有不同的名字,具名slot将匹配内容片段中有对应slot特性的元素。

代码示例:(computer.vue子组件)

<template>
  <div>
      <slot name="CPU">这儿是CPU插槽</slot>
      <slot name="GPU">这儿是显卡插槽</slot>
      <slot name="Memory">这儿是内存插槽</slot>
      <slot name="Hard-drive">这儿是硬盘插槽</slot>
  </div>
</template>

<script>
export default {
  data(){
    return{

    }
  },
  components:{}

}
</script>
<style>
</style>

 代码示例:(App.vue父组件)

<template>
  <div id="app">
    <computer>
      <!-- 插槽显示的具体内容 -->
      <div slot="CPU">Initel Core i7</div>
      <div slot="GPU">GTX980Ti</div>
      <div slot="Memory">Kingston 32G</div>
      <div slot="Hard-drive">Samsung SSD 1T</div>
    </computer>
  </div>
</template>

<script>
 //1.引入子组件computer
import Computer from './components/computer.vue'
export default {
  name: 'App',
  data(){
    return{
      message:0
    }
  },
  methods:{
    
  },
 //2.注册子组件computer
  components:{Computer}  
}
</script>

<style>
</style>

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

vue.js组件详解 的相关文章

  • WebPack 源映射令人困惑(重复文件)

    我决定在我今天正在启动的一个新项目上尝试 WebPack 并且我从源映射中得到了非常奇怪的行为 我在文档中找不到任何相关信息 在浏览 StackOverflow 时也找不到其他人遇到此问题 我目前正在查看由以下公司制作的 HelloWorl
  • firebase.storage() 不是玩笑测试用例中的函数

    我正在使用 Jest 来测试我的 firebase 功能 这一切都在浏览器中进行 因此我与服务器端的 firebase 没有任何冲突 当我使用firebase auth or firebase database 一切正常 当我尝试使用时fi
  • 始终滚动 div 元素而不是页面本身

    我有一个带有内部的页面布局 div 包含页面上重要内容的元素 设计的重要部分是 content height 300px width 500px overflow scroll 现在 当包含的文本大于 300px 时 我需要能够滚动它 是否
  • 如何使用 CSS 或 javascript 创建圆角

    复制 使用 CSS 创建圆角的最佳方法是什么 https stackoverflow com questions 7089 what is the best way to create rounded corners using css 7
  • 如何在 Asp.Net MVC 上实现客户端 Ajax 登录(Asp.Net Webforms 解决方案的链接位于此处)

    我正在尝试在 Asp Net MVC 上实现客户端 ajax 登录 我以前在 WebForms 上设置得很好 但现在我已经转向 MVC 这给我带来了一些麻烦 如果您想要有关 Asp Net Webforms 的客户端 Ajax 登录的教程
  • 如何在没有数据库的情况下创建AJAX分页?

    是否可以在没有 MySQL 帮助的情况下获取 AJAX 分页页面 难道我不能只添加一个包含我需要显示的文本和标记的 PHP 文件 然后通过单击页码将该内容提供给用户吗 那么可以用纯 jQuery 和 PHP 来实现吗 您会使用什么代码方法来
  • 如何使用 QuerySelector 获得第二个匹配项?

    以下语句给出了该类的第一个元素titanic element document querySelector titanic 我如何检索具有相同类的第二个元素 Use document querySelectorAll https devel
  • Bootstrap shown.bs.tab 事件不起作用

    我正在使用灵活的模板 http the8guild com themes html flexy v1 7 stylesPage html 使用引导程序 并且我无法让选项卡上的 shown bs tab 事件正常工作 我已经成功让它发挥作用J
  • 可拖动的非模态弹出窗口 Jquery Mobile

    我希望在 Jquery mobile 中有一个弹出窗口 它不会阻止用户与页面交互 并且 data dismissible false 即当页面的另一部分与页面的另一部分交互并保持可见时 弹出窗口不会消失 我已经尝试过这个 popupNew
  • 角度引导手风琴数据绑定问题

    我有 2 个相同型号的下拉菜单 一个位于手风琴内部 另一个位于外部 外部下拉菜单在 2 路数据绑定方面工作良好 但手风琴内部的下拉菜单似乎只有 1 路绑定 换句话说 在 UI 中选择并不会设置模型值 我找到了一个建议here https s
  • Ember:命名出口错误

    我不知道为什么我的模板没有在指定的插座中呈现 这是我第一次尝试学习 ember 我被困在指定的渠道上 我想渲染侧边栏模板 in the outlet sidebar 和内容模板 in the outlet content 但我不断在控制台中
  • 可点击的进度条

    我正在使用 Angular 并在 JavaScript 的帮助下开发了一个可点击的进度条 这是我能做到的最好的 有没有办法将滑块放置在进度条内但不干扰进度可视化 堆栈闪电战 https stackblitz com edit angular
  • 在流星收集加载时显示加载程序

    我有一个模板 task list 看起来像这样 each tasks gt task each Template task list tasks返回一个集合 在用户界面中 加载似乎需要一些时间 当集合正在加载时 我想显示一个加载指示器 关于
  • 从数据库中给定时间起经过的时间

    我有一个 HTML 表 其中包含从数据库中提取的记录 我正在使用 PHP MySQL 我的表中名为 Timer 的列未从数据库中检索 我需要在此处显示经过的时间 从数据库中的特定时间开始 例如 假设现在的时间是2013年2月21日下午6点2
  • Nuxt + Vuex - 如何将 Vuex 模块分解为单独的文件?

    在 Nuxt 文档中 here https nuxtjs org guide vuex store module files 它说 您可以选择将模块文件分解为单独的文件 state js actions js mutations js an
  • Chrome:window.print() 打印对话框仅在页面重新加载后打开 (javascript)

    我面临着一个非常奇怪的问题 我正在从 javascript 文件调用 window print 这在 Safari IE Firefox 中运行良好 直到两小时前 它在 Chrome 中也运行良好 版本29 0 1547 57 我没有更改我
  • 通过ajax POST提交两次表单

    插入到mysql using php通过文件调用AJAX 前insert语句php代码执行select查询到查找重复记录并继续insert statement Issue 从ajax调用php文件时 它执行了两次并得到作为重复记录的响应 好
  • 谷歌浏览器不显示一个网站的alert()弹出窗口

    我正在开发一个 javascript 循环 该循环会随着循环的进行而提醒每个键值 为了加快速度 我选中了 阻止此页面创建其他对话框 框 通常这只会抑制一个例程的弹出窗口 但它们还没有回来 在 Google Chrome 中 alert 消息
  • 关于 Node.js Promise then 和 return?

    我对承诺感到困惑 I use 那么就答应没有返回像这样 new Promise resolve reject gt resolve 1 then v1 gt console log v1 new Promise resolve reject
  • angularjs 将 ngModel 从包装器指令传递到包装器指令

    我是 Angular 的新手 但仍然痛苦地纠结于自定义指令 我想重用这段 HTML

随机推荐

  • 【ubuntu】ubuntu添加或删除用户

    文章目录 1 创建新用户 2 为新用户填加超级用户权限 方法一 填加新用户到sudo group 方法二 在 etc sudoers中指定用户的权限 3 删除用户 创建新用户的意义不再多述 最直观的就是多个人用同一台机器 要为每个人创建一个
  • tomcat自动加载改变的class文件,且无需重启

    不重启Tomcat有两种方式 热部署 热加载 热部署 容器在运行时重新部署整个项目 这类环境下 一般整个内存会被清空 重新加载 这类方式有可能造成sessin丢失等问题 tomcat 6以上已解决该问题 热加载 最好是在调试过程中使用 以免
  • Caffe源码:math_functions 解析

    目录 目录 主要函数 caffe cpu gemm 函数 caffe cpu gemv 函数 caffe axpy 函数 caffe set 函数 caffe add scalar 函数 caffe copy 函数 caffe scal 函
  • 基于ChatGPT-API实现聊天机器人服务

    1 背景 要基于GPT自己去实现一个聊天机器人服务功能实现上其实特别简单 将上游服务过来的请求转换为GPT接口请求发出去然后直接返回或者回调给上游服务即可 但是其中的一些其他问题不知道大家有没有考虑过 1 搞成一个大同步的实现 当并发真的上
  • 集合方法的代码

    创建一个集合 获取从 某一索引开始到某一索引的前一位结束的代码 class b public static void main String args List
  • GO语言学习-变量2和常量与iota枚举

    变量进阶 1 多重赋值 从左至右依次匹配 如果有不需要的数据用匿名变量处理 2 匿名变量 下划线 丢弃数据不处理 匿名变量主要用于配合函数返回值使用 注 go语言的函数返回值可以有多个 使用匿名变量可以舍去不需要的返回值 package m
  • 下载安装Android Studio教程

    步骤1 下载Android Studio 访问Android Studio官方网站 https developer android com studio 点击 下载Android Studio 按钮 选择适用于您操作系统的版本 然后下载安装
  • Unix Shell 范例精解——awk课后题

    题目数据如下 Mike Harrington 510 548 1278 250 100 175 Christian Dobbins 408 538 2358 155 90 201 Susan Dalsass 206 654 6279 250
  • Three.js 基础- 第 2 章 - 几何体BufferGeometry

    Three js 基础 第 2 章 几何体BufferGeometry Three js教程 几何体BufferGeometry 在Three js中 几何体是3D对象的基本形状 本教程将介绍如何使用缓冲类型几何体BufferGeometr
  • 【独家源码】ssm高校试卷管理系统i0lzr应对计算机毕业设计困难的解决方案

    本项目包含程序 源码 数据库 LW 调试部署环境 文末可获取一份本项目的java源码和数据库参考 系统的选题背景和意义 选题背景 高校试卷管理是教学工作中的重要环节 涉及到试卷的编写 存储 分发和评阅等多个方面 然而 传统的试卷管理方式存在
  • [转]Java 线程池的原理与实现

    最近在学习线程池 内存控制等关于提高程序运行性能方面的编程技术 在网上看到有一哥们写得不错 故和大家一起分享 分享 Java 线程池的原理与实现这几天主要是狂看源程序 在弥补了一些以前知识空白的同时 也学会了不少新的知识 比如 NIO 或者
  • SoftwareSerial库的使用——Arduino软件模拟串口通信

    除HardwareSerial外 Arduino还提供了SoftwareSerial类库 它可以将你的其他数字引脚通过程序模拟成串口通信引脚 通常我们将Arduino UNO上自带的串口称为硬件串口 而使用SoftwareSerial类库模
  • 如何开启计算机cpu虚拟化,电脑开启虚拟化设置的方法 如何开启虚拟化设置

    虚拟化设置的开启其实很简单 因为大家没有接触和操作过 所以一开始会不知所措 虚拟化设置的开启其实很简单 因为大家没有接触和操作过 所以一开始会不知所措 小编在这里为广大玩家深度总计虚拟化开启方法 方便大家在电脑端更流畅的体验手机游戏 虚拟化
  • maven工程依赖的jar包,在本地仓库有,但是pom.xml文件却报错找不到jar包

    例如 Missing artifact com ibm db2 db2jcc license cisuz jar 10 1 但在我本地的仓库中却存在这个jar包 查找了很多的资料发现了两种解决方法 第一种 在eclipse中的window
  • 透彻了解inlining的里里外外——条款30

    Inline函数 多棒的点子 它们看起来像函数 动作像函数 比宏好得多 见条款2 可以调用它们又不需要蒙受函数调用所招致的额外开销 你还能要求更多吗 你实际获得的比想到的还多 因为 免除函数调用成本 只是故事的一部分而已 编译器最优化机制通
  • 2021美赛F题

    2021年 问题E 重新优化食物系统 最近的事件向我们表明 我们的全球粮食系统即使在世界的某些地区也是不稳定的 它通常服务于全世界 这些不稳定的部分原因是我们目前的全球气候变化 庞大的国内和国际食品生产商和经销商体系 这个食物系统 使食物的
  • CUDA矩阵乘法优化

    前言 纸上的来终觉浅 绝知此事要躬行 naive写法 一个矩阵的乘法简单如下 C A B 一般用gemm A B C M N K 来表示 其中的m n k代表的位置如下 默认是k表示消失的纬度 上图的红色虚线围起来的是一个block要负责的
  • MySQL存储引擎InnoDB与Myisam的六大区别

    MySQL有多种存储引擎 每种存储引擎有各自的优缺点 可以择优选择使用 MyISAM InnoDB MERGE MEMORY HEAP BDB BerkeleyDB EXAMPLE FEDERATED ARCHIVE CSV BLACKHO
  • MySQL注入绕安全狗脚本 -- MySQLByPassForSafeDog,以及端口爆破工具 -- PortBrute配置使用

    工具介绍 此Tamper仅仅适用于MySQL数据库 在SQLMap使用过程中添加参数 tamper MySQLByPassForSafeDog 安装与使用 1 安装网站安全狗Apache最新版 2 启用安全狗 不加MySQLByPassFo
  • vue.js组件详解

    一 组件的概念及复用 1 1 为什么要使用组件 组件 component 是vue js最核心的功能 用来实现局部 特定 功能效果的代码集合 html css js image 组件是可复用的 Vue 实例 把一些公共的模块抽取出来 然后写