10 月 23 - 25 日,QCon 上海站即将召开,现在大会已开始正式报名,可以享受 8 折优惠 了解详情
写点什么

3 个概念,入门 Vue 组件开发

  • 2019-04-01
  • 本文字数:6007 字

    阅读完需:约 20 分钟

3个概念,入门 Vue 组件开发

“组件”是 Vue 中比较基础的概念,但我发现,许多同学对 Vue 组件的概念和由来并不是清楚。因此,我希望通过这个专题,带大家换个角度来分析,最终让大家更清楚组件开发。


首先,我们先不谈组件,我想问大家一个问题:


我们平常用任何编程语言写方法(method)的时候,当一个方法里的逻辑过多时,我们会怎么办?当多个方法里有很多相似的逻辑时,我们该怎么办?


答案很明了:拆分成一个独立的方法。


如果拆分后还是有类似问题呢?那就继续拆分。


类比一下,HTML 也一样。当我们写了一大堆的 HTML 后,发现有不少类似或重复的地方,我们也可以按照拆分的方法,拆分 HTML。除了拆分 HTML 之外,我们还可以拆分针对这段 HTML 书写的逻辑,甚至是样式。拆分后的 HTML,逻辑,样式组合在一起,我们就称之为组件。


这么讲似乎有点抽象,我们来举个例子吧。假如我们要做一个简单的 TodoList 项目,代码如下:


<ul>​    <li>​      <input type="checkbox">​      <span>学习 Vue 属性</span>​      <button>删除</button>​    </li>​    <li>​      <input type="checkbox">​      <span>学习 Vue 事件</span>​      <button>删除</button>​    </li>​    <li>​      <input type="checkbox">​      <span>学习 Vue 插槽</span>​      <button>删除</button>​    </li>  </ul></div>
复制代码


可以看到,我们 li 标签内的内容越来越多,似乎可以把它独立出来,在 Vue 中,通过以下代码就可以将这部分代码独立出来.


通过 Vue.component 定义(注册)一个组件,起名为 todo-item, 组件的 HTML 写在 template 字段上:


Vue.component('todo-item', {  template: `<li>​      <input type="checkbox">​      <span>学习 Vue 属性</span>​      <button>删除</button>​    </li>`})
复制代码


然后,你可以通过下面这样的方式来使用这个组件:


  <ul>​    <todo-item></todo-item>​    <todo-item></todo-item>​    <todo-item></todo-item>  </ul></div>
复制代码


当然前提条件是你要先 new Vue 一个实例,并添加挂载点


