一、组件化开发概述
  1.组件化开发思想
    标准
    分治:不同的功能分配到不同的组件中
    重用:
    组合
  2.编程中的组件化思想体现
  3.组件化规范:
    Web Components
      我们希望尽可能多的重用代码
      自定义组件的方式不太容易(html、css和js)
      多次使用组件可能导致冲突
    Web Components通过创建封装好功能的定制元素解决上述问题
    Vue部分实现了上述规范
    不同的功能封装到不同的组件中,组件可以组合以形成完整的应用
 
二、组件的注册
 
  2.1 全局组件注册语法
    Vue.component(组件名称,{
      data:组件数据,
      template:组件模板内容
    })
 
  例:
1 // 定义一个名为button-counter的组件
2 Vue.component('button-counter',{
3 data:function(){
4 return{
5 count:0
6 }
7 },
8 template:`<button @click='count++'>点击了{{count}}次</button>`
9 });
  
  2.2 组件的用法
1 <div id="app">
2 <button-counter></button-counter>
3 <button-counter></button-counter>
4 <button-counter></button-counter>
5 </div>
    注:组件可以重用,且组件之间是相互独立的
  2.3 组件注册注意事项
    1.data必须是一个函数
      分析函数与普通对象的对比
 
    2.组件模板内容必须是单个的根元素
      分析实际演示效果
 
    3.组件模板内容可以是模板字符串
      模板字符串需要浏览器提供支持(ES6语法)
 
    4.组件的命名方式
      短横线
      Vue.component('my-component',{/*...*/})
      驼峰式
      Vue.component('MyComponent',{/*...*/})
    

      如果使用驼峰式命名组件,那么在使用组件的时候,只能在字符串模板中用驼峰的方式使用组件,但是在普通的标签模板中,必须使用短横线的方式使用组件
  2.4 局部组件注册
    var ComponentA = { /* ... */}
    var ComponentB = { /* ... */}
    var ComponentC = { /* ... */}
    new Vue({
      el:'#app',
      components:{
        'component-a':ComponentA,
        'component-b':ComponentB,
        'component-c':ComponentC,
      }
    })
 1 var HelloWorld = {
2 data:function(){
3 return{
4 msg:'Hello World'
5 }
6 },
7 template:`<div>{{msg}}</div>`
8 };
9
10 var HelloTom = {
11 data:function(){
12 return{
13 msg:'Hello Tom'
14 }
15 },
16 template:`<div>{{msg}}</div>`
17 };
18
19 var HelloJerry = {
20 data:function(){
21 return{
22 msg:'Hello Jerry'
23 }
24 },
25 template:`<div>{{msg}}</div>`
26 };
27 var vm = new Vue({
28 el:'#app',
29 data:{
30
31 },
32 components:{
33 'hello-world':HelloWorld,
34 'hello-tom':HelloTom,
35 'hello-jerry':HelloJerry
36 }
37 })
    注:局部组件只能在父组件中使用,不能在其他的组件中使用
 
三、Vue调试工具
  3.1 调试工具安装
    (1) 克隆仓库
    (2) 安装依赖包
    (3) 构建
    (4) 打开Chrome扩展页面
    (5) 选中开发者模式
    (6) 加载已解压的扩展,选择shells/chrome
 
四、组件间数据交互
   
  4.1 父组件向子组件传值
 
    1.子组件中通过props接收父组件传递过来的内容,具体通过属性名来接收
    2.父组件通过属性将值传递给子组件,属性绑定有两种方式,一是写死,二是动态绑定
    3.属性可以传递多个,具体可以在props中多加参数
1 <div id="app">
2 {{pmsg}}
3 <menu-item title='来自父组件的值'></menu-item>
4 <menu-item :title='ptitle' content='hello'></menu-item>
5 </div>
 1 Vue.component('menu-item',{
2 props:['title','content'],
3 data:function(){
4 return{
5 msg:'子组件自身的数据'
6 }
7 },
8 template:`<div>{{msg + '----' + title + '----' + content}}</div>`
9 })
10 var vm = new Vue({
11 el:'#app',
12 data:{
13 pmsg:'父组件中的内容',
14 ptitle:'父组件传向子组件的动态绑定的数据'
15 }
16 })

    

   4.2 props属性名规则
     1.在props中使用驼峰的形式,模板中需要使用短横线的形式
     2.字符串形式的模板中没有这个限制   
