18910140161

vue系统摘要2

顺晟科技

2021-09-04 11:52:35

114

注册组件 组件其他补充 组件数据存放 父子组件通信 父级向子级传递信息 子级向父级传递信息 插槽slot

 

1.1什么是组件化 1.2 注册组件的基本步骤 创建组件构造器 注册组件 使用组件
<div id="app">
    <mycpn></mycpn>
</div>
<script src="../js/vue.js"></script>
<script>
    //1.创建组件构造器对象
    const cpn = Vue.extend({
        template: `
        <div>
            <h2>我是标题</h2>
            <p>我是内容,哈哈哈哈</p>
            <p>我是内容,呵呵呵呵呵呵</p>
        </div>`
    })

    Vue.component('mycpn',cpn)

    const app = new Vue({
        el: '#app',
        data: {

        }
    })
</script>
1.3全局组件和局部组件 当我们通过调用Vue.component()注册组件时,组件的注册是全局的 这意味着该组件可以在任意Vue实例下使用   如果我们注册的组件时挂载在某个实例中,那么就是局部组件  
<div id="app">
    <mycpn></mycpn>
    <cpn></cpn>
</div>
<script src="../js/vue.js"></script>
<script>
    //1.创建组件构造器
    const cpn = Vue.extend({
        template: `
        <div>
            <h2>我是标题1</h2>
            <p>我是内容 哈哈哈哈</p>
        </div>
        `
    })
    // 2.注册组件(全局组件,意味着可以再多个vue实例中使用)
    Vue.component('mycpn',cpn)

    const app = new Vue({
        el: '#app',
        data: {
            message: '你好啊'
        },
        components: {
            cpn:cpn
        }
    })
</script>
1.4父组件和子组件:
<div id="app">
    <cpn2></cpn2>
    <h2>--------</h2>
    <cpn1></cpn1>
</div>

<script src="../js/vue.js"></script>

<script>
    // 1.创建个组件构造器
    const cpn1 = Vue.extend({
        template: `<div>
        <h2>我是子组件标题</h2>
        <p>我是子组件内容 哈哈哈</p>
        </div>`
    })
    
    //2.创建第二个组件构造器
    const cpn2 = Vue.extend({
        template:`<div>
        <h2>我是父组件标题</h2>
        <p>我是父组件内容 呵呵呵呵呵</p>
        <cpn1></cpn1>
        </div>`,
        //在组件内部使用带s的components
        components:{
            cpn1: cpn1
        }
    })
    const app = new Vue({
        el:'#app',
        data:{
        },
        components:{
            cpn2: cpn2,
            cpn1: cpn1
        }
    })
</script>
1.5注册组件语法糖:
<div id="app">
<cpn></cpn>  
</div>
<script src="../js/vue.js"></script>
<script>

    //一.全局组件注册的语法糖
    //1.创造组件构造器
    // const cpn1 = Vue.extend()

    //2.注册组件
    // Vue.component('cpn',{
    //     template: `<div>
    //     <h2>我是全局组件标题</h2>
    //     <p>我是全局组件内容 呵呵呵呵呵</p>
    //     </div>`
    // })

    const app = new Vue({
        el: '#app',
        data: {
        },
        components:{
            cpn: {
                template: `<div>
                <h2>我是局部组件标题</h2>
                <p>我是局部组件内容 呵呵呵呵呵</p>
                </div>`
            }
        }
    })
</script>
1.6模板的分离写法:
<div id="app">
    <cpn></cpn>
    <cpn></cpn>
    <cpn></cpn>
</div>

<!-- 种模板 注意:必须是text/x-template类型-->
<!-- <script type="text/x-template" id="cpn">
    <div>
        <h2>我是标题</h2>
        <p>我是内容</p>
    </div>
</script> -->

<!-- 第二种模板:template -->
<template id="cpn">
    <div>
        <h2>这是标题哈哈</h2>
        <p>这是内容哈哈</p>
    </div>
</template>

<script src="../js/vue.js"></script>
<script>
    
    // 1.注册一个全局组件
    Vue.component('cpn',{
        template: '#cpn'
    })

    const app = new Vue({
        el: '#app',
        data: {
            message: '你好啊'
        }
    })
