组件的复用

这里的工程和上一节的一样

先建立一个组件

MyButton.vue

<template>
<button @click="count++">You clicked me {{ count }} times</button>
</template> <script>
export default {
name: "MyButton",
data: () => ({
count: 0
})
}
</script> <style scoped> </style>

引用这个组件

About.vue

<template>
<div class="about">
<my-button></my-button>
<my-button></my-button>
<my-button></my-button>
</div>
</template>
<script>
import MyButton from '../components/MyButton'
export default {
components: {MyButton}
}
</script>

页面:

1. MyButton.vue 就是一个组件,其它位置通过import来引入这个组件,就可以来使用了

2. 注意 一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝

如果不是这样:

data: () => ({
count: 0
})

而是这样:

data: {
count: 0
}

额,会报错~

页面也不能正常:

..

通过 Prop 向子组件传递数据

新建一个子组件

MyTitle.vue

<template>
<h3>{{blog}}</h3>
</template> <script>
export default {
name: "MyTitle",
props: ['blog']
}
</script> <style scoped> </style>

这里通过自定义的属性blog来传递数据,定义在子组件里面

在父组件里面使用,并传入数据

<template>
<div class="about">
<my-title v-for="t in items" :blog="t"></my-title>
</div>
</template>
<script>
import MyTitle from '../components/MyTitle'
export default {
components: {MyTitle},
data: () => ({
items: ['My journey with Vue','Blogging with Vue','Why Vue is so fun']
})
}
</script>

将数据绑定到blog属性上 :blog

页面:

当组件变得复杂,我们需要传递的不止一个数据,如果是多个数据可以通过以下方式:

子组件:MyTitle.vue

<template>
<div>
<h3>{{blog.title}}</h3>
<p>{{blog.content}}</p>
</div>
</template> <script>
export default {
name: "MyTitle",
props: ['blog']
}
</script> <style scoped> </style>

父组件:About.vue

<template>
<div class="about">
<my-title v-for="t in items" :blog="t"></my-title>
</div>
</template>
<script>
import MyTitle from '../components/MyTitle'
export default {
components: {MyTitle},
data: () => ({
items: [
{title:'My journey with Vue',content:'every component must have a single root element (每个组件必须只有一个根元素)'},
{title:'Blogging with Vue',content:'你可以将模板的内容包裹在一个父元素内,来修复这个问题'},
{title:'Why Vue is so fun',content:'看起来当组件变得越来越复杂的时候,我们的博文不只需要标题和内容,还需要发布日期、评论等等。为每个相关的信息定义一个 prop 会变得很麻烦'},
]
})
}
</script>

页面:

通过事件向父级组件发送消息

一些功能可能要求我们和父级组件进行沟通。例如我们可能会引入一个可访问性的功能来放大博文的字号,同时让页面的其它部分保持默认的字号。

Vue 实例提供了一个自定义事件的系统来解决这个问题。我们可以在子组件里调用内建的 $emit 方法并传入事件的名字,来向父级组件触发一个事件

子组件:

<template>
<div>
<h3>{{blog.title}}</h3>
<!--$emit('enlarge-text') 自定义事件,click的时候触发父组件的enlarge-text事件,下同-->
<button v-on:click="$emit('enlarge-text')">放大</button>
<button v-on:click="$emit('shrink-text')">缩小</button>
<p>{{blog.content}}</p>
</div>
</template> <script>
export default {
name: "MyTitle",
props: ['blog']
}
</script> <style scoped> </style>

父组件:

<template>
<div class="about" :style="{ fontSize: postFontSize + 'em' }">
<!--@enlarge-text和@shrink-text 监听来自子组件的自定义事件-->
<my-title v-for="t in items" :blog="t" @enlarge-text="postFontSize += 0.1" @shrink-text="postFontSize -= 0.1"></my-title>
</div>
</template>
<script>
import MyTitle from '../components/MyTitle'
export default {
components: {MyTitle},
data: () => ({
// 控制字号
postFontSize: 1,
items: [
{title:'My journey with Vue',content:'every component must have a single root element (每个组件必须只有一个根元素)'},
{title:'Blogging with Vue',content:'你可以将模板的内容包裹在一个父元素内,来修复这个问题'},
{title:'Why Vue is so fun',content:'看起来当组件变得越来越复杂的时候,我们的博文不只需要标题和内容,还需要发布日期、评论等等。为每个相关的信息定义一个 prop 会变得很麻烦'},
]
})
}
</script>

页面:可以点击放大或者缩小

有的时候我们可能想让子组件来决定文本放大多少,那么也就是用一个事件来抛出一个特定的值,只需要修改子组件的$emit,加上第二个参数:

然后当在父级组件监听这个事件的时候,我们可以通过 $event 访问到被抛出的这个值

或者,父组件的处理函数是一个方法,那么从子组件传过来的$event变成这个方法的第一个参数

处理方法:

插槽

匿名插槽【木有名字的插槽:<slot></slot>】

