Vue.js组件

组件: 顾名思义, 也就是组成的部件, 即整体的组成部分
这个组成部分是可以缺少的,但是其存在的意义是无可替代的
这个组成部分也是可以复用的
全局方法一:
大致可以分成三步
1.在我们引入vue.js之后,Vue会被注册为一个全局对象,我们使用对象本身的方法进行组件的创建
------使用Vue这个全局对象的component方法进行全局注册一个组件

2.创建根实例,进行视图的绑定

3.组件的显示

-----将组价的名称作为标签写在视图内部,就能够完成组件的显示

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
        <!--引入js-->
        <script src="https://unpkg.com/vue/dist/vue.js"></script>
    </head>

    <body>
        <div id="app">
            <!--3. 定义的组件名作为标签存在,将组件显示在页面上-->
            <my-component></my-component>

        </div>
    </body>

</html>
<script>

    //1. 使用vue这个全局队形内置的components方法进行组件的创建
    //在components这个方法中有两个重要的参数,第一个参数是组件的名称,第二个参数是组件的内容
    Vue.component('my-component', {
        //在这里使用一个父标签将组件包裹起来
        template: '<div><a href="#">注册</a><a href="#">登录</a></div>'
    })

    //2. 创建根实例,也就是实例化一个vue对象,进行视图的绑定
    var vm = new Vue({
        el: '#app'
    })
</script>

全局方法二
使用全局的Vue.extend()构造器进行注册
Vue.extend()类似于继承,通过这个构造器扩展(继承)之后,相当于Vue对象本身添加了一些这个对象原先没有的东西

<!DOCTYPE html>
<html lang="en">

    <head>
        <meta charset="UTF-8">
        <title>Vue入门之extend全局方法</title>
        <script src="https://unpkg.com/vue/dist/vue.js"></script>

        <style type="text/css">

        </style>
    </head>

    <body>
        <div id="app"></div>
    </body>

</html>
<script>
    //通过构造器创建一个组件,相当于在vue这个全局对象本身上添加了一些新的内容,作用相当于构造函数
    //----继承自vue,但是比vue本身更强大
    var myVue = Vue.extend({
        template: '<div>这是通过构造器创建出来的组件</div>'
    });
    var app = new myVue({
        el: '#app'
    });
</script>

局部方法一
大致分成两个部分
1.穿件跟实例
2.在跟实例内部定义组件

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
        <!--引入js-->
        <script src="https://unpkg.com/vue/dist/vue.js"></script>
    </head>

    <body>
        <div id="app">
            <!--3. 这是我定义的组件    占位标签-->
            <my-component></my-component>

        </div>
    </body>

</html>
<script>
    //1. 创建根实例
    var vm = new Vue({
        el: '#app',
        //2. 在根实例内部创建组件
        components:{
           'my-component':{
               template: '<div><a href="#">注册</a><a href="#">登录</a></div>'
           }
        }
    })
</script>

组件注册的其它方式1

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
        <!--引入js-->
        <script src="https://unpkg.com/vue/dist/vue.js"></script>
    </head>

    <body>
        <div id="app">
            <!--这是我定义的组件-->
            <my-component></my-component>

        </div>

        <template id="my-template">
            <div>
                <a href="#">注册</a>
                <a href="#">登录</a>
            </div>
        </template>
    </body>

</html>
<!--

    注意组件的模板替换了自定义元素,自定义元素的作用只是作为一个挂载点。

    ----这可以用实例选项 replace 改变。


-->
<script>
    //1. --定义  +  注册 组件构造器
    Vue.component('my-component', {
        //将template的内容提取到一个标签中,通过id来获取
        template: '#my-template'
    })

    //2. 创建根实例
    var vm = new Vue({
        el: '#app'
    })
</script>

组件注册的其它方式2

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
        <!--引入js-->
        <script src="https://unpkg.com/vue/dist/vue.js"></script>
    </head>

    <body>
        <div id="app">
            <!--这是我定义的组件-->
            <template>
                <div>
                    <a href="#">注册</a>
                    <a href="#">登录</a>
                </div>
            </template>

        </div>

    </body>

</html>
<!--

自定义的标签只是自定义组件的一个挂载点,自定义组件会将其替换掉

----直接使用自定义的组件将自定义的标签替换

-->
<script>
    //2. 创建根实例
    var vm = new Vue({
        el: '#app'
    })
</script>

组件内部的data
组件内部的data属性必须是一个函数
以全局注册的组件为例

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
        <!--引入js-->
        <script src="https://unpkg.com/vue/dist/vue.js"></script>
    </head>

    <body>
        <div id="app">
            <!--全局的组件-->
            <ab></ab>
            <!--局部的组件-->
            <my-component></my-component>
        </div>
    </body>