</script>
1.7组件数据的存放 组件自己的数据存放在哪里呢? 组件对象也有一个data属性(也可以有methods等属性,下面我们有用到) 只是这个data属性必须是一个函数 而且这个函数返回一个对象,对象内部保存着数据  
<div id="app">
    <cpn></cpn>
    <cpn></cpn>
    <cpn></cpn>
</div>

<!-- 种模板 注意:必须是text/x-template类型-->
<!-- <script type="text/x-template" id="cpn">
    <div>
        <h2>我是标题</h2>
        <p>我是内容</p>
    </div>
</script> -->

<!-- 第二种模板:template -->
<template id="cpn">
    <div>
        <h2>{{title}}</h2>
        <p>这是内容哈哈</p>
    </div>
</template>

<script src="../js/vue.js"></script>
<script>
    
    // 1.注册一个全局组件
    Vue.component('cpn',{
        template: '#cpn',
        data() {
            return {
                title: '测试文件'

            }
        }
    })

    const app = new Vue({
        el: '#app',
        data: {
            message: '你好啊'
        }
    })
</script>
1.8演示:为什么data是一个函数? 首先,如果不是一个函数,vue直接回报错 其次,原因在于Vue让每个组件对象都返回一个新的对象,因为如果是同一个对象的,组件在多次使用后相互影响  
<div id="app">
<cpn></cpn>
<cpn></cpn>
<cpn></cpn>
</div>
<template id="cpn">
    <div>
        <h2>当前计数是 : {{counter}}</h2>
        <button @click='innerment'>+</button>
        <button @click='denerment'>-</button>
    </div>
</template>
<script src="../js/vue.js"></script>
<script>

    Vue.component('cpn',{
        template: '#cpn',
        data () {
            return {
                counter: 0
            }
        },
        methods:{
            innerment(){
                this.counter++
            },
            denerment(){
                this.counter--
            },
        }
    })

    const app = new Vue({
        el: '#app',
        data: {
            message: '你好啊'
        }
    })
</script>
1.9.1父子组件的通信 一些数据需要从上层传递到下层 vue官方提到: 通过props向子组件传递数据 通过事件向父组件发送消息 props基本用法 在组件中,使用选项props来声明需要从父级接收到的数据 props的值有两种方式 方式一: 字符串数组,数组中的字符串就是传递时的名称 方式二: 对象,对象可以设置传递时的类型,也可以设置默认值等
<body>
<div id="app">
    <!-- 使用cpn子组件 动态绑定movies和message -->
    <cpn :cmovies="movies" :cmessage="message"></cpn>
</div>

<!-- 子组件模板 -->
<template id="cpn">
    <div>
        <ul>
            <!-- 循环cmovies的电影  -->
            <li v-for="item in cmovies">{{item}}</li>
        </ul>
        <h2>{{cmessage}}</h2>
    </div>
</template>
<!-- 引入vue文件 -->
<script src="../js/vue.js"></script>
<script>
    //实例化子组件
    const cpn = {
        //模板对象,和el挂载点相似,注意:template必须要有id为cpn的
        template: '#cpn',
        //子组件data必须是一个函数,每个组件调用的时候不能是同一个对象,
        //只能是一个函数,必须带有return返回值
        data(){
            return {}
        },
        methods:{},
        //父组件向子组件传递信息使用props方法
        props:{
            cmovies:{
                type:Array,
                default(){
                    return []
                },
                required: true
            },
            cmessage: {
                type:String,
                default: 'aaaa',
                required: true
            }
        }
    }

    //根组件,也可以算父组件,实例化vue对象
    const app = new Vue({
        //挂载点:#app
        el: '#app',
        //对象中数据现在不用函数
        data: {
            message: '测试文件',
            movies:['肖申克的救赎','当幸福来敲门','加勒比海盗','了不起的盖茨比']
        },
        //注册组件
        components:{
            cpn
        }
    })
</script>
除了数组之外,也可以使用对象,当需要对props进行类型验证时,就需要对象写法了 支持的类型: String(字符串) Number(数字) Boolean(布尔值) Array(数组) Object(对象) Date(时间) Function(函数) Symbol   1.9.2子级向父级传递 方式:自定义事件 流程: 在子组件中,通过$emit() 来出发事件 在父组件中,通过v-on来监听子组件事件  
<div id="app">
    <cpn @itembtn="cpnclick"></cpn>
</div>

<template id="cpn">
    <div>
        <button v-for="item in categories"
        @click="itemclick(item)">{{item.name}}</button>
    </div>