new Vue({  el: '#app'  // 提供一个挂载点,这样我们就可以在里面使用 todo-item 了})
复制代码


这样一来清爽了许多,可是这样就变成三个“学习 Vue 属性” 事项了,我们还缺“学习 Vue 事件”和“学习 Vue 插槽” ,怎么办呢,这就要用到 Vue 的属性了。


点击此处,开始你的第一个 Vue 程序


点击此处,了解单文件组件

属性

我们接着改改,调用方法时,可以传递不同的参数,方法也可以接收参数,执行不同的逻辑,加载组件时同样也可以传递不同的参数(属性),组件也可以接收参数(属性)来显示不同的内容:


Vue.component('todo-item', {  props: ['item'], // 声明能接收的参(属)数(性)  // {{item}} 使用传递过来的 item  template: `<li>​      <input type="checkbox">​      <span>{{item}}</span>​      <button>删除</button>​    </li>`})
<div id="app"> <ul>​ <todo-item item="学习 Vue 属性"></todo-item>​ <todo-item item="学习 Vue 事件"></todo-item>​ <todo-item item="学习 Vue 插槽"></todo-item> </ul></div>
复制代码


我们再精简一下:


 <ul>​    <todo-item v-for="item in list" :item="item"></todo-item>  </ul></div>new Vue({  el: '#app',  data() {​    return {​      list: ['学习 Vue 属性', '学习 Vue 事件', '学习 Vue 插槽']​    }  }})
复制代码


这样就可以了,是不是很简单?


点击此处,深入学习 Vue 中组件的属性

事件

我现在已经学完了 Vue 属性,想要从 todolist 里面把它删除掉,这好像并不太容易。这时,我需要给 button 绑定一个事件,当然 Vue 提供给我们了一个简单的方式进行绑定事件,用@xxx 就可以进行事件绑定了(这里的 xxx 指的任一字符串,根据你的实际需要来命名就行)


Vue.component('todo-item', {  props: ['item'],  template: `<li>​      <input type="checkbox">​      <span>{{item}}</span>​      <button @click="handleClick">删除</button>​    </li>`,  methods: {​    handleClick() {​    }  }})
复制代码


然后我们需要把点击事件告诉我们的上层(父组件),Vue 同样给我们提供了一个 API:this.$emit(‘xxx’, …),我们既然是做删除操作,那就是叫 delete 好了,我们还可以传递更多的参数,如 this.item:


handleClick() {  this.$emit('delete', this.item)}
复制代码


上层组件还缺少了一个用来接收 delete 的地方,我们可以通过 @delete 的方式来绑定一个用来接收 delete 事件的方法:


<todo-item v-for=“item in list” :item=“item” @delete=“handleDelete”>


最后只需要在 methods 字段上定义一个 handleDelete 方法,改变 list 数组就完成了我们的删除操作:


new Vue({  el: '#app',  data() {    return {      list: ['学习 Vue 属性', '学习 Vue 事件', '学习 Vue 插槽']    }  },  methods: {    handleDelete(item) {      const index = this.list.findIndex(text=>text === item);      this.list.splice(index, 1);    }  }})
复制代码


以上就是 Vue 中事件的用法。


点击此处,深入学习 Vue 中组件的事件

插槽

现在我想让这个 TodoList 中的“学习 Vue XXX”前加个图标 Icon,怎么办呢?还好 Vue 早就帮我想到了,我们不能再通过属性传递这些带有标签的内容,而是通过一种名叫“插槽”的东西进行传递:


<todo-item v-for="item in list" :item="item" @delete="handleDelete">  <span>我是Icon</span></todo-item>
复制代码


当然我们也不能再用双括号来解析,我们需要使用这种写法来解析:


template: `<li>​      <input type="checkbox">​      <span>{{item}}</span>​      <slot></slot>​      <button @click="handleClick">删除</button>​    </li>`,
复制代码


这种我们称之为默认插槽。


现在我想更进一步,添加两个图标,一个在文字前面,一个在文字后面,没问题:


<todo-item v-for="item in list" :item="item" @delete="handleDelete">  <span slot="prefixIcon">我是前缀Icon</span>  <span slot="suffixIcon">我是后缀Icon</span></todo-item>
复制代码


同样 template 需要更改:


template: `<li>​      <input type="checkbox">​      <slot name="prefixIcon"></slot>​      <span>{{item}}</span>​      <slot name="suffixIcon"></slot>​      <button @click="handleClick">删除</button>​    </li>`,
复制代码


这便是我们的具名插槽。


如果想让功能更加丰富的话,比如我想根据我的 input checkbox 的是否选中来改变图标的颜色,该怎么做?


第一步,记录我们 input 的选中状态,我们使用 Vue 的 v-model 进行 input 的双向绑定:


Vue.component('todo-item', {  props: ['item'],  data() {​    return {​      checked: false, // 默认不选中​    }  },  template: `<li>​      <input type="checkbox" v-model="checked">​      <slot name="prefixIcon"></slot>​      <span>{{item}}</span>​      <slot name="suffixIcon"></slot>​      <button @click="handleClick">删除</button>​    </li>`,  methods: {​    handleClick() {​      this.$emit('delete', this.item)​    }  }})
复制代码


状态有了,现在需要把这个状态传递给上层:


<slot name="prefixIcon" v-bind="{checked}">我是前缀Icon</slot>
复制代码


接收到状态后并根据状态提供不同颜色的图标:


<span slot="prefixIcon" slot-scope="props" :style="{color: props.checked ?'red':'blue'}">我是前缀Icon</span>
复制代码


这就是我们的作用域插槽。


为了方便理解,插槽使用方式我们使用了 Vue 2.5 版本的语法进行讲解,Vue 2.6 的语法可查看视频教程。


点击此处,深入学习 Vue 中组件的插槽


如果你已经阅读到了这里,那么恭喜你,你已经可以进行简单的 Vue 组件开发了。


如果还想学习更多的 Vue 实战技巧,欢迎订阅我的视频课程《Vue 开发实战》


2019-04-01 17:444011

评论 1 条评论

发布
用户头像
<span slot="prefixIcon" slot-scope="props" :style="{color: props.checked ?'red':'blue'}"> 我是前缀 Icon</span>
这行代码里面 slot-scope="props" 是什么意思呢?
2019-04-10 14:34
回复
没有更多了
发现更多内容

Scrum Patterns:产品的自豪感(Product Pride)

Bruce Talk

Scrum 敏捷 Agile Scrum Patterns

架构误区系列5:滥用分布式锁

agnostic

分布式锁

如何召回流失用户

穿过生命散发芬芳

11月月更 流失召回

CleanMyMac2023Mac系统电脑磁盘优化软件

茶色酒

CleanMyMac CleanMyMac2023

ABBYY FineReader16最新版PDF编辑器功能介绍

茶色酒

abbyy

API渗透测试4个关键步骤

阿泽🧸

11月月更 API渗透测试

架构实战营模块 5 作业

陌生流云

架构实战营

网络核心笔记(一)

lxmoe

学习笔记 网络 11月月更

网络核心笔记(二)

lxmoe

学习笔记 网络 11月月更

GitHub标星75k,阿里15W字的Spring高级文档(全彩版),真的太香了

程序知音

Java spring ssm java架构 后端技术

聊聊香港优才-续篇(58/100)

hackstoic

香港优才

Camtasia2023免费电脑录屏视频软件使用教程

茶色酒

Camtasia Camtasia2023

有限状态机

芯动大师

Verilog 11月月更 Melay FSM

OSPF路由协议三

初学者

网络 11月月更

亿级万物互联新时代的物联网消息中间件EMQX调研

宋小生

物联网 mqtt emqx

8年Java开发含泪刷题,架构岗现在好难进,有点崩溃

钟奕礼

Java 程序员 java面试 java编程

这20道微服务面试题,阿里、字节、美团、百度面试都问了

钟奕礼

Java 程序员 java面试 java编程

从基础到实战,阿里巴巴高并发系统设计全彩版手册限时开源

Java全栈架构师

程序员 面试 程序员人生 高并发 架构师

FL Studio21最新版编曲DJ舞曲制作软件

茶色酒

FL Studio FL Studio 21

算法题学习---链表的奇偶重排

桑榆

算法题 11月月更

三到五年互联网公司Java面试题大全

钟奕礼

Java 程序员 java面试 java编程

Redis分布式锁剖析和几种客户端的实现

C++后台开发

redis 分布式 后端开发 C++开发

一篇文章彻底理解 HDFS 的安全模式

明哥的IT随笔

hadoop hdfs

赞不绝口!仅靠阿里P9分享的 Redis 工作手册,拿到60W年薪Offer

程序知音

Java 数据库 redis 后端技术 Redis 6.0

LeetCode题解:783. 二叉搜索树节点最小距离,栈,JavaScript,详细注释

Lee Chen

JavaScript 算法 LeetCode

精选2022年大厂高频Java面试真题集锦(含答案),面试一路开挂

程序知音

java面试 大厂面试 java架构 后端技术 Java面试八股文

2022成功入职阿里:阿里的三套Java研发岗面试题总结(文末有答案)

钟奕礼

Java java面试 java编程 程序员、

2022年华为Java面经,还没搞懂JVM

钟奕礼

Java 程序员 Java 面试 java编程

霸榜巨作!阿里内部顶级大佬整理(Redis 5设计与源码分析)

钟奕礼

Java 程序员 java面试 java编程

阿里、百度、美团、面试题大集合,愿你更轻松拿下大厂offer

钟奕礼

Java java面试 java编程 程序员、

CorelDraw2023主要功能特性

茶色酒

CorelDraw2023 CorelDraw

3个概念,入门 Vue 组件开发_大前端_唐金州_InfoQ精选文章