组件的复用

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

先建立一个组件

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. wordpress常用函数及使用位置

    single 页面: 摘要内容:the_excerpt():如果摘要空,摘取正文内容:需要在循环中使用 获取当下页面的分类:wp_get_post_terms( int $post_id, strin ...

  2. Mac Java Idea 下面Git配置简要教程

    Mac Java Idea 配置简要教程(Sunplay) 1.找到git路径 终端输入:which git 2.在idea的设置git路径 3.测试Git的效果 测试Git成功的效果

  3. iOS----------Bad Gateway

    今天项目因为元数据被拒,再次提交去编辑APP时,发现进不了我的APP界面,出现了如下情况,大概有10多分钟 ,一直进不去 ,公司网络一直不稳定,于是打开了我的VPN,然后就可以了.

  4. requests库下载图片的方法

    方法: 传入图片url,requests.get()方法请求一下,将源码以二进制的形式写在本地即可. 以前一直以为requests库中有特定的方法获取图片,类似urllib.request.urlre ...

  5. Exchange 2010邮件服务器的搭建和部署

    Exchange主要是针对内部网或者企业网用户进行搭建的邮件服务器软件,利用它能够很快地搭建安全性较高的内部网邮件系统. 本次搭建在个人环境中实践,纯属爱好折腾,分四步骤,1.搭建windows 20 ...

  6. windows10滑轮bug

    今天我突然发现我一点也忍受不了在UWP应用.wi10窗口.设置等界面无法使用鼠标滑轮了.这个bug已经困扰了我差不多一年了,从买了这台笔记本就开始了.而且这个问题在中间的某一次升级系统后,也修复了,但 ...

  7. git 多用户多仓库配置

    ssh全称是Secure Shell,即安全Shell,是一种可以进行安全远程登录的协议,在Linux中以OpenSSH为代表,Windows中则有Putty作为实现.ssh的会话建立阶段类似TCP协 ...

  8. react dnd demo2

    import React, { Component } from 'react'; import './App.css'; import Card from './Card'; import HTML ...

  9. scala的多种集合的使用(8)之队列和栈的操作方法

    1.使用队列 队列是一种那个先进先出的队列.1)创建一个队列. scala> import scala.collection.mutable.Queue import scala.collect ...

  10. EXT 设置编辑框为只读

    Ext.getCmp("processResult").setReadOnly(ture);   //processResult是属性的id,setReadOnly(ture)设置 ...