</template>

<script src="../js/vue.js"></script>
<script>
    const cpn = {
        template: '#cpn',
        data () {
            return {
                categories: [
                    {id: 'aaa',name: '打开应用'},
                    {id: 'bbb',name: '获取应用'},
                    {id: 'ccc',name: '新建应用'},
                    {id: 'ddd',name: '保存应用'},
                    {id: 'eee',name: '关闭应用'},
                ]
            }
        },
        methods: {
            itemclick (item) {
                console.log(item.id)
                this.$emit('itembtn',item)
            }
        }
    }

    const app = new Vue({
        el: '#app',
        data: {
            message: '你好啊'
        },
        components: {
            cpn
        },
        methods:{
            cpnclick (item) {
                console.log(item.id)
            }
        }
    })
</script>
2.0父子组件的访问方式: $children 有时候需要父组件直接访问子组件,子组件直接访问父组件,或者子组件访问根组件 父组件访问子组件: 使用$children或者$refs 子组件访问父组件: 使用$parent  
<div id="app">
    <cpn ref="ccc"></cpn>
    <cpn ref="bbb"></cpn>
    <cpn ref="aaa"></cpn>
    <button @click='btnClick'>测试按钮</button>
</div>

<template id="cpn">
    <div>
        <h2>我是子组件</h2>
    </div>
</template>

<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            message: '你好啊'
        },
        methods: {
            btnClick() {
                //1$children 用法比较少 是获取全部的自组件里面方法
                // console.log(this.$children)
                // // this.$children[0].showMessage()
                // for(let c of this.$children){
                //     c.showMessage()
                //     console.log(c.name)
                // }

                //2 $refs  用的最多  注意此处写的 是refs ,上面写的是ref=""
                //  $refs  => 对象类型 ,默认是一个空的对象 如果使用上面要用  ref="bbb"
                console.log(this.$refs.aaa.name)
                this.$refs.aaa.showMessage()
                console.log(this.$refs.bbb.name)
                this.$refs.bbb.showMessage()
                console.log(this.$refs.ccc.name)
                this.$refs.ccc.showMessage()

            }
        },
        components: {
            cpn: {
                template: '#cpn',
                data() {
                    return {
                        name: `中级的欲望 通过努力可以获得
                        低级的欲望 通过放纵可以获得`
                    }
                },
                methods: {
                    showMessage() {
                        console.log('的欲望 通过煎熬才能获得')
                    }
                }
            }
        }
    })
</script>
this.$children是一个数组类型,它包含了所有子组件对象 $children的缺陷 通过$children访问子组件时,是一个数组类型,访问其中的子组件必须通过索引值. 但是当子组件过多,我们需要拿到其中一个时,往往不能确定他的索引值,甚至还可能发生变化 有时候,我们想明确获取其中一个特定的组件,这个时候就可以使用$refs   $refs的使用: $refs和ref指令通常是一起使用的 首先,我们通过ref 给某一个子组件绑定一个特定的ID 其次,通过this.$refs.ID就可以访问到该组件了     2.1父子组件的访问方法: $parent 尽管在Vue开发中,我们允许通过$parent来访问父组件,但是在真实开发中尽量不要这样做 子组件应该尽量避免访问父组件的数据,因为这样耦合度太高了 如果我们将子组件放在另外一个组件之内,很可能该父组件没有对应的属性,往往会引起问题 另外,更不好做的是用过$parent直接改父组件的状态,那么父组件中的状态将变得不稳定  
<div id="app">
    <h2>这是vue实例</h2>
    <cpn></cpn>
</div>

<template id="cpn">
    <div>
        <h2>这是自组件</h2>
        <ccpn></ccpn>
    </div>
</template>

<template id="ccpn">
    <div>
        <h2>我是子组件内部组件</h2>
        <button @click="btnClick">点击按钮</button>
    </div>
</template>

<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            message: '你好啊'
        },
        components: {
            cpn: {
                template: '#cpn',
                data(){
                    return {
                        name: `
                        低级的欲望 通过放纵就可获得
                        的欲望 通过自律方可获得
                        的欲望 通过骄傲才可获得`
                    }
                },
                components: {
                    ccpn: {
                        template: '#ccpn',
                        methods: {
                            btnClick() {
                                //1种 $parent 只能访问父级组件的数据,但是耦合性很高,不能扩展
                                // console.log(this.$parent)
                                // console.log(this.$parent.name)

                                //2第二种,通过root 获取根组件的数据
                                console.log(this.$root)
                                console.log(this.$root.message)
                            }
                        }
                    }
                }
            }
        }
    })
