Vue(2)

一.组件

1.定义组件

Vue自定义组件分为两种:全局注册和局部注册,全局组件可以在任何地方引用,局部组件只能在当前Vue实例使用。
1)全局注册
使用Vue.component(tagName, options)来定义:
2)局部注册
在Vue实例中使用components属性来定义:
注意:HTML 特性是不区分大小写的,所有在定义组件时尽量使用中划线“-”来指定组件名。
即使,使用了驼峰标示命名如:myComponent,在页面引用时仍然要使用<my-component>进行引用。

<body>
<div id="app">
            <my-hello></my-hello>
        </div>
        
        <div id="root">
            <!--使用组件-->
            <my-hello></my-hello>
            <my-hello></my-hello>
            <my-hello></my-hello>
            <!--    <my-hello/>--> <!--不推荐使用-->
            <my-hello></my-hello>
            
            <inner-hello></inner-hello>
        </div>
        
        
    </body>
    
    <script type="text/javascript">
        
        /*定义全局组件*/
        Vue.component("my-hello",{
            template:"<h3>Hello Vue</h3>"
        });
        
        new Vue({
            el:"#app"
        });
        new Vue({
            el:"#root",
            components:{
                "inner-hello":{
                    template:"<h3>我是局部组件</h3>"
                }
            }
        });
        
    </script>

2.is属性

在table标签中直接使用自定义组件,无法正常显示。DOM解析时会解析到<table>标签的外部:
原因是:table/ol/ul/select 这种html标签有特殊的结构要求,不能直接使用自定义标签。他们有自己的默认嵌套规则,比如:
table> tr> [th, td];
ol/ul > li;
select > option

<body>
<table id="app">
            <tr is="my-hello"></tr>
        </table>
        
    </body>
    
    <script type="text/javascript">
        
        /*定义全局组件*/
        Vue.component("my-hello",{
            template:"<h3>Hello Vue</h3>"
        });
        
        new Vue({
            el:"#app"
        });
        
    </script>

3.模板

<body>
        <!--
            模板
                当模板的html结构比较复杂时,直接在template属性中定义就不现实了,效率也会很低,此时我们可以使用模板,定义模板的四种形式:
                1)直接使用字符串定义
                2)使用<script type="text/x-template">
                3)使用<template>标签
                4)使用.vue组件,需要使用模块加载机制
                在使用直接字符串模板时、x-template和.vue组件时,不需要is进行转义。
        -->
        
        <div id="app">
            <my-hello1></my-hello1>
            <my-hello2></my-hello2>
            <my-hello3></my-hello3>
            <my-hello4></my-hello4>
        </div>
        
        
        <!--2)使用<script type="text/x-template">-->
        <script type="text/x-template" id="tpl3">
            <ul>
                <li>01</li>
                <li>02</li>
            </ul>
        </script>
        
        <!--3)使用<template>标签-->
        <template id="tpl4">
            <ul>
                <li>011</li>
                <li>022</li>
            </ul>
        </template>
        
        
    </body>
    
    <script type="text/javascript">
        /*1)直接使用字符串定义*/
        var tpl = "<div><button>按钮</button><span>Hello</span></div>";
        var tpl2 = `
            <div>
            <button>按钮2</button>
            <span>Hello2</span>
            </div>
        `;
        console.log(tpl2);
        
        // 定义组件
        
        Vue.component("my-hello1",{
            template:tpl
        });
        
        Vue.component("my-hello2",{
            template:tpl2
        });
        
        Vue.component("my-hello3",{
            template:"#tpl3"
        });
        Vue.component("my-hello4",{
            template:"#tpl4"
        });
        
        
        new Vue({
            el:"#app"
        });
        
    </script>

4.data属性

通过data属性指定自定义组件的初始数据,要求data必须是一个函数,如果不是函数就会报错。

<body>
<div id="app">
            <!--使用组件-->
            <my-hello></my-hello>
            <my-hello></my-hello>
            <my-hello></my-hello>
        </div>
        
        
    </body>
    
    <script type="text/javascript">
        /*定义组件需要在实例化vue之前*/
        Vue.component("my-hello",{
            template:"<button @click='count++'>按钮{{count}}</button>",
            // 定义组件内部data: 必须通过函数定义
            data:function(){
                return {count:0};
            }
        });
        
        
        new Vue({
            el:"#app",
            data:{
                
            }
        });
        
    </script>

5.props

组件可以嵌套使用,叫做父子组件。那么父组件经常要给子组件传递数据这叫做父子组件通信。
父子组件的关系可以总结为 props 向下传递,事件向上传递。
父组件通过 props 给子组件下发数据,子组件通过事件给父组件发送消息。
1、在父组件中定义数据
2、在使用组件时,绑定父组件中的数据
3、在子组件中通过props属性声明父组件中传递过来的参数
4、在template属性中使用父组件中的参数

<body>
<div id="app">
            <!--使用组件-->
            <my-hello :txt1="msg" :txt2="txt"></my-hello>
        </div>
        
        
    </body>
    
    <script type="text/javascript">
        /*定义组件需要在实例化vue之前*/
        Vue.component("my-hello",{
            // 声明父组件传递过来的参数
            props:["txt1","txt2"],
            template:"<div>{{txt1}}:{{txt2}}</div>"
        });
        
        
        new Vue({
            el:"#app",
            data:{
                msg:"来自系统的消息",
                txt:"Hello Vue!"
            }
        });
        
    </script>