1 <div id="app">
2 {{pmsg}}
3 <menu-item :menu-title='ptitle'></menu-item>
4 </div>
 1 Vue.component('third-com',{
2 props:['testTitle'],
3 template:`<div>{{testTitle}}</div>`
4 })
5 Vue.component('menu-item',{
6 props:['menuTitle'],
7 template:`<div>{{menuTitle}}<third-com testTitle="啦啦啦"></third-com></div>`
8 })
9 var vm = new Vue({
10 el:'#app',
11 data:{
12 pmsg:'父组件中的内容',
13 ptitle:'动态绑定属性'
14 },
15 })
    4.3 props属性值类型
 
      字符串  String
      数值     Number
      布尔值  Boolean
      数组     Array
      对象     Object 1<div id="app"> 2<!--       
 3             字符串  String
4 数值   Number
5 布尔值  Boolean
6 数组   Array
7 对象   Object
8 -->
9 <menu-item :pstr='pstr' :pnum='pnum' :pboo='pboo' :parr='parr' :pobj='pobj'></menu-item>
10 </div>
 1 Vue.component('menu-item',{
2 props:['pstr','pnum','pboo','parr','pobj'],
3 template:`<div>
4 <div>{{"传递的是字符串" + pstr}}</div>
5 <div>{{"传递的是数字" + pnum}}</div>
6 <div>{{"传递的是布尔值" + pboo}}</div>
7 <div>数组:</div>
8 <ul>
9 <li :key='index' v-for='(item,index) in parr'>{{item}}</li>
10 </ul>
11 <div>{{"传递的是对象:"}}<span>{{pobj.name}}</span><span>{{pobj.age}}</span></div>
12 </div>`
13 })
14 var vm = new Vue({
15 el:'#app',
16 data:{
17 pmsg:'父组件中的内容',
18 pstr:'hello',
19 pnum:12,
20 pboo:true,
21 parr:['apple','orange','banana'],
22 pobj:{
23 name:'lisi',
24 age:12
25 }
26 }
27 })

       

    4.4 子组件向父组件传值
 
      注:props传递数据原则: 单向数据流,只允许父组件向子组件传递数据,不允许子组件直接操作props的数据
 
      1. 子组件通过自定义事件向父组件传值
        <button v-on:click='$emit("enlarge-text")'>扩大字体</button>
 
      2. 父组件监听子组件事件
        <menu-item v-on:enlarge-text='fontSize += 0.1'></menu-item>
 
1 <div id="app">
2 <div :style='{fontSize:fontSize + "px"}'>{{pmsg}}</div>
3 <menu-item :parr='parr' @enlarge-text='handle'></menu-item>
4 </div>
 1  /*
2 props传递数据原则: 单向数据流,只允许父组件向子组件传递数据,不允许子组件直接操作props的数据
3 */
4 Vue.component('menu-item',{
5 props:['parr'],
6 template:`
7 <div>
8 <ul>
9 <li :key='index' v-for='(item,index) in parr'>{{item}}</li>
10 </ul>
11 <button @click='parr.push("lemon")'>点击</button>
12 <button @click='$emit("enlarge-text")'>扩大父组件中字体大小</button>
13 </div>
14 `
15 })
16 var vm = new Vue({
17 el:'#app',
18 data:{
19 pmsg:'父组件中内容',
20 parr:['apple','orange','banana'],
21 fontSize:10
22 },
23 methods: {
24 handle:function(){
25 // 扩大字体大小
26 this.fontSize += 5;
27 }
28 },
29 })
      
      3. 子组件通过自定义事件向父组件传递消息
        <button v-on:click='$emit("enlarge-text",0.1)'>扩大字体</button>
 
      4. 父组件监听子组件的事件
        <menu-item v-on:enlarge-text='fontSize += $event'></menu-item>
        $event是固定的
1 <div id="app">
2 <div :style='{fontSize:fontSize + "px"}'>{{pmsg}}</div>
3 <menu-item :parr='parr' @enlarge-text='handle($event)'></menu-item>
4 </div>
 1  Vue.component('menu-item',{
2 props:['parr'],
3 template:`
4 <div>
5 <ul>
6 <li :key='index' v-for='(item,index) in parr'>{{item}}</li>
7 </ul>
8 <button @click='parr.push("lemon")'>点击</button>
9 <button @click='$emit("enlarge-text",5)'>扩大父组件中字体大小</button>
10 <button @click='$emit("enlarge-text",10)'>扩大父组件中字体大小</button>
11 </div>
12 `
13 })
14 var vm = new Vue({
15 el:'#app',
16 data:{
17 pmsg:'父组件中内容',
18 parr:['apple','orange','banana'],
19 fontSize:10
20 },
21 methods: {
22 handle:function(val){
23 // 扩大字体大小
24 this.fontSize += val;
25 }
26 },
27 })
 
 
    4.5 非父子组件间传值
      1. 单独的事件中心管理组件间的通信
        var eventHub = new Vue()
      2. 监听事件与销毁事件
        eventHub.$on('add-todo',addTodo)
        eventHub.$off('add-todo')
      3. 触发事件
        eventHub.$emit('add-todo',id)

   