</script>
2.2插槽slot 编译作用域: 父组件模板的所有东西都会在父级作用域内编译,子组件模板的所有东西都会在子级作用域内编译   插槽的作用:为了让我们封装的组件更加具有扩展性 如何使用slot: 在子组件中,使用特殊的元素<slot>就可以为子组件开启一个插槽 该插槽的插入什么内容取决于父组件如何使用
<div id="app">
    <cpn>
        <span>姓名</span>
        <input type="text" name='username' placeholder="请输入姓名">
    </cpn>
    <cpn>
        <span>密码</span>
        <input type="text" name="password" placeholder="请输入密码">
    </cpn>
    <cpn>
        <button>登录</button>
        <button>注册</button>
    </cpn>
</div>

<template id="cpn">
    <div>
        <!-- <h2>使用slot</h2>
        <button>slot</button> -->
        <slot>
            <button>初始按钮</button>
        </slot>
    </div>
</template>

<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            message: 'hell Vue.js'
        },
        components: {
            cpn: {
                template: '#cpn',
                data() {
                    return {}
                },
                methods:{}
            }
        }
    })
</script>
具名插槽slot 当子组件的功能复杂时,插槽并非一个 只要给slot元素一个name属性即可 <slot name="myslot"></slot>
<div id="app">
    <cpn>
        <button slot="left">返回</button>
    </cpn>
    <cpn>
        <span slot="left">姓名</span>
        <input type="text" slot="center" placeholder="请输入姓名">
    </cpn>
    <cpn>
        <span slot="left">密码</span>
        <input type="text" slot="center" placeholder="请输入密码">
    </cpn>
    <cpn>
        <button slot="left">登录</button>
        <button slot="right">注册</button>
    </cpn>
</div>

<template id="cpn">
    <div>
        <slot name="left"></slot>
        <slot name="center"></slot>
        <slot name="right"></slot>
        <slot name="noname"></slot>
    </div>
</template>

<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            message: 'hello Vue.js'
        },
        components:{
            cpn: {
                template: '#cpn',
                methods:{},
                data() {
                    return {}
                },
                props:{},
                computed:{}
            }
        }
    })
</script>
作用域插槽: 父组件替换插槽的标签,但是内容由子组件来提供  
<div id="app">
    <cpn v-show="isShow"></cpn>
</div>

<template id="cpn">
    <div>
        <h2>我是子组件</h2>
        <h3>你有为自己努力过吗</h3>
        <button v-show="isShow"></button>
    </div>
</template>

<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            message: 'hello Vue.js',
            isShow: true
        },
        components: {
            cpn: {
                template: '#cpn',
                props:{},
                methods:{},
                data () {
                    return {
                        isShow: false
                    }
                }
            }

        }
    })
</script>
插槽作用域的使用: 核心是在slot中加上属性: :data 然后在父组件中调用自组件数据: slot-scope="slot"  
<div id="app">
    <cpn></cpn>
    <cpn>
        <span slot="aaa">测试文件</span>
    </cpn>
    <cpn>
        <div slot="aaa" slot-scope="slot">
            <span v-for="item in slot.data">{{item}} -</span>
        </div>
    </cpn>
    <cpn>
        <div slot="aaa" slot-scope="slot">
            <span v-for="item in slot.data">{{item}} $</span>
        </div>
    </cpn>
    <cpn>
        <div slot="aaa" slot-scope='slot'>
            <!-- <span v-for="item in slot.data">{{item}}</span> -->
            <span>{{slot.data.join('--')}}</span>
        </div>
    </cpn>
</div>

<template id="cpn">
    <div>
        <slot name='aaa' :data="pLanges">
            <ul>
                <li v-for="item in pLanges">{{item}}</li>
            </ul>
        </slot>
    </div>
</template>

<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            message: 'hello Vue.js'
        },
        components:{
            cpn: {
                template: '#cpn',
                data() {
                    return {
                        pLanges: ['C++','python','java','js','php']
                    }
                }
            }
        }
    })
</script>

 

相关文章
我们已经准备好了,你呢?
2024我们与您携手共赢,为您的企业形象保驾护航