6.props校验

子组件在接收父组件传入数据时, 可以进行props校验,来确保数据的格式和是否必传。可以指定一下属性:
1) type: 指定数据类型 String Number Object ...注意不能使用字符串数组,只能是对象大写形式
2) required: 指定是否必输
3) default: 给默认值或者自定义函数返回默认值
4) validator: 自定义函数校验

非props属性
引用子组件时,非定义的props属性,自动合并到子组件上,class和style也会自动合并。

<body>
        <div id="app">
            <!--使用组件-->
            <my-hello class="item" style="font-size: 30px;color:pink;"  ></my-hello>
        </div>
        
        
    </body>
    
    <script type="text/javascript">
        /*定义组件需要在实例化vue之前*/
        Vue.component("my-hello",{
            template:"<span class='test' style='color:red'>Vue</span>"
        });
        
        
        new Vue({
            el:"#app"
            
        });
        
    </script>

7.自定义事件

父组件给子组件传值使用props属性, 那么需要子组件更新父组件时,要使用自定义事件$on和$emit:
$on监听: 不能监听驼峰标示的自定义事件, 使用全部小写(abc)或者-(a-b-c)
$emit主动触发: $emit(事件名,传入参数)
主动挂载
自定义事件不仅可以绑定在子组件,也可以直接挂载到父组件,使用$on绑定和$emit触发。

<body>
<div id="app">
            <my-hello v-on:update-count="changecount()"></my-hello>
            {{count}}
        </div>
        
        
    </body>
    
    <script type="text/javascript">
        
        Vue.component("my-hello",{
            template:"<button v-on:click='update'>子组件Child</button>",
            methods:{
                update:function(){
                    console.log("点击...");
                    this.$emit("update-count","自定义事件");
                }
            }
        });
        
        
        var app = new Vue({
            el:"#app",
            data:{
                count:0
            },
            methods:{
                changecount:function(){
                    this.count++;
                }
            }
        });
        // 主动挂载自定义事件
        app.$on("update-count",function(value){
            console.log(value);
            this.count++;
        });
        // 触发自定义事件
        app.$emit("update-count","这是自定义事件");
        
    </script>

二.插槽分发

1.slot插槽

<body>
        <!--
            
            
        -->
        
        <div id="app">
            <my-hello></my-hello>
            <my-hello>
                <h3>你好</h3>
                <p>这是p元素</p>
            </my-hello>
        </div>
        
        <!--使用template标签-->
        <template id="tpl1">
            <div>
                <h4>Hello Vue</h4>    
                <!--插槽,占位-->
                <slot>如果没有传递数据,默认显示这段文本</slot>
            </div>
        </template>
        
    </body>
    
    <script type="text/javascript">
        
        // 自定义组件
        Vue.component("my-hello",{
            template:"#tpl1",
        });
        
        
        var app = new Vue({
            el:"#app"
            
        });
        
    </script>

2.具名插槽

具名插槽slot, 就是给插槽起个名字。
在子组件定时可以定定义多个<slot>插槽,同时通过name属性指定一个名字,如:<slot name='header'>,父组件引用时使用< slot='header'>进行插槽选择。

<body>
<div id="app">
            <!--<my-hello></my-hello>-->
            <my-hello>
                <h3 slot="header">你好</h3>
                <p slot="footer">这是p元素</p>
            </my-hello>
        </div>
        
        <!--使用template标签-->
        <template id="tpl1">
            <div>
                <slot name="header">如果没有传递数据,默认显示这段文本</slot>
                <div>--------------------</div>
                <!--插槽,占位-->
                <slot name="footer">如果没有传递数据,默认显示这段文本</slot>
            </div>
        </template>
        
    </body>
    
    <script type="text/javascript">
        
        // 自定义组件
        Vue.component("my-hello",{
            template:"#tpl1",
        });
        
        
        var app = new Vue({
            el:"#app"
            
        });
        
    </script>

3.插槽作用域

作用域插槽slot-scope,
父组件通过<slot>插槽混入父组件的内容, 子组件也可以通过slot作用域向插槽slot内部传入数据,使用方式:<slot text='子组件数据'>,
父组件通过<template slot-scope="props">进行引用。

<body>
<div id="app">
            <!--<my-hello></my-hello>-->
            <my-hello>
                <template slot-scope="props">
                    <h3>你好----{{props.msg}}----{{props.txt}}</h3>
                </template>
            </my-hello>
        </div>
        
        <!--使用template标签-->
        <template id="tpl1">
            <div>
                <div>--------------------</div>
                <!--插槽,占位-->
                <slot msg="你好啊" txt="Hello">如果没有传递数据,默认显示这段文本</slot>
            </div>
        </template>
        
    </body>
    
    <script type="text/javascript">
        
        // 自定义组件
        Vue.component("my-hello",{
            template:"#tpl1",
        });
        
        
        var app = new Vue({
            el:"#app"
            
        });
        
    </script>

猜你喜欢

转载自www.cnblogs.com/xiaokeji/p/10776723.html