Vue基础篇--8组件基础 component

Vue基础篇--8组件基础 component

1.简单示例

<div id='components1'>
    <button-conter></button-conter>
</div>
<script>
    // 定义一个名为button-conter组件
    Vue.component("button-conter",{
        data:function () {
            return {
                count:0
            }
        },
        template:`<button v-on:click="count++">You clicked me {{count}}</button>`
    });
    // 创建一个根实例
    new Vue({el:"#components1"})
</script>
  • 组件是可以复用的,这样你在id=‘components1‘的作用域中再定义<button-conter></button-conter>也是可以的,并且它们彼此之间互不影响。
  • 因为组件是可复用的 Vue 实例,所以它们与 new Vue 接收相同的选项,例如 datacomputedwatchmethods 以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项。

2.组件的复用

  • 你可以将组件进行任意次数的复用:
<div id="components-demo">
  <button-counter></button-counter>
  <button-counter></button-counter>
  <button-counter></button-counter>
</div>

注意: 当点击按钮时,每个组件都会各自独立维护它的 count。因为你每用一次组件,就会有一个它的新实例被创建。

data必须是一个函数

  • 当我们定义这个 `组件时,你可能会发现它的data` 并不是像这样直接提供一个对象:
data: {
  count: 0
}

取而代之的是,一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝:

data: function () {
  return {
    count: 0
  }
}

3.组件的组织

  • 通常一个应用会以一颗嵌套的组件树的形式来组织

    例如,你可能会有页头、侧边栏、内容区等组件,每个组件又包含了其它的像导航链接、博文之类的组件。

    为了能在模板中使用,这些组件必须先注册以便 Vue 能够识别。这里有两种组件的注册类型:全局注册局部注册。至此,我们的组件都只是通过 Vue.component 全局注册的:

    Vue.component('my-component-name', {
      // ... options ...
    })

    全局注册的组件可以用在其被注册之后的任何 (通过 new Vue) 新创建的 Vue 根实例,也包括其组件树中的所有子组件的模板中。

    到目前为止,关于组件注册你需要了解的就这些了,如果你阅读完本页内容并掌握了它的内容,我们会推荐你再回来把组件注册读完。

4.通过 Prop 向子组件传递数据

  • Prop 是你可以在组件上注册的一些自定义 attribute。当一个值传递给一个 prop attribute 的时候,它就变成了那个组件实例的一个属性。为了给博文组件传递一个标题,我们可以用一个 props 选项将其包含在该组件可接受的 prop 列表中:
Vue.component('blog-post', {
  props: ['title'],
  template: '<h3>{{ title }}</h3>'
})

一个组件默认可以拥有任意数量的 prop,任何值都可以传递给任何 prop。在上述模板中,你会发现我们能够在组件实例中访问这个值,就像访问 data 中的值一样。

一个 prop 被注册之后,你就可以像这样把数据作为一个自定义 attribute 传递进来:

<blog-post title="My journey with Vue"></blog-post>
<blog-post title="Blogging with Vue"></blog-post>
<blog-post title="Why Vue is so fun"></blog-post>

然而在一个典型应用中,你可能在data里有一个博文数组:

<div id='components1'>
  <button-conter></button-conter>
  <blog-post v-for="post in posts"
  v-bind:title="post.title"
  v-bind:key="post.id"
  ></blog-post>
</div>
// 定义一个名为button-conter组件
Vue.component("button-conter",{
  data:function () {
      return {
          count:0,
      }
  },
  template:`<button v-on:click="count++">You clicked me {{count}}</button>`
});
Vue.component("blog-post",{
  props:['title'],
  template:`<h3>{{title}}</h3>`
})

// 创建一个根实例
new Vue({el:"#components1",
data:{
  posts:[
      {id:1,title:"My journey with Vue"},
      {id:2,title:"Blogging with Vue"},
      {id:3,title:"Why Vue is so fun"},
  ]
}
})

如上所示,你会发现我们可以使用 v-bind 来动态传递 prop。这在你一开始不清楚要渲染的具体内容,比如从一个 API 获取博文列表的时候,是非常有用的。

5.单个根元素

  • 当构建一个 <blog-post> 组件时,你的模板最终会包含的东西远不止一个标题:

    最最起码,你会包含这篇博文的正文:

<h3>{{ title }}</h3>
<div v-html="content"></div>

然而如果你在模板中尝试这样写,Vue 会显示一个错误,并解释道 every component must have a single root element (每个组件必须只有一个根元素)。你可以将模板的内容包裹在一个父元素内,来修复这个问题,例如:

<div class="blog-post">
  <h3>{{ title }}</h3>
  <div v-html="content"></div>
</div>

看起来当组件变得越来越复杂的时候,我们的博文不只需要标题和内容,还需要发布日期、评论等等。为每个相关的信息定义一个 prop 会变得很麻烦:

<blog-post
  v-for="post in posts"
  v-bind:key="post.id"
  v-bind:title="post.title"
  v-bind:content="post.content"
  v-bind:publishedAt="post.publishedAt"
  v-bind:comments="post.comments"
></blog-post>

所以是时候重构一下这个<blog-post>组件了,让它变成接受一个单独的 post prop:

