美文网首页
Vue 组件

Vue 组件

作者: 小李疯狂输出 | 来源:发表于2018-10-26 21:41 被阅读0次
Question :什么是组件化?

~~~~~~将想要的各种功能,丢进一个个的组件,就叫做组件化。
~~~~~~在vue中,每一个template组件,面只能有一个元素,该唯一元素,可以有子元素,且子元素没有上限。template模板在没有调用的情况下,不被识别。

一、组件用法

1.在html中或模板字符串中写好模板 (template script textarea)

  <template id="tem">
        <div>
            <p>i am first p</p>
            <p>i an sceond p</p>
        </div>
    </template>

2.调用Vue.extend()创建组件构造器,使template变成组件。
(已经在html中创建啦。)
在js中构造模板如下:
~~~~~~使用模板字符串,先创建,再注册。在注册中表明标识符和创建字符串的变量。

    let pro = Vue.extend({
        template:`
        <div>
            <p>我是一个p</p>
            <button >点我点我????</button>
        </div>
        `
    })
    /* 注册组件 */
    Vue.component("my-pro",pro);

3.调用Vue.component()注册组件,只有注册过的组件,才能被挂载元素调用。
~~~~~~my-pro类似组件的标识符,便于调用。

Vue.component("my-pro",{
        template:"#tem"//选中模板
})

4.挂载元素 div#app 直接调用。

<div id="app">
        <!-- 使用模板标识符,调用模板 -->
        <my-pro></my-pro>
  </div>
二、局部组件和全局组件。

~~~~~~全局组件,单独写在外部的组件,如上3中注册的组件my-pro为全局组件。
~~~~~~局部组件,写在实例Vue中的组件。
如下:

  • 模板写在挂载元素前面(针对script)。
  • 使用script创建的模板注意这是type = "text/x-template"。
<body>
    <!-- 使用template作为模板 -->
    <template id="tem">
        <p>我是#tem</p>
    </template>
    <!-- 使用script作为 -->
    <script type="text/x-template" id="rip" >
        <p>我是script模板</p>
   </script>

    <div id="box">
        <!-- 调用通过template创建的局部组件 -->
        <lly></lly>
        <!-- 调用通过script创建的局部组建 -->
        <srci></srci>
    </div>
</body>
<!-- 引入vue.js -->
<script src="vue.js"></script>
<script>
    new Vue({
        el:"#box",
        components:{
            "lly":{
                template:"#tem"
            },
            "srci":{
                template:"#rip"
            }
        }
    })
</script>
三、父子组件。

1.构造父子组件
~~~~~~父子组件存在依赖关系。
~~~~~~~~~~①:全局分别构造父子组件。
~~~~~~~~~~②:在父组件中注册子组件。
~~~~~~~~~~③:全局注册父组件。
~~~~~~综上构成依赖关系。

2.调用父子组件。
~~~~~~父子组件嵌套调用。
~~~~~~~~~~①:挂载中直接调用父组件。
~~~~~~~~~~②:父模板中任意位子调用组件。

<body>
    <!-- 挂载元素 -->
    <div id="app">
        <!-- 调用父组件 -->
        <tem-parent></tem-parent>
    </div>
    <!-- 子组件 -->
    <template id="tem-child">
        <p>我是儿子</p>
    </template>
    <!-- 父组件 -->
    <template id="tem-parent">
        <div>
            <p>我是爸爸</p>
            <!-- 父组件中调用子组件 -->
            <tem-child></tem-child>
        </div>
    </template>
</body>
<script src="./vue.js"></script>
<script>
    let child = Vue.extend({
        template:"#tem-child"
    })
    let parent = Vue.extend({
        template:"#tem-parent",
        /* 父组件中注册子组件 */
        components:{
           "tem-child":child
        }
    })
    /* 注册父组件 */
    Vue.component("tem-parent",parent);
    /* 实例化vue */
    new Vue({
        el:'#app'
    })
</script>

nice!

四、挂载数据

~~~~~~多次调用模板,会相互影像数据。要将返回数据作为对象全部return。
举个点赞栗子:

GIF.gif

代码如下:

<body>
    <!-- 先写个模板 -->
    <template id="tem">
        <div>
            <!-- 点击调用foo方法 -->
            <button @click = "foo()">点赞{{count}}</button>
        </div>
    </template>
    <!-- 再写个挂载div -->
    <div id="app">
        <div class="con">
            <tem></tem>
            <tem></tem>
            <tem></tem>
            <tem></tem>
            <tem></tem>
            <tem></tem>
        </div>
    </div>