</html>
<script>
    //自定义指令
    //Vue.directive('指令名',{})


    //定义组件    参数1:组件的名称    参数2: 对象
    Vue.component("ab",{
        template:
            `<ul>
                <li>{{name}}</li>
                <li>{{age}}</li>
                <li>{{sex}}</li>
            </ul>`,
        //data属性的属性值是一个函数----函数内部返回一个对象
        data:function(){
            return {
                name:"首页",
                age:"联系我们",
                sex:"新闻"
            }
        }

    })

    //2. 创建根实例-----并在根实例下面创建一个局部的组件
    var vm = new Vue({
        el: '#app',
        //局部组件
         components:{
           'my-component':{
               template: `<ul>
                <li>{{name}}</li>
                <li>{{age}}</li>
                <li>{{sex}}</li>
            </ul>`,
            data:function(){
                return {
                    name:1,
                    age:2,
                    sex:3
                }
            }
           }
        }
    })

</script>

父子组件通信
父组件将数据传递给自组件使用prop 子组件将其内部发生的事情通告给父组件使用emit
复杂的父子组件的props

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
        <!--引入js-->
        <script src="https://unpkg.com/vue/dist/vue.js"></script>
        <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
    </head>

    <body>
        <div id="app">
            <parent></parent>
        </div>
        <template id="parent">
            <div>
                <div>我是父组件</div>
                <child :message="message"></child>
            </div>
        </template>
        <template id="child">
            <div>
                <div>我是子组件</div>
                <span>{{message}}</span>
            </div>
        </template>
    </body>
</html>
<script>
    var vm = new Vue({
        el: '#app',
        //我是父组件
        components:{'parent':{
            template:"#parent",
            data:function(){
                return {
                    message:"hello world"
                }
            },
            //我是子组件
            components:{'child':{
                props:['message'],
                template:"#child"
            }}
        }}
    })
</script>

字面量语法 vs 动态语法
使用字面量语法传递数字,有时候会出现问题
单向数据流
数据从父组件传递到子组件,但是不会反过来传递
数据传递-注意事项
在 JavaScript 中对象和数组是引用类型,指向同一个内存空间,
如果 prop 是一个对象或数组,在子组件内部改变它会影响父组件的状态。
自定义事件

每个 Vue 实例都实现了事件接口(Events interface),即:

    使用 $on(eventName) 监听事件

    使用 $emit(eventName) 触发事件

类似于我们注册(vue中是$on)点击事件,通过鼠标点击触发(vue中是emit)
    document.onclick = function(event){
        console.log(111)
    }
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <script src="https://unpkg.com/vue/dist/vue.js"></script>
        <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
        <style>
            #dv1,
            #dv2 {
                width: 500px;
                height: 100px;
            }

            #dv1 {
                border: 1px solid red;
                margin: 50px auto;
            }

            #dv2 {
                border: 1px solid green;
                margin: 50px auto;
            }
        </style>
    </head>

    <body>

        <div id="app2">
            <component2></component2>
        </div>

        <div id="app1">
            <component1></component1>
        </div>
    </body>

</html>
<script type="text/javascript">
    //1. 创建一个空的公共的vue对象
    var bus = new Vue();

    //2. 在vm1实例中创建组件1,定义$emit来发送数据
    var vm1 = new Vue({
        el: '#app1',
        components: {
            component1: {
                template: `<div id="dv1"  v-on:click="add">
                                <div>点击我,触发自定义事件,进行数据的传递</div>
                                <div>当前的数据是:{{num}}</div>
                            </div>`,
                data: function() {
                    return {
                        num: 0
                    }
                },
                methods: {
                    add: function() {
                        this.num++;
                        bus.$emit('test', this.num)
                    }
                }
            }
        }
    })

    //在vm2实例中创建组件2,定义$on来接收传递的数据
    var vm2 = new Vue({
        el: '#app2',
        components: {
            component2: {
                template: `<div id="dv2" v-on:click="result">
                                <div>点击我,进行自定义事件的注册</div>
                                <div>传递过来的数据是{{getData}}</div>
                            </div>`,
                data: function() {
                    return {
                        getData: 0
                    }
                },
                methods: {
                    result: function() {
                        //this问题
                        var vm2This = this;
                        bus.$on('test', function(num) {
                            vm2This.getData = num;
                            //事件的解绑问题
                            bus.$off("test")
                        })

                    }
                }
            }
        }
    })
</script>

slot
有时候,我们需要对组件进行局部的修改,
vue提供了一种方式来混合父组件的内容与子组件自己的模板
这个过程被称为 内容分发 也就是slot