<blog-post
  v-for="post in posts"
  v-bind:key="post.id"
  v-bind:post="post"
></blog-post>
Vue.component('blog-post', {
  props: ['post'],
  template: `
    <div class="blog-post">
      <h3>{{ post.title }}</h3>
      <div v-html="post.content"></div>
    </div>
  `
})

上述的这个和一些接下来的示例使用了 JavaScript 的模板字符串来让多行的模板更易读。它们在 IE 下并没有被支持,所以如果你需要在不 (经过 Babel 或 TypeScript 之类的工具) 编译的情况下支持 IE,请使用折行转义字符取而代之。

现在,不论何时为 post 对象添加一个新的属性,它都会自动地在 <blog-post> 内可用。

6.监听子组件事件

  • 在我们开发<blog-post>组件时,它内部一些功能要求我们和父级组件进行沟通。比如在父组件定义字体大小,子组件中 引入一个辅助功能来放大博文的字号 ,同时页面其他字号保持默认
  • 示例:
    <div id='components1'>
        <!--在父组件中,我们添加一个postFontSize数据属性来支持这个功能-->
        <!--通过 v-on:enlarge-text="postFontSize += 0.1" 监听器,父级组件就会接收该事件并更新 postFontSize 的值-->
      <div :style="{fontSize:postFontSize + 'em'}">
          <blog-post v-for="post in posts"
          v-bind:post="post"
          v-bind:key="post.id"
          v-on:enlarge-text="postFontSize += 0.1"
          ></blog-post>
      </div>
    </div>
    Vue.component("blog-post",{
      props:['post'],
        // 每篇博文正文之前添加一个按钮来放大字号
        // 同时子组件调用内建$emit方法传入事件名称
      template:`<div class="blog-post">
          <h3>{{post.title}}</h3>
          <button v-on:click="$emit('enlarge-text')">Enlarge text</button>
          <div v-html="post.content"></div>
      </div>`
    })
    
    // 创建一个根实例
    new Vue({el:"#components1",
    data:{
      posts:[
          {id:1,title:"My journey with Vue",content:"<span>文章1</span>"},
          {id:2,title:"Blogging with Vue",content:"<span>文章2</span>"},
          {id:3,title:"Why Vue is so fun",content:"<span>文章3</span>"},
      ],
        // 定义默认字体大小
      postFontSize:1
    }
    })
    

使用事件抛出一个值

  • 例如我们想让<blog-post>组件决定它的文本要放大多少,可以通过使用$emit第二个参数提供这个值

    <!--子组件定义传入放大的大小-->
    <button v-on:click="$emit('enlarge-text', 0.1)">
      Enlarge text
    </button>

    然后当父组件监听这个事件时候,我们通过$event 访问抛出这个值:

    <blog-post
      ...
      v-on:enlarge-text="postFontSize += $event"
    ></blog-post>
  • 又或用函数去处理这个事件:
    <blog-post
      ...
      v-on:enlarge-text="onEnlargeText"
    ></blog-post>
    // 那么这个值将会作为第一个参数传入这个方法
    methods: {
      onEnlargeText: function (enlargeAmount) {
        this.postFontSize += enlargeAmount
      }
    }

在组件上使用v-model

  • 自定义事件也可以用于创建支持 v-model 的自定义输入组件。

    <input v-model="searchText">
  • 等价于
    <input
      v-bind:value="searchText"
      v-on:input="searchText = $event.target.value"
    >
  • 当用在组件上时,v-model 则会这样:
<custom-input
  v-bind:value="searchText"
  v-on:input="searchText = $event"
></custom-input>

为了让它正常工作,这个组件内的 `` 必须:

  • 将其 value attribute 绑定到一个名叫 value 的 prop 上
  • 在其 input 事件被触发时,将新的值通过自定义的 input 事件抛出

写成代码之后是这样的:

Vue.component('custom-input', {
  props: ['value'],
  template: `
    <input
      v-bind:value="value"
      v-on:input="$emit('input', $event.target.value)"
    >
  `
})

现在 v-model 就应该可以在这个组件上完美地工作起来了:

<custom-input v-model="searchText"></custom-input>

7.通过插槽分发内容

  • 和 HTML 元素一样,我们经常需要向一个组件传递内容,像这样:
<div id="demo">
        <alert-box>
            Something bad happened
        </alert-box>
</div>
Vue.component("alert-box",{
        template:`
            <div class="demo-alert-box">
                你好啊!
            </div>
        `
    });
    new Vue({el:"#demo"})
  • 我们定义<alert-box>内的内容并没有打印出来,此时你只需要加入<slot></slot>,这样内容都会打印出来。

    Vue.component("alert-box",{
            template:`
                <div class="demo-alert-box">
                    你好啊!
                    <slot></slot>
                </div>
            `
        });
        new Vue({el:"#demo"})

8.动态组件

<div id="app">
    <button @click="change">切换</button>
    <component :is="type"></component>
</div>
Vue.component("One",{
    template:"<span>One</span>"
});
Vue.component("Two",{
    template:"<span>Two</span>"
});
new Vue({
    el:"#app",
    data:{
        type:"One"
    },
    methods:{
        change:function () {
            this.type = (this.type === "One"?"Two":"One")
        }
    }
})