1 <div id="app">
2 <div>父组件</div>
3 <div><button @click='handle'>销毁事件</button></div>
4 <test-tom></test-tom>
5 <test-jerry></test-jerry>
6 </div>
 1  // 提供事件中心
2 var hub = new Vue();
3
4 Vue.component('test-tom',{
5 data:function(){
6 return{
7 num:0
8 }
9 },
10 template:`
11 <div>
12 <div>TOM:{{num}}</div>
13 <div>
14 <button @click='handle'>点击</button>
15 </div>
16 </div>
17 `,
18 methods: {
19 handle:function(){
20 // 触发兄弟组件的事件
21 hub.$emit('jerry-event',2);
22 }
23 },
24 mounted:function(){
25 // 监听事件
26 hub.$on('tom-event',(val) =>{
27 this.num += val;
28 });
29 }
30 });
31 Vue.component('test-jerry',{
32 data:function(){
33 return{
34 num:0
35 }
36 },
37 template:`
38 <div>
39 <div>JERRY:{{num}}</div>
40 <div>
41 <button @click='handle'>点击</button>
42 </div>
43 </div>
44 `,
45 methods: {
46 handle:function(){
47 // 触发兄弟组件的事件
48 hub.$emit('tom-event',1);
49 }
50 },
51 mounted:function(){
52 // 监听事件
53 hub.$on('jerry-event',(val) =>{
54 this.num += val;
55 });
56 }
57 });
58
59 var vm = new Vue({
60 el:'#app',
61 data:{
62
63 },
64 methods: {
65 handle:function(){
66 hub.$off('tom-event');
67 hub.$off('jerry-event');
68 }
69 },
70 })
五、组件插槽
    5.1 组件插槽的作用
      父组件向子组件传递内容
      <alert-box>hi</alert-box> -> <slot></slot>
 
    

    5.2 组件插槽的基本用法
      1.插槽的位置
        Vue.component('alert-box',{
          template:`
            <div class="demo-alert-box">
            <strong>Error!</strong>
            <slot></slot>
            </div>
              `
        })
      2.插槽的位置
        <alert-box>Something bad happened</alert-box>       
1 <div id="app">
2 <alert-box>啦啦啦</alert-box>
3 <alert-box></alert-box>
4 </div>

    

 1 Vue.component('alert-box',{
2 template:`
3 <div>
4 <strong>ERROR:</strong>
5 <slot>默认内容</slot>
6 </div>
7 `
8 })
9 var vm = new Vue({
10 el:'#app',
11 data:{
12
13 }
14 })
    5.3 具名插槽用法
      1.插槽定义
      <div class="container">
        <header>
          <slot name="header"></slot>
        </header>
 
        <main>
          <slot></slot>
        </main>
 
        <footer>
          <slot name="footer"></slot>
        </footer>
      </div>
      2.插槽内容
        <base-layout>
          <h1 slot="header">标题内容</h1>
          <p>主要内容1</p>
          <p>主要内容2</p>
          <p slot="footer">底部内容</p>
        </base-layout>
 
    5.4 作用域插槽
      应用场景:父组件对子组件内容进行加工处理
 
六、基于组件的案例 - 购物车
    6.1 按照组件化的方式实现业务需求
      根据业务功能进行组件化划分
        (1) 标题组件 展示文本
        (2) 列表组件 列表展示、商品数量变更、商品删除
        (3) 结算组件 计算商品总额
      实现整体布局和样式效果
        划分独立的功能组件
        组合所有的子组件形成整体结构
        逐个实现各个组件功能
        标题组件
        列表组件
        结算组件
      

