zoukankan      html  css  js  c++  java
  • Vue.js 组件(四)

    1. 组件

    1.1 全局组件

    全局组件,全局任何 Vue 实例都可以使用,在 Vue 实例创建之前创建。

    1. 方式一

    <body>
        <div id="app">
            <!-- 使用 -->
            <mycom1></mycom1>
            <!-- <my-Com1></my-Com1> -->
        </div>
    
        <script src="./lib/vue-2.4.0.js"></script>
        <script>
            // Vue.extend 创建全局组件
            var com1 = Vue.extend({
                template: '<h3>全局组件</h3>'
            })
    
            // Vue.component('组件名称', 创建出来的组件模块对象)
            // 若组件名称使用驼峰名,那么使用组件名时中间必须有横线 -
            // Vue.component('myCom1', com1)
            Vue.component('mycom1', com1)
    
            var vm = new Vue({
                el: '#app',
                data: {},
                methods: {}
            })
        </script>
    </body>
    

    简写,省略为一步:

     Vue.component('mycom1', Vue.extend({
        template: '<h3>全局组件</h3>'
    }))
    

    2. 方式二

    • 可以省略 Vue.extend
    • 将组件模板直接定义在 template 元素中,然后定义 id 属性,最后在组件中取 id 属性即可
    <body>
        <div id="app">
            <mycom2></mycom2>
            <mycom3></mycom3>
        </div>
    
        <!-- template 必须 Vue 实例之外 -->
        <template id="com3">
            <h2>在 template 中定义模板</h2>
        </template>
    
        <script src="./lib/vue-2.4.0.js"></script>
        <script>
            Vue.component('mycom2', {
                template: '<h3>全局组件创建方式二</h3>'
            })
    
            Vue.component('mycom3', {
                template: '#com3'
            })
    
            var vm = new Vue({
                el: '#app',
                data: {},
                methods: {}
            })
        </script>
    </body>
    

    Tips:template 必须 Vue 实例之外,模板中有且只能有一个根元素,不能有多个根元素

    <!-- 不能存在多个根元素 -->
    <template id="com3">
        <h2>在 template 中定义模板</h2>
        <h3>哈哈</h3>
    </template>
    
    <!-- 只能有一个根元素 -->
    <template id="com3">
        <div>
            <h2>在 template 中定义模板</h2>
            <h3>哈哈</h3>
        </div>
    </template>
    

    1.2 局部组件

    局部组件,Vue 实例中定义的组件,仅能 Vue 实例使用。

    <body>
        <div id="app">
            <mycom4></mycom4>
        </div>
    
        <template id="com4">
            <h2>局部组件</h2>
        </template>
    
        <script src="./lib/vue-2.4.0.js"></script>
        <script>
            var vm = new Vue({
                el: '#app',
                data: {},
                methods: {},
                components: {
                    // 组件名称
                    mycom4: {
                        template: '#com4'
                    }
                }
            })
        </script>
    </body>
    

    1.3 组件 data 和 method

    • 组件 data 必须是一个方法
    • data 内部必须返回一个对象
    • 使用方式与实例中 data 一致
    • method:与实例中一样
    <body>
        <div id="app">
            <mycom4></mycom4>
        </div>
    
        <template id="com4">
            <div>
                <h2>局部组件:{{ msg }}</h2>
                <input type="button" value="按钮" @click="btn">
                <p v-if="flag">{{ msg }}</p>
            </div>
        </template>
    
        <script src="./lib/vue-2.4.0.js"></script>
        <script>
            // 组件 data 必须是一个方法
            // data 内部必须返回一个对象才行
            // 使用方式与实例中 data 一致
            Vue.component('mycom4', {
                template: '#com4',
                data: function () {
                    return {
                        msg: '组件 data',
                        flag: false
                    }
                },
                methods: {
                    btn() {
                        this.flag = true
                    }
                }
            })
    
            var vm = new Vue({
                el: '#app',
                data: {},
                methods: {},
            })
        </script>
    </body>
    

    1.4 组件切换

    在同一元素区域通过点击不同按钮,来显示不同元素,就可以使用组件切换来实现,比较常见的有:登陆注册

    • 点击登陆按钮,切换到登录框
    • 点击注册按钮,切换到注册框

    1.4.1 使用 flag 标识符结合 v-if 和 v-else 切换组件

    <body>
        <div id="app">
            <a href="" @click.prevent="flag=true">登陆</a>
            <a href="" @click.prevent="flag=false">注册</a>
    
            <login v-if="flag"></login> 
            <register v-else="flag"></register>
        </div>
    
        <script src="./lib/vue-2.4.0.js"></script>
        <script>
            // 登陆组件
            Vue.component('login', {
                template: '<h3>登陆组件</h3>'
            })
    
            // 注册组件
            Vue.component('register', {
                template: '<h3>注册组件</h3>'
            })
    
            var vm = new Vue({
                el: '#app',
                data: {
                    flag: false
                },
                methods: {},
            })
        </script>
    </body>
    

    缺点

    flag 标识符只有两种状态,truefalse,即最多只能切换两个组件

    1.4.2 使用 :is 属性来切换不同的子组件

    Vue 提供 :is 属性来解决组件之间的切换,它没有组件数量的限制。

    <body>
        <div id="app">
            <a href="" @click.prevent="comName='login'">登陆</a>
            <a href="" @click.prevent="comName='register'">注册</a>
    
            <!-- Vue提供了 component ,来展示对应名称的组件 -->
            <!-- component 是一个占位符, :is 属性,可以用来指定要展示的组件的名称 -->
            <component :is="comName">
    
            </component>
    
        </div>
    
        <script src="./lib/vue-2.4.0.js"></script>
        <script>
            // 登陆组件
            Vue.component('login', {
                template: '<h3>登陆组件</h3>'
            })
    
            // 注册组件
            Vue.component('register', {
                template: '<h3>注册组件</h3>'
            })
    
            var vm = new Vue({
                el: '#app',
                data: {
                    comName: 'login'     // 当前 component 中的 :is 绑定的组件的名称
                },
                methods: {},
            })
        </script>
    </body>
    

    默认 comNamelogin,即为登陆组件,等点击注册按钮时,comName 赋值为 register,即可切换到注册组件。

    1.4.3 组件切换动画

    1、使用 transition 元素包裹 componentmode 属性设置组件切换时候的模式:

    <div id="app">
        <a href="" @click.prevent="comName='login'">登陆</a>
        <a href="" @click.prevent="comName='register'">注册</a>
    
        <!-- 通过 mode 属性,设置组件切换时候的模式,先出后进,这样就不会有前一个组件还未消失,后一个组件就切换进入 -->
        <transition mode="out-in">
            <component :is="comName"></component>
        </transition>
    </div>
    

    2、设置切换样式:

     <style>
        .v-enter,
        .v-leave-to {
            opacity: 0;
            transform: translateX(150px);
        }
    
        .v-enter-active,
        .v-leave-active {
            transition: all 0.5s ease;
        }
    </style>
    

    参考文章:

    1.5 父子组件间传值

    1.5.1 父组件向子组件传值

    在子组件中不能直接使用父组件的 data 上的数据 和 methods 中的方法,需要通过 props 传递,两个步骤:

    1、使用 v-bind 或简化指令,将数据传递到子组件中:

    <div id="app">
        <!-- 给子组件绑定一个属性 parentmsg,值为 msg,即父组件的 data -->
        <com1 v-bind:parentmsg="msg"></com1>
    </div>
    

    2、使用 props 属性来定义父组件传递过来的数据:

    <script src="./lib/vue-2.4.0.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                msg: "父组件"
            },
            methods: {
    
            },
            components: {
                // data 上的数据,都是可读可写的;
                data() {
                    return {
                        title: 123
                    }
                }
                com1: {
                    template: '<h3>子组件 :{{ parentmsg }}</h3>',      // 在子组件中使用
                    props: ["parentmsg"]        // 在 porps 中定义该属性, props 中的数据,都是只读的,无法重新赋值
                },
            }
        })
    </script>
    

    1.5.2 父组件方法传递给子组件

    如何将父组件 method 传递给子组件:

    1、父组件将方法的引用(字符串形式),传递到子组件内部,子组件在内部调用父组件传递过来的方法,同时将要传递给父组件的数据,在调用方式时
    当做参数传递进去。

    <div id="app">
        <!-- 父组件向组组件传递 method,使用事件绑定机制 v-on,当自定义一个事件属性后,子组件中就能够通过某些方式 -->
        <!-- 来调用传递进来的这个方法 -->
        <com @func="show"></com>
    </div>
    
    <template id="tmp1">
        <div>
            <h1>子组件</h1>
            <input type="button" value="点击触发父组件传递过来的 func 方法" @click="myclick">
        </div>
    </template>
    

    2、子组件内部通过 this.$emit('方法名', 参数) 方法,来调用父组件中的方法,同时将数据传递给父组件:

    <script src="./lib/vue-2.4.0.js"></script>
    <script>
        // 定义一个字面量的全局子组件
        var com = {
            template: '#tmp1',      // 指定 ID,加载 template 元素中内容
            data() {
                return {
                    somMsg: { 'name': 'rose'}
                }
            },
            methods: {
                myclick() {
                    // 子组件中通过 this.emit('父组件事件属性', 参数一,参数二...),即可调用父组件中传递过来的方法
                    this.$emit('func', this.somMsg)
                }
            }
        }
    
        var vm = new Vue({
            el: '#app',
            data: {
                datamsgFromdson: null
            },
            methods: {
                show(data) {
                    console.log(data)
                    this.datamsgFromdson = data
                }
            },
            components: {
                com         // 注册子组件
            }
        })
    </script>
    

    1.5.3 评论列表示例

    练习:父子之间 datamethod 传递。

    1、html

    <div id="app">
        <com @func="add"></com>
    
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <ul class="list-group">
                    <li class="list-group-item" v-for="item in list" :key="item.id">
                        <span class="badge">评论人:{{ item.user }}</span>
                        {{ item.content }}
                    </li>
                </ul>
            </div>
        </div>
    </div>
    
    <!-- 子组件模板 -->
    <template id="tmp1">
        <div class="row" style="margin-top: 5%;">
            <div class="col-md-8 col-md-offset-2">
                <div class="form-group">
                    <label for="">评论人:</label>
                    <input type="text" class="form-control" v-model="user">
                </div>
    
                <div class="form-group">
                    <label for="">评论内容:</label>
                    <input type="text" class="form-control" v-model="content">
                </div>
    
                <div class="form-group">
                    <input type="button" class="btn btn-primary" value="发表评论" @click="postComment">
                </div>
            </div>
        </div>
    </template>
    

    2、js

    <script src="./lib/vue-2.4.0.js"></script>
    <script>
        var com = {
            template: '#tmp1',
            data() {
                return {
                    user: '',
                    content: '',
                }
            },
            methods: {
                // 发表评论
                postComment() {
                    // this.$emit('func', this.user, this.content)
                    // this.user = this.content = ''
    
                    // 存入 localStorage
                    // 1、组织一个评论数据对象
                    // 2、localStorage 仅支持字符串,JSON.stringify() 转换为字符串
                    // 3、保存最新的评论之前,从 localStorage 中获取之前的评论,转换为数组,再将最新的评论 unshift 到这个数组
                    // 4、若获取的评论为空,不存在,则返回一个 [],JSON.parse 转换不会报错
                    // 5、再将评论数组转换为字符串,setItem 存入到 localStorage 中
                    var comment = { id: new Date(), user: this.user, content: this.content }
                    
                    // 从 localStorage 中获取评论数组(取出时为字符串),并转换为数组
                    var list = JSON.parse(localStorage.getItem('cmts') || '[]')
                    list.unshift(comment)
    
                    // 重新保存
                    localStorage.setItem('cmts', JSON.stringify(list))
                    this.user = this.content = ''   // 清空输入框
    
                    // 调用父组件方法
                    this.$emit('func')
                }
            }
        }
    
        var vm = new Vue({
            el: '#app',
            data: {
                list: [
                    { id: Date.now(), user: '李白', content: '天生我材必有用' },
                    { id: Date.now(), user: '江小白', content: '劝君更尽一杯酒' },
                    { id: Date.now(), user: '小马', content: '我姓马, 风吹草低见牛羊的马' }
                ]
            },
            created() {
                this.add()
            },
            methods: {
                // add(name, comment) {
                //     this.list.unshift({ id: Date.now(), user: name, content: comment})
                // }
    
                add() {
                    // 从 localStorage 中取出评论数据
                    var list = JSON.parse(localStorage.getItem('cmts') || '[]')
                    this.list = list
    
                }
            },
            components: {
                com
            }
        })
    </script>
    

    将新评论存储到 localStorage 中,父组件 add 方法再从 localStorage 中获取所有评论列表,并将其渲染到页面中,
    created 生命周期函数中调用 add 方法,以保证刷新时最新评论不会消失。

    2.6 ref 获取 DOM 元素和组件

    使用 this.$refs 来获取元素对象和组件(数据、方法),this.$refs 获取的是 DOM 元素对象,因此可以通过其获取元素的文本、属性等。

    <div id="app">
        <input type="button" value="获取元素" @click="getElement">
        <h3 ref="myh3">标题三</h3>
    
        <com ref="son"></com>
    </div>
    
    <template id="tmp1">
        <h1>子组件,标题一</h1>
    </template>
    
    <script src="./lib/vue-2.4.0.js"></script>
    <script>
        var com = {
            template: '#tmp1',
            data() {
                return {
                    msg: "som msg"
                }
            },
            methods: {
                show() {
                    console.log('子组件方法')
                }
            }
        }
    
        var vm = new Vue({
            el: '#app',
            data: {},
            methods: {
                getElement() {
                    // 获取 h3 的文本值
                    // console.log(this.$refs.myh3.innerText)
                    
                    // 获取子组件的 data 数据
                    // console.log(this.$refs.son.msg)
    
                    // 执行子组件的 show 方法
                    this.$refs.son.show()
                }
            },
            components: {
                com
            }
        })
    </script>
    

    Tips:在浏览器中 F12 -- console 中,vm.$refs 可查看页面中的 refs 对象,refs 也可以用来替代父子组件直接传值

  • 相关阅读:
    HDU 4628 Pieces
    HDU 2983 Integer Transmission
    HDU 1820 Little Bishops
    CodeForces 165E Compatible Numbers
    CodeForces 11D A Simple Task
    HDU 4804 Campus Design
    HDU 3182 Hamburger Magi
    Linux的用户和组
    Linux文件/目录权限及归属
    Vim使用介绍
  • 原文地址:https://www.cnblogs.com/midworld/p/13611047.html
Copyright © 2011-2022 走看看