<!DOCTYPE html>
    <html lang="en">

    <head>
        <meta charset="UTF-8">
        <title>Vue入门之extend全局方法</title>
        <script src="https://unpkg.com/vue/dist/vue.js"></script>
    </head>

    <body>
        <div id="app">
            <!--父容器输入标签,会将slot标签替换掉-->
            <my-slot>
                <h3>这里是父容器写入的</h3>
            </my-slot>

            <!--父容器绑定数据到子容器的slot,会将slot中的数据替换掉-->
            <my-slot>{{ email }}</my-slot>

            <!--父容器什么都不传内容-->
            <my-slot></my-slot>
        </div>
    </body>

    </html>

    <script>
        // 反引号:可以定义多行字符串。
        var temp = `
      <div>
        <h1>这里是子组件</h1>
        <hr>
        <slot>slot标签会被父容器写的额外的内容替换掉,如果父容器没有写入任何东西,此标签将保留!</slot>
      </div>
    `;
        Vue.component('MySlot', { // 如果定义的组件为MySlot,那么用组件的时候:<my-slot></my-slot>
            template: temp,
        });
        // 初始化一个Vue实例
        var app = new Vue({
            el: '#app',
            data: {
                email: 'flydragon@gmail.com'
            }
        });
    </script>

具名slot
元素可以用一个特殊的属性 name 来配置如何分发内容。多个 slot 可以有不同的名字。
具名 slot 将匹配内容片段中有对应 slot 特性的元素
仍然可以有一个匿名 slot ,它是默认 slot ,作为找不到匹配的内容片段的备用插槽。如果没有默认的 slot ,这些找不到匹配的内容片段将被抛弃

动态组件
通过使用保留的 元素,动态地绑定到它的 is 特性,我们让多个组件可以使用同一个挂载点,并动态切换
如果把切换出去的组件保留在内存中,可以保留它的状态或避免重新渲染

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
        <!--引入js-->
        <script src="https://unpkg.com/vue/dist/vue.js"></script>
        <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
    </head>

    <body>
        <h3>动态组件</h3>
        <!-- 定义三个temp模板,用于切换 -->
        <template id="temp-tab01">
            <div>this is tab01</div>
        </template>
        <template id="temp-tab02">
            <div>this is tab02</div>
        </template>
        <template id="temp-tab03">
            <div>this is tab03</div>
        </template>

        <div id="dr01">
            <!-- 导航栏 -->
            <div class="border cf">
                <ul>
                    <li>
                        <a href="javascript:void(0);" @click="toggleTabs(tab01Text);">{{tab01Text}}</a>
                    </li>
                    <li>
                        <a href="javascript:void(0);" @click="toggleTabs(tab02Text);">{{tab02Text}}</a>
                    </li>
                    <li>
                        <a href="javascript:void(0);" @click="toggleTabs(tab03Text);">{{tab03Text}}</a>
                    </li>
                </ul>
            </div>
            <!-- 点击导航后要切换的内容 -->
            <div class="border" style="height: 100px;">
                <!-- 如果把切换出去的组件保留在内存中,可以保留它的状态或避免重新渲染。为此可以添加一个 keep-alive 指令参数 -->
                <component :is="currentView" keep-alive></component>
            </div>
        </div>
    </body>

</html>
<script>
//通过使用保留的 <component> 元素,动态地绑定到它的is属性,我们让多个组件可以使用同一个挂载点,并动态切换:
    //扩展组件tab01
    var tab01 = Vue.extend({
        template: "#temp-tab01",
    });
    //扩展组件tab02
    var tab02 = Vue.extend({
        template: "#temp-tab02",
    });
    //扩展组件tab03
    var tab03 = Vue.extend({
        template: "#temp-tab03",
    });
    //新建vue实例
    var dr01 = new Vue({
        el: "#dr01",
        data: {
            tab01Text: "tab01", //导航栏文本1
            tab02Text: "tab02", //导航栏文本2
            tab03Text: "tab03", //导航栏文本3
            currentView: 'tab01', //默认选中的导航栏
        },
        //局部注册组件
        components: {
            tab01: tab01,
            tab02: tab02,
            tab03: tab03,
        },
        methods: {
            //绑定tab的切换事件
            toggleTabs: function(tabText) {
                this.currentView = tabText;
            }
        }
    });
</script>
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,616评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,020评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,078评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,040评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,154评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,265评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,298评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,072评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,491评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,795评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,970评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,654评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,272评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,985评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,815评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,852评论 2 351

推荐阅读更多精彩内容

  • 本文章是我最近在公司的一场内部分享的内容。我有个习惯就是每次分享都会先将要分享的内容写成文章。所以这个文集也是用来...
    Awey阅读 9,437评论 4 67
  • 什么是组件 组件(Component)是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用...
    angelwgh阅读 781评论 0 0
  • 有一篇非常棒的关于vue.js的组件的文章,写的特别好,特别清楚,容易理解。链接:上篇:http://www.cn...
    恰皮阅读 1,774评论 0 8
  • 组件局部注册 is 属性挂载组件 常见:ul、select、table(字符串模板除外:.vue文件) 例:在ta...
    彤_姑娘阅读 446评论 0 0
  • 一、组件 组件,可以说是现代前端框架中必不可少的组成部分。使用组件,不仅能极大地提高代码的复用率和开发者的开发效率...
    ebfc7d0362e4阅读 1,039评论 2 6