</body>
<script src="./vue.js"></script>
<script>
    /* 注册组件 */
    Vue.component("tem",{
        template:"#tem",
        data(){
            return{
                /* 返回数据对象 */
                count:0
            }
        },
        methods:{
            foo(){
                this.count++;
            }
        }
    })
    new Vue({
        el: '#app'
    })
</script>
vue实现分页效果。上一页下一页~

效果图如下:


GIF.gif

复习一波鼠标点击的五中状态:

  • a:link 未访问时的状态(鼠标点击前显示的状态)
  • a:hover 鼠标悬停时的状态
  • a:visited 已访问过的状态(鼠标点击后的状态)
  • a:active 鼠标点击时的状态
  • a:focus 点击后鼠标移开保持鼠标点击时的状态(只有在<a href="#"></a>时标签中有效)
<style>
    .box{
        height: 45px;
        margin: 60px auto;
        padding: 5px 30px;
    }
    button{
        width: 90px;
        height: 100%;
        text-align: center;
    }
    span{
        display: inline-block;
        width: 50px;
        text-align: center;
        background-color: rgba(202, 152, 163, 0.2);
        margin: 5px;
    }
    .act{
        background-color: rgba(202, 152, 163, 0.6);
    }
    span:active{
        background-color: rgba(30, 152, 163, 0.6);
    }
</style>
<body>
    <template id="tem">
        <div class="box">
            <!-- 点上一张被选中的减减 -->
            <button v-show = "active != 1" @click = "active--">上一页</button>
            <!-- 动态生成span -->
            <span v-for = "index in pages" :class ="{act:active == index}"  @click = "goto(index)">{{index}}</span>
            <button v-show = "active != allpage" @click = "active++">下一页</button>
        </div>
    </template>
     <!-- Vue  挂载元素 -->
    <div id="app">
        <!-- 引入辣个模板 -->
        <tem></tem>
    </div>
</body>
<script src="./vue.js"></script>
<script>
    /* 注册辣个组件 */
    Vue.component("tem",{
        template:"#tem",
        data(){
            return{
                allpage:15,//总页
                opcpage:5,//显示页
                active:1 //当前显示页,默认为1
            }
        },
        computed:{
            pages(){
                let pag = []; //保存需要显示的页数。
                /* 当当前显示页<显示页数 */
                if(this.active < this.opcpage){
                    /* 取小 */
                    let i = Math.min(this.opcpage,this.allpage);
                    while(i){
                        pag.unshift(i--);
                    }
                }else{
                    //获取起始位子
                    let mid = this.active - Math.floor(this.opcpage / 2);
                    let i = this.opcpage;
                    if(mid > (this.allpage -this.opcpage)){
                        mid = (this.allpage - this.opcpage)+1;
                    }
                    while (i--) {
                        pag.push(mid++)
                    }
                }
                return pag;
            }
        },
        methods:{
            goto(cur){
                if(cur != this.active){
                    this.active = cur;
                }
            }
        }
    })
    /* 实例化辣个Vue */
    new Vue({
        el:"#app"
    })
</script>

emmm,这个思路每台明白,复制一波,很难受。

五、组件通信 props

props 可以是数组或对象,用于接收来自父组件的数据。在组件中使用变量,在父组件(挂载app中传递参数。)
1.传递变量

    <!-- 整个模板 -->
    <template id = "tem">
        <div>
            <h1>{{mse}}</h1>
            <p>{{msg}}</p>
        </div>
    </template>

    <!-- div -->
    <div id = "app">
        <!-- 调用模板,传参 -->
        <my-pro mse = "我是模板1" msg= "我是p"></my-pro>
    </div>
</body>
<script src="./vue.js"></script>
<script>
    Vue.component("my-pro",{
        /* 用于接受父组件的数据 */
        props:["mse","msg"],
        template:"#tem"
    })
    new Vue({
        el:"#app",
    })
</script>

