• Vue 组件基础


    官方教程: https://cn.vuejs.org/v2/guide

    声明组件

    let myComponent = Vue.extend({
        template : '#my',
        // 此时的 #my 是id="my"的template标签
    });
    
    // 可以简化为
    let myComponent = {
        template : '#my',
        data(){
            // 此处的data必须是一个函数
        }
    };
    

    注册组件(全局组件, 局部组件)

    // 全局组件: 一次注册在所有的vue实例中(都能够使用
    Vue.component('my-component',{
        template : '#my-component',
        data () {
            // 此处的data必须是一个函数    
        },
    });
    
    // 局部组件: 只能在某一个vue实例中使用
    const vm = new Vue({
        'el' : '#app',
        components : {
            'my-component' : {
                template : '#my',
                data() { 
                    // 此处的data必须是一个函数
                }
            },
        }
    });
    

    注: 为了保证各个组件的相互独立性,所有的组件中的data必须是一个函数

    组件之间的通信

    • 父组件 => 子组件: props
    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>vue study</title>
        <script src="../node_modules/vue/dist/vue.js"></script>
    </head>
    <body>
    <!-- templates -->
    <template id="my">
        <div>
            <p>这是本组件自己的数据: {{selfData}}</p>
            <p>这是父组件的数据: {{msg}}</p>
        </div>
    </template>
    <!-- /templates -->
    
    
    <!-- 使用组件 -->
    <div id="app">
        <my-component :msg="message"></my-component>
    </div>
    
    
    <script>
        // 1.声明一个组件
        let myComponent = Vue.extend({
            template: '#my',
            props: ["msg"],
            // props 不仅仅可以是一个数组,也可以是一个对象
            data() {
                return {
                    selfData: "hello Vue",
                };
            },
        });
        
        
    /** props 支持的类型=========================
     1. 简单语法
      Vue.component('props-demo-simple', {
        props: ['size', 'myMessage']
      })
      2. 对象语法,提供校验
      Vue.component('props-demo-advanced', {
        props: {
          // 检测类型
          height: Number,
          // 检测类型 + 其他验证
          age: {
            type: Number,
            default: 0,
            required: true,
            validator: function (value) {
              return value >= 0
            }
          }
        }
      });
    ==================================*/
    
        // 2.在Vue实例中来注册组件
        const vm = new Vue({
            el: '#app',
            data: {
                message: 'hello world',
            },
            components: {
                // 注册一个局部组件
                'my-component': myComponent,
                // 注: 此时必须使用 - 分割单词,或者全部小写,不能使用驼峰式写法
            }
        });
    </script>
    <!--
        父组件 => 子组件: 在子组件中使用父组件的数据
        1. 声明一个组件
        2. 注册组件(全局或者局部组件都可以通信)
        3. 使用组件(my-component), 并在使用时绑定一个属性 :msg
        4. 在子组件中用 props 来获取绑定的属性   props : ["msg"],
        5. 测试,看是否能够成功传递值
    -->
    </body>
    </html>
    
    • 子组件 => 父组件: 发布订阅
    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>vue study</title>
        <script src="./node_modules/vue/dist/vue.js"></script>
    </head>
    <body>
    <div id="app">
        <!-- 使用组件 -->
        <my-component :msg="message" @custom_event="changeData"></my-component>
    </div>
    
    <!-- templates -->
    <template id="my">
        <div>
            <p>{{msg}}</p>
            <p>{{selfData}}</p>
            <!-- <button @click="$emit('custom_enevt','args')">点我改变父组件的数据</button> -->
            <!-- 如果觉得这种行内的触发满足不了复杂的逻辑需求,你也可以把这个触发写到这个组件的方法中 -->
             <button @click="triggerParent(10)">点我改变父组件的数据</button>
        </div>
    </template>
    
    <script>
        // 声明一个组件
        let myComponent = Vue.extend({
            template: '#my',
            props: ["msg"],
            data() {
                return {
                    selfData: 'hello Vue',
                };
            },
            methods : {
                triggerParent(val){
                    // 触发父组件并传递一个参数,此时的val是click调用时传递的参数
                    this.$emit('custom_event', val);
                },
            },
        });
    
        const vm = new Vue({
            el: '#app',
            data: {
                message: 'hello world',
            },
            methods: {
                changeData (val) {
                    // 把message变成一个随机数连接上子组件传递的参数
                    this.message = val + Math.ceil(Math.random()*100);
                },
            },
            components: {
                // 注册一个局部组件
                'my-component': myComponent,
            }
        });
    </script>
    <!--
    由于vue为了保证各个组件的独立性,所以将各个组件的数据流向做成那单向数据流,
    而这样,就只能父组件改变子组件的内容,而不能子组件改变父组件的内容
    所以为了能够在子组件中改变父组件的数据,只有使用自定义事件系统
    
    1. 声明一个组件  let myComponent = Vue.extend({...});
    2. 注册一个组件(全局,局部都行)
    3. 使用组件
        3.1) 绑定一个属性     :msg="message"  子组件可以用 props 来获取绑定的属性
        3.2) 绑定一个自定义事件 @custom_event="changeData" 此时的custom_event是事件名称,changeData是methods中的方法
        3.3) 子类想改变父类的数据,可以用$emit('事件名称')来触发父组件的事件,然后由父组件决定改变的规则,从而达到单向数据流的目的
        3.4) 触发父类自定义事件
            3.4.1) 行内触发
                <button @click="$emit('custom_enevt','args')">点我改变父组件的数据</button> 此时的args是参数
            3.4.2) 使用方法触发
                <button @click="triggerParent(10)">点我改变父组件的数据</button>
                methods : {
                     triggerParent(val){
                         // 触发父组件并传递一个参数,此时的val是click调用时传递的参数
                         this.$emit('custom_event', val);
                      },
                }
    -->
    </body>
    </html>
    
    • 组件嵌套的情况
    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>vue组件嵌套</title>
        <script src="./node_modules/vue/dist/vue.js"></script>
        <style>
            .cmpt1, .cmpt2 {
                color: #ffffff;
                padding: 15px;
            }
    
            .cmpt1 {
                background: #272822;
            }
    
            .cmpt2 {
                background: #265a88;
            }
        </style>
    </head>
    <body>
    <div id="app">
        <my-component @custom_event="changeData" :msg="message"></my-component>
    </div>
    
    <!-- templates -->
    <template id="my">
        <div>
            <one :msg="msg" :name="name"></one>
            <two :msg="msg" @test_event="changeMess"></two>
        </div>
    </template>
    
    <!--one-->
    <template id="one">
        <div class="cmpt1">
            <p>这是组件1</p>
            <p>这是二级传递: hello {{msg}}!!! </p>
            <p>这是三级传递: what's your name? my name is {{name}}</p>
        </div>
    </template>
    
    <!--two-->
    <template id="two">
        <div class="cmpt2">
            <p>这是组件2</p>
            <p> hello {{msg}} </p>
            <p>
                <button @click="changePrentData(10)">点我改变父组件数据</button>
            </p>
        </div>
    </template>
    
    
    <script>
        // 声明一个子组件
        let one = Vue.extend({
            template: '#one',
            props: ["msg", "name"],
        });
    
        // 声明一个子组件
        let two = Vue.extend({
            template: '#two',
            props: ["msg"],
            methods: {
                changePrentData(val) {
                    let m = Math.ceil(Math.random() * val);
                    // this.$emit('custom_event', m);
                    this.$emit('test_event', m);
                }
            },
        });
    
        // 声明一个父组件
        let myComponent = Vue.extend({
            template: '#my',
            props: ["msg"],
            methods: {
                changeMess(val){
                    this.$emit('custom_event',val);
                }
            },
            components: {
                'one': one,
                'two': two
            },
            data() {
                return {
                    name: 'Tom',
                };
            }
        });
    
        const vm = new Vue({
            el: '#app',
            data: {
                message: 'world',
            },
            methods: {
                changeData(val) {
                    this.message = "这是改变后的message,喜欢吗? " + val + " 是点击是传递的参数";
                }
            },
            components: {
                // 注册一个局部组件
                'my-component': myComponent,
            }
        });
    </script>
    <!--
        组件嵌套时,最底层的组件想要与最顶层的组件通信,必须一层一层向上传递
    -->
    </body>
    </html>
    
    • 实例 模态框
    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>蒙版效果</title>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
    
            html, body {
                 100%;
                height: 3000px;
                /* 为了测试滚动 */
            }
    
            #alert-panel {
                 100%;
                height: 100%;
                background: rgba(0, 0, 0, 0.5);
                position: absolute;
                top: 0;
                left: 0;
                /*display: none;*/
            }
    
            #alert-panel #login {
                 500px;
                height: 300px;
                background: #000000;
                position: fixed;
                top: 50%;
                left: 50%;
                margin-left: -250px;
                margin-top: -180px;
            }
    
            #close-alert-panel {
                background: #000;
                color: #ffffff;
                border: none;
                 30px;
                height: 30px;
                float: right;
            }
    
            #close-alert-panel:hover {
                background: #f00;
            }
        </style>
    
        <!--javascript-->
        <script src="./node_modules/vue/dist/vue.js"></script>
    </head>
    <body>
    
    <div id="app">
        <!-- 当点击button的时候,显示模态框,在模态框中点击关闭按钮时,关闭模态框 -->
        <button id="btn" @click="showDialog">点击登陆</button>
    
        <modal :is-hide-dialog="!isHide" @close="closeModal"></modal>
    </div>
    
    <template id="dialog">
        <div id="alert-panel" v-show="isHideDialog">
            <div id="login">
                <button id="close-alert-panel" @click="$emit('close')">&times;</button>
            </div>
        </div>
    </template>
    
    <script>
        // 声明一个组件
        let modal = Vue.extend({
            template: '#dialog',
            props: ["isHideDialog"],
        });
    
        const vm = new Vue({
            el: '#app',
            data: {
                isHide: true,
            },
            methods: {
                showDialog() {
                    this.isHide = false;
                },
                closeModal() {
                    this.isHide = true;
                }
            },
            components: {
                'modal': modal
            }
        });
    </script>
    </body>
    </html>
    
    • 父组件调用子组件的方法

    注: 如果ref放在组件上,那么通过$refs拿到的不是组件的dom而是这个组件

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>vue study</title>
        <script src="./node_modules/vue/dist/vue.js"></script>
    </head>
    <body>
    
    <div id="app">
        <!-- 注: 如果ref放在组件上,那么通过$refs拿到的不是组件的dom而是这个组件 -->
        <load ref="load"></load>
    </div>
    
    <!--templates-->
    <template id="load">
        <div v-if="isShow">
            <p>玩命加载中...</p>
        </div>
    </template>
    
    <!-- JavaScript -->
    <script>
        let load = Vue.extend({
            template: '#load',
            data () {
                return {
                    isShow: true,
                }
            },
            methods: {
                hide(){
                    this.isShow = false;
                    console.log("我被调用了,这个组件已经被隐藏了");
                }
            },
        });
    
        const vm = new Vue({
            el: '#app',
            components: {
                "load": load,
            },
            mounted () {
                // 当vm实例挂载的时候,就调用子组件的方法,隐藏加载组件
                this.$refs.load.hide();
            }
        });
    
    </script>
    </body>
    </html>
    
    
    • 在子组件中加工父组件传递的值

    默认在子组件中不能修改父组件传递的值,如果非要
    加工父组件传递过来的数据,可以使用 computed 属性或者 data()
    来加工父组件传递的值,此种方式虽然能够加工了父组件
    传递的数据,但是不会改变父组件的数据,保证了各个组件的独立性(单向数据流)

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>vue study</title>
        <script src="./node_modules/vue/dist/vue.js"></script>
    </head>
    <body>
    
    
    <div id="app">
        <my-comp :name="message"></my-comp>
    </div>
    
    <!--templates-->
    <template id="my">
        <div>
            <p>父组件原数据: {{name}}</p>
            <p>改变后的数据: {{myName}}</p>
            <p>改变后的数据: {{myName2}}</p>
        </div>
    </template>
    
    <!-- JavaScript -->
    <script>
        // make a component
        let myComponent = Vue.extend({
            template: '#my',
            props: ["name"],
            // 要求: 在子组件中,将父组件传递的值拼接一个随机数
            // 方式一:使用计算属性来改变父组件传递的值
            computed:{
                myName(){
                    return this.name + Math.random();
                }
            },
            // 方式二:使用data()方法来改变父组件传递的值(局部变量)
            data(){
                return {
                    "myName2" :this.name + Math.random(),
                }
            },
        });
    
        const vm = new Vue({
            el: '#app',
            data: {
                message: 'hello world',
            },
            components: {
                // register a local component
                "my-comp": myComponent,
            },
        });
    
    </script>
    </body>
    </html>
    
    
  • 相关阅读:
    qunar面试题及一位大牛的解答
    深入理解js里面的this
    用js实现的一个可拖动标签的例子
    Linux启动详细过程(开机启动顺序)
    linux下用top命令查看cpu利用率超过100%
    linux内核内存管理(zone_dma zone_normal zone_highmem)
    用户线程与内核线程如何映射?
    Linux用户空间与内核地址空间
    linux超级块和inode 详解 和 df 、du 命令详解与环境变量
    内核空间、进程和线程等概念
  • 原文地址:https://www.cnblogs.com/liaohui5/p/10581653.html
Copyright © 2020-2023  润新知