新建一个子组件:

NoNameSlot.vue

<template>
<p>
<slot></slot>
</p>
</template> <script>
export default {
name: "NoNameSlot"
}
</script> <style scoped> </style>

父组件:

<template>
<div class="about">
<no-name-slot v-for="i in items">
{{i.content}}
</no-name-slot>
</div>
</template>
<script>
import NoNameSlot from '../components/NoNameSlot'
export default {
components: {NoNameSlot},
data: () => ({
items: [
{title:'My journey with Vue',content:'当组件渲染的时候,这个 <slot></slot> 元素将会被替换为父组件传入的当前内容。'},
{title:'Blogging with Vue',content:'插槽内可以包含任何模板代码,包括 HTML'},
{title:'Why Vue is so fun',content:'嗯嗯嗯'},
]
})
}
</script>

一句话:子组件的 <slot></slot> 会被替换成父组件传入的任何内容,但是如果子元素里面没有<slot></slot>,父组件传入的内容会被抛弃

页面:

不信你看,三个p

具名插槽【有名字的插槽:<slot name="header"></slot>】

有时候我们需要多个插槽,不同的位置渲染不同的内容,那么就需要具名插槽了

子组件:MyLayout.vue

<template>
<div id="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
</template> <script>
export default {
name: "MyLayout"
}
</script> <style scoped> </style>

父组件:About.vue

<template>
<div class="about">
<my-layout>
<template slot="header">
<h1>这里是标题啊!</h1>
</template>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<template slot="footer">
<h2>这里是脚丫子</h2>
</template>
</my-layout>
</div>
</template>
<script>
import MyLayout from '../components/MyLayout'
export default {
components: {MyLayout}
}
</script>

页面:

可以看出,父组件在使用的时候,只需要通过指定slot的名字,就可以把指定内容送到对应的插槽上;而那些没有指定名字的,如果存在匿名插槽则会被送到匿名插槽的位置上。如果不存在,则不渲染。

作用域插槽【2.1.0+新增:可从子组件获取数据的可复用的插槽。引申:scope 用于表示一个作为带作用域的插槽的 <template> 元素,它在 2.5.0+ 中被 slot-scope 替代。】

前面两个都是从父组件获取数据,这个恰好反过来,从子组件获取数据。

子组件:

<template>
<div>
<!--只需要绑定数据即可-->
<slot :items="items"></slot>
</div>
</template> <script>
export default {
name: "MyScopeSlot",
data: () => ({
items: ['White','Black','Pink']
})
}
</script> <style scoped> </style>

父组件:

<template>
<div class="about">
<h3>按套路输出数据</h3>
<my-scope-slot>
<template slot-scope="childData">
<ul>
<li v-for="item in childData.items">{{item}}</li>
</ul>
</template>
</my-scope-slot>
<h3>一锅端</h3>
<my-scope-slot>
<template slot-scope="childData">
{{childData.items}}
</template>
</my-scope-slot>
<h3>不使用子组件提供的数据</h3>
<my-scope-slot>
作用域插槽退化为匿名插槽
</my-scope-slot>
</div>
</template>
<script>
import MyScopeSlot from '../components/MyScopeSlot'
export default {
components: {MyScopeSlot}
}
</script>

slot-scope 任何名字都可以,注意在父组件里,childData通过引用子组件的绑定属性名称来获取数据

页面

动态组件【在不同组件之间进行动态切换】

建立三个子组件 ComponentA、ComponentB、ComponentC

<template>
<h2>组件A</h2>
</template> <script>
export default {
name: "ComponentA"
}
</script> <style scoped> </style>

内容一样,只是改个字母,这里不重复了。

父组件

<template>
<div class="about">
<button @click="next">下一个</button>
<!--切换的关键,参数是组件的名字-->
<component :is="view"></component>
</div>
</template>
<script>
import ComponentA from '../components/ComponentA'
import ComponentB from '../components/ComponentB'
import ComponentC from '../components/ComponentC' export default {
components: {ComponentA,ComponentB,ComponentC},
data: ()=> ({
index:0,
componentName:['ComponentA','ComponentB','ComponentC']
}),
computed:{
// 这是一个计算属性,返回当前index对应的组件名字
view: function () {
return this.componentName[this.index];
}
},
methods:{
// 循环index
next: function () {
this.index = ++this.index % 3;
}
}
}
</script>

页面:

--

当在这些组件之间切换的时候,你有时会想保持这些组件的状态,以避免反复重渲染导致的性能问题。也就是说,切换是一个销毁/渲染的过程,失效的被销毁,展示的时候重新渲染。那么如果我们不想要这一浪费的行为,我们更希望那些标签的组件实例能够被在它们第一次被创建的时候缓存下来,只需要把组件用<keep-alive>包裹起来:

<!-- 失活的组件将会被缓存!-->
<keep-alive>
<component v-bind:is="currentTabComponent"></component>
</keep-alive>