2.传递属性
~~~~~~将props中值定义为属性,属性值通过实例Vue中的data传输,在模板中直接写属性值,通过调用者(挂载div#app)使用属性名传data值。

<body>
    <template id="tem">
        <div>
            <!-- 在模板中写属性 -->
            {{aa}}
        </div>
    </template>
    <div id="app">
        <!-- 调用时,通过属性传值 -->
        <my-pro :aa = "msg"></my-pro>
    </div>
</body>
<script src="./vue.js"></script>
<script>
    Vue.component("my-pro",{
        template:"#tem",
        props:["aa"] //定义属性aa 通过data传值
    })  
    new Vue({
        el:"#app",
        data:{
            msg:"我是莉莉娅"
        }
    })
</script>
六、子组件响应。

~~~~~~通过$.emit(“xxx”)中的xxx 作为该模板的属性,触发父组件的事件。

GIF.gif
    <template id="btn">
        <!-- 调用组件中的方法 -->
        <button @click = 'fn()'>点击了{{count}}次</button>
    </template>
    <div id="app">
        <!--xxx作为父组件属性监听父组件的方法 -->
        <my-btn @xxx = 'all()'></my-btn>
        <my-btn @xxx = 'all()'></my-btn>
        <my-btn @xxx = 'all()'></my-btn>
        <my-btn @xxx = 'all()'></my-btn>
        <my-btn @xxx = 'all()'></my-btn>
        <p>总共点击了{{soc}}下</p>
    </div>
</body>
<script src="./vue.js"></script>
<script>
    /* 注册组件 */
    Vue.component("my-btn",{
        template:'#btn',
        data(){
            return {
                count : 0
            }
        },
        methods:{
            fn(){
                this.count ++;
                //响应父组件的xxx事件,通过xxx事件调用父组件的all事件
                this.$emit('xxx');
            }
        }
    })
    new Vue({
        el:'#app',
        data:{
            soc:0
        },
        methods:{
            all(){
                this.soc ++;
            }
        }
    })
</script>
七、三层通信(可以说是每句话都写注释了!)

nice!
1.创建内层模板。
~~~~~在内层模板中直接调用该props中的属性名。
2.创建中间层模板
~~~~~中间层调用内层模板使用内层属性名 ,并将自身属性名赋值。
3.挂载元素作为最外层,即三层。
~~~~~外层调用中间层模板使用中间层属性名 ,将实例vue中data数据名赋值。

4.引入vue.js
5.构建内层模板。
6.注册中间层模板,并在内部注册内层模板。
7.实例vue。

<body>
    <!-- 三层通信,调用者作为最高层一层层传输数据。 -->
    <!-- 创建内层模板 -->
    <template id="in-set">
        <div>
            <!-- 内层直接调用属性名 -->
            {{tmin}}
        </div>
    </template>

    <!-- 创建中间层模板 -->
    <template id="mid">
        <div>
            <!-- 中间层调用内层模板使用内层属性名 并将自身属性名赋值-->
            <in-set :tmin="tmid"></in-set>
        </div>
    </template>

    <!-- 挂载元素作为最外层 -->
    <div id="out-set">
        <!-- 外层调用中间层模板使用中间层属性名 将实例vue中data数据名赋值 -->
        <mid :tmid = "msg"></mid>
    </div>
</body>
<!-- 引入vue -->
<script src="./vue.js"></script>
<script>
    /* 构建内层模板 */
    let tmin = Vue.extend({
        template:"#in-set",
        props:["tmin"]
    })
    /* 注册中间层模板,并且在内部注册内层模板 */
    /* 中间层模板,标识为mid */
    Vue.component("mid",{
        template:"#mid",
        props:["tmid"],
        components:{
            /* 注册内层模板,标识为in-set */
            "in-set":tmin
        }
    })
    new Vue({
        el:"#out-set",
        data:{
            msg:"我是一条数据。"
        }
    })
</script>
一个傻了吧唧的demo

数据渲染,和emm多次复用。


image.png
八、插槽 slot

①:匿名插槽、
定义:

<slot>自定义部分</slot>

调用:

<h1>自定义</h1>

~~~~在挂在元素中调用模,模板中的slot块可自定义内容。自定义内容湖识别slot标签并自定插入。
②:命名插槽
定义:

<slot name='s1'>自定义部分</slot>

调用:

<h1 slot='s1'>自定义</h1>

~~~~写好相应名字调用

相关文章

网友评论

      本文标题:Vue 组件

      本文链接:https://www.haomeiwen.com/subject/fdqktqtx.html