4.Vue组件的更多相关文章

  1. vue组件

    分享出来让思路更成熟. 首先组件是 Vue.js 最强大的功能之一. 可以减少很多的工作量,提高工作效率. 编写一个可复用性的组件,虽然官网上也有.... 编写可复用性的vue组件 具备一下的几个要求 ...

  2. vue组件的配置属性

    vue组件的声明语法: Vue.component('component-name',{ template:'<p>段落{{prop1}} {{prop2}}</p>', da ...

  3. vue组件,撸第一个

    实现此例您可以学到: vue-cli的基本应用 父组件如何向子组件传递值 单文件组件如何引入scss v-on和v-for的基础应用 源码下载 一.搭建vue开发环境 更换镜像到cnpmnpm ins ...

  4. vue组件最佳实践

    看了老外的一篇关于组件开发的建议(强烈建议阅读英文原版),感觉不错翻译一下加深理解. 这篇文章制定一个统一的规则来开发你的vue程序,以至于达到一下目的. 1.让开发者和开发团队更容易发现一些事情. ...

  5. JS组件系列——又一款MVVM组件:Vue(二:构建自己的Vue组件)

    前言:转眼距离上篇 JS组件系列——又一款MVVM组件:Vue(一:30分钟搞定前端增删改查) 已有好几个月了,今天打算将它捡起来,发现好久不用,Vue相关技术点都生疏不少.经过这几个月的时间,Vue ...

  6. vue组件大集合 component

    vue组件分为全局组件.局部组件和父子组件,其中局部组件只能在el定义的范围内使用, 全局组件可以在随意地方使用,父子组件之间的传值问题等. Vue.extend 创建一个组件构造器 template ...

  7. 【Vue】详解Vue组件系统

    Vue渲染的两大基础方式 new 一个Vue的实例 这个我们一般会使用在挂载根节点这一初始化操作上: new Vue({ el: '#app' }) 注册组件并使用—— 全局注册 通过Vue.comp ...

  8. 关于vue组件的一个小结

    用vue进行开发到目前为止也有将近一年的时间了,在项目技术选型的时候隔壁组选 react的时候我们坚持使用vue作为前端的开发框架.虽然两者思想上的差异不大,但是vue的语法在代码的可读性以及后期的维 ...

  9. Vue组件基础用法

    前面的话 组件(Component)是Vue.js最强大的功能之一.组件可以扩展HTML元素,封装可重用的代码.根据项目需求,抽象出一些组件,每个组件里包含了展现.功能和样式.每个页面,根据自己所需, ...

  10. Vue组件模板形式实现对象数组数据循环为树形结构

    数据结构为数组中包含对象--树形结构,用Vue组件的写法实现以下的效果: 树形列表,缩进显示层级,第5级数据加底色,数据样式显色,点击展开折叠数据.本文为用Vue实现方式,另有一篇为用knockout ...

随机推荐

  1. Verilog仿真遇到的问题

    1.Vivado 15.4仿真时编译没有报错,但是仿真不成功,逻辑很简单,full为高电平时,rd_en要拉高,但全程没有拉高! 检查语法发现语句" else if( empty == 'b ...

  2. xd p4 WEB源码拓展

    WEB 源码在安全测试中是非常重要的信息来源,可以用来代码审计漏洞也可以用来做信息突破口,其中 WEB 源码有很多技术需要简明分析. 知识点 关于 WEB 源码目录结构 后台目录.模板目录.数据库目录 ...

  3. docker镜像原理(二)

    一.docker镜像定义 如果我们想要定义mysql5.7镜像应该怎么做? 获取基础镜像,选择一个发行版平台(unbtu.centos) 在centos镜像中安装mysql5.7软件 导出镜像,可以命 ...

  4. 栈和寄存器虚拟机比较(以python和lua为例)

    指令长度 python python的指令定长,长度为16bit,其中8bit操作码,8bit操作数. ///@file: Python-3.6.0\Include\code.h typedef ui ...

  5. HDLbits——Lfsr32

    //Build a 32-bit Galois LFSR with taps at bit positions 32, 22, 2, and 1. 草图 verilog描述 module top_mo ...

  6. lxml.etree.XMLSyntaxError: Opening and ending tag mismatch: meta line 4 and head, line 6, column 12 报错分析与解决方案

    报错分析: 我们检查代码没有任何问题,但报错显示:开始和结束标记不匹配. html:因为html是超文本标记语言,代码不规范也能解析. python:python是编程语言,代码不规范则解析不了. 解 ...

  7. chrome浏览器启用es6语法支持,初次体验浏览器端模块化加载

    医院项目,记录下,花了一个晚上的时间. 注意:最新版本的chrome浏览器已支持module语法,需要在web服务器环境下运行! 注:chrome76版本及以上不再需要设置了,浏览器已默认支持,至于从 ...

  8. conda出现Solving environment: failed错误

    conda在使用create新建环境和install安装时报错"Solving environment: failed" 报错截图  解决方案 1.在cmd中输入 %HOMEPAT ...

  9. Something Just Like This

    I've been reading books of old我遍读旧籍 The legends and the myths那些古老传奇和无边神秘 Achilles and his gold如阿喀琉斯和 ...

  10. Win10服务主机本地系统磁盘占用过高解决

    前言:发现电脑卡,磁盘被本地系统占用好多.把尝试过的方法都发一下. 1.尝试用了网上的关闭家庭组: win+R打开运行输入:services.msc  打开Windows服务管理器.找到HomeGro ...