9.解析 DOM 模板时的注意事项

  • 有些 HTML 元素,诸如 ,对于哪些元素可以出现在其内部是有严格限制的。而有些元素,诸如 、 和,只能出现在其它某些特定的元素内部。

    这会导致我们使用这些有约束条件的元素时遇到一些问题。例如:

<table>
  <blog-post-row></blog-post-row>
</table>

这个自定义组件 <blog-post-row>会被作为无效的内容提升到外部,并导致最终渲染结果出错。幸好这个特殊的 is attribute 给了我们一个变通的办法:

<table>
  <tr is="blog-post-row"></tr>
</table>

参照文献:Vue.js组件基础

原文地址:https://www.cnblogs.com/xujunkai/p/12215961.html

时间: 2024-11-05 21:59:10

Vue基础篇--8组件基础 component的相关文章

Linux运维之路 基础篇:Linux基础命令(一)

Linux运维之路 基础篇:Linux基础命令(一) Linux哲学宗旨: 一切皆文件:把几乎所有的资源,包括硬件设备都组织为文件 有众多单一的小程序组成,一个程序制实现一个功能,组成小程序完成复杂操作 尽量避免和用户交互:实现脚本编程,以自动完成某些功能 使用纯文本文件保存配置信息 终端:用户和主机交互时用到的设备 物理终端:直接接入的设备也叫控制台/dev/console 虚拟终端:附加在物理终端上虚拟出的,默认启动六个,Ctrl+Alt(F1~F6),系统启动时,默认启动虚拟终端1,启动终

跟着文档学Vue(三)——组件基础

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" con

Vue 第六章 组件切换component

component案例: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <!--cdn镜像快速导入Vue包--> <script src="https://cdn.bootcss.com/vue/2.6.11/vue.js"><

linux学习基础篇01--硬件基础

最近看马哥的linux运维视频,虽然我是我做软件测试的,但是最近也对运维方面的东西很感兴趣,因为以前总是写写测试框架代码,谢谢自动化测试代码.发现自己懂得东西很少.我的目标是成为一个测试架构师,可是只是会写写代码的话,永远也达不到这个目标.测试架构师需要在各个计算机领域都有一定深度的了解.所以前一段时间学习mysql调优后,现在开始看马哥的linux视频.学习一下运维的知识.这里有一个很诧异的地方就是,运维需要会的东西是很多的,而且要很深.为什么国内运维人员的工资缺普遍还不如我们测试呢.这是个问

申论(基础篇)之基础常识复习建议

一.历史常识复习建议(1~3题) 以历史人物为中心学习相关的历史事实.常识. 二.地理知识复习建议(1~3题) 1.自转和公转 2.中国三级阶梯 3.五种基本地形 4.地貌 三.历史文学常识入门级复习建议(3~8题) 原文地址:https://www.cnblogs.com/fzz9/p/8503832.html

一、基础篇--1.1Java基础-包装类的装箱和拆箱

包装类:java是典型的面向对象编程,但是八种基本数据类型并不支持面向对象编程.基本类型的数据不具备对象的特性,没有属性和方法.沿用它们只是为了迎合人类根深蒂固的习惯,并的确能简单.有效地进行常规数据处理. 但是,这种非面向对象的做法也会带来不便,因此,java为每种基本数据类型分别设计了对应的类,称为包装类. 基本数据类型以及对用的包装类的关系如下: byte Byte short Short int Integer long Long char Char float Float double

ESA2GJK1DH1K:基础篇: 内容简介

说明 1.当前基础篇,升级篇,数据篇,安全篇,微信小程序篇,基本上的功能已经实现,但是实现以后出现各种问题,所以将重新进行整理资料. 当前除了基础篇的资料链接需要重新索要,其它套餐的资料源码将放到原资料的根目录! 注:以前的资料教程在新教程录制完成前都会保留. 2.具体为什么需要重新整理的原因 1,以前的程序移植性差 2.知识点太多,一开始录制没有一个系统的路线,导致教程乱 3.所有的繁琐的基础知识全部以文章形式展现,每一节的视频控制半小时内. 基础篇说明 1.基础篇教程目录 1.1.安装MQT

vue基础篇---vue组件《2》

定义全局组件 我们通过Vue的component方法来定义一个全局组件. <div id="app"> <!--使用定义好的全局组件--> <counter></counter> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script type="text/javascript&quo

Vue组件基础用法

前面的话 组件(Component)是Vue.js最强大的功能之一.组件可以扩展HTML元素,封装可重用的代码.根据项目需求,抽象出一些组件,每个组件里包含了展现.功能和样式.每个页面,根据自己所需,使用不同的组件来拼接页面.这种开发模式使前端页面易于扩展,且灵活性高,而且组件之间也实现了解耦.本文将详细介绍Vue组件基础用法 概述 组件是一个自定义元素或称为一个模块,包括所需的模板.逻辑和样式.在HTML模板中,组件以一个自定义标签的形式存在,起到占位符的功能.通过Vue.js的声明式渲染后,