Vue(四)组件的更多相关文章

  1. vue中组件的四种方法总结

    希望对大家有用 全局组件的第一种写法 html: <div id = "app"> <show></show></div> js: ...

  2. vue+element ui项目总结点(四)零散细节概念巩固如vue父组件调用子组件的方法、拷贝数据、数组置空问题 等

    vue config下面的index.js配置host: '0.0.0.0',共享ip (假设你的电脑启动了这个服务我电脑一样可以启动)-------------------------------- ...

  3. vue.js组件化开发实践

    前言 公司目前制作一个H5活动,特别是有一定统一结构的活动,都要码一个重复的轮子.后来接到一个基于模板的活动设计系统的需求,便有了下面的内容.借油开车. 组件化 需求一到,接就是怎么实现,技术选型自然 ...

  4. VUE.JS组件化

    VUE.JS组件化 前言 公司目前制作一个H5活动,特别是有一定统一结构的活动,都要码一个重复的轮子.后来接到一个基于模板的活动设计系统的需求,便有了下面的内容.借油开车. 组件化 需求一到,接就是怎 ...

  5. [转] Vue + Webpack 组件式开发(练习环境)

    前言 研究了下别人的 vue 多页面框架, 都是直接复制 package.json 文件,然后在本地 npm install 一下即可, 或者使用官网 vue-cli 工具生成一个项目, 觉得这样虽然 ...

  6. vue父子组件的传值总结

    久违的博客园我又回来了.此篇文章写得是vue父子组件的传值,虽然网上已经有很多了.写此文章的目的就是记录下个人学习的一部分.接下来我们就进入主题吧! 在开发vue项目中,父子组件的传值是避免不掉的. ...

  7. 从零开始学 Web 之 Vue.js(六)Vue的组件

    大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:ht ...

  8. vue学习—组件的定义注册

    组件的定义注册 效果: 方法一: <div id="box"> <v-header></v-header> <hr /> <b ...

  9. vue的组件传输

    vue的组件传输有四种,我个人觉得pubsub(订阅/发布)是最好用的,因为他不用去考虑关系,所以我们下面就只讲解pubsub吧 1) 优点: 此方式可实现任意关系组件间通信(数据)   首先我们需要 ...

  10. Vue兄弟组件通信

    Vue兄弟组件通信之借助中央事件总线 下载链接:https://www.yinxiangit.com 其实要实现兄弟组件通信,就算是通过父子组件通信的方式也是可以达到的,如 子 ——>父——&g ...

随机推荐

  1. HTML/CSS快速入门

    Web概念 JavaWeb 使用java语言开发基于互联网的项目 软件架构 C/S架构:Client/Server 客户端/服务器 用户本地有一个客户端程序,在远程有一个服务端程序 如QQ,英雄联盟. ...

  2. 属于自己的MES(二)必备的主数据

    MES在系统建设前,需要先进行一些必要的数据,这些主数据是支撑MES执行的关键. 1.BOM BOM通常称为“物料清单”,也就是产品结构,在化工.制药.食品.烟草领域也叫“配方”,它主要描述了物料的物 ...

  3. 【错误笔记】MyBatis SQLException: 无效的列类型: 1111

    问题描述: org.springframework.jdbc.UncategorizedSQLException: Error setting null for parameter #1 with J ...

  4. cent os 7 与cent os 6区别

    原文地址:https://www.cnblogs.com/Csir/p/6746667.html 前言 centos7与6之间最大的差别就是初始化技术的不同,7采用的初始化技术是Systemd,并行的 ...

  5. js斐波拉切

    如下: //1 1 2 3 5 8 13 21...//斐波拉切 function fei(n){ if(n==1 || n==2){ return 1 }else{ return fei(n-1)+ ...

  6. 10分钟学会在Ubuntu 18.04 LTS上安装NFS服务器和客户端

    https://www.linuxidc.com/Linux/2018-11/155331.htm

  7. CentOS7 安装配置 MySQL 5.7

    1. 下载 yum 源文件 mysql80-community-release-el7-2.noarch.rpm https://dev.mysql.com/downloads/repo/yum/ 2 ...

  8. Python--day05(数字、字符串、列表)

    1.数字类型 1.  整型  int   long(py2) 2.  小数 float 3.  布尔 bool 4.  复数 complex 2.  字符串类型 只能存一个值,是有序的不可变类型 2. ...

  9. springboot配置SSL自签名证书

    1.证书生成 每一个JDK或者JRE里都有一个工具,叫做:keytool,安装了jdk或jre之后,配置好JAVA环境之后,就可以直接在控制台使用该命令生成自签名证书: 在控制台输入: keytool ...

  10. scala的多种集合的使用(2)之集合常用方法

    一.常用的集合方法 1.可遍历集合的常用方法 下表列出了Traverable在所有集合常用的方法.接下来的符号: c代表一个集合 f代表一个函数 p代表一个谓词 n代表一个数字 op代表一个简单的操作 ...