vue核心 -- 组件篇

627 阅读4分钟

Vue组件

组件化:

  1. 如果我们实现一个页面结构和逻辑非常复杂的页面时,如果全部一起实现会变得非常复杂,而且也不利于后续的维护和迭代功能。
  2. 但如果我们这时候把页面分成一个个小的功能块,每个功能块能完成属于自己这部分独立的功能,那么整个页面之后的维护和迭代也会变得非常容易。

组件化思想

  1. 它提供了一种抽象,让我们可以开发出一个个独立可复用的小组件来构造我们的应用
  2. 任何的应用都会被抽象成一颗组件树。

1568877913978

组件化思想的应用开发:

  1. 有了组件化的思想,我们在之后的开发中就要充分的利用它。
  2. 尽可能的将页面拆分成一个个小的、可复用的组件。
  3. 这样让我们的代码更加方便组织和管理,并且扩展性也更强

1.创建组件

1.1、全局

通过Vue.component('组件名称', {}),通过这个方法注册的都是全局组件,也就是他们再注册之后可以用在任何新创建的Vue 实例挂载的区域内

使用组件时可以使用双标签或单标签

​ 两者的区别:

​ 双标签内可以放内容,而单标签不行 插槽的使用 牵扯到插槽的使用**)

 <div id="app">
      //使用组件
     <add-ul></add-ul>
     <add-ul />
 </div>

我们在实例化一个vue对象后创建一个最简单的全局组件

缺点:写死了(在模板抽离中解决)

new Vue({
	el:'#qpp',
	data:{}
})
//创建全局组件
Vue.component('组件名',{
	template:`<ul><li>我是最简单的组件</li></ul>`
})

1.2、局部

通过 `components:{} 方式注册的组件是局部组件,可以减少用户下载,避免造成不必要的资源浪费

html结构

<div id="app">
    <my-list></my-list>
</div>

js部分

new Vue({
    el: "#app",
    //创建局部组件
    components: {
        'my-list': {
            template: ` 
				<ul>
    				<li>
        				<span>
            				{{msg}}
            				<a href="http://baidu.com">
                				百度
            				</a>
        				</span>
    				</li>
				</ul>
					`
            } 	
        }
    }
})

2、模板抽离

在使用组件时模板抽离让它有更多可能性并且使臃肿的代码更加简洁

html结构

<div id="app">
    <my-list></my-list>
    <<my-list />
</div>

组件模板 -- 可以在任何位置书写

我们把模板抽离出来并且给他一个id

<template id="list">
    <ul>
        <li>
            <span>
                跳转
                <a href="http://baidu.com">
                    百度
                </a>
            </span>
        </li>
    </ul>
</template>

全局组件 使用

//全局组件
Vue.component('my-list', {
    //绑定使用
    template:'#list'
})
new Vue({
    el: "#app",
    data: { }
})

局部组件 使用

new Vue({
    el: "#app",
    //局部组件
    components: {
        'my-list': {
            //绑定使用
            template: "#list",
            data() { }
        }
    }
})

3、组件中如果使用实例数据

组件中无法使用实例data 组件中使用data必须是函数 多次调用一个组件,我们就需要对这个组件的数据进行维护,相当于我们希望给这个组件的数据套上一个作用域,防止被外部数据影响

完整代码

<div id="app">
    <add-ul></add-ul>
    <add-ul />
</div>
<template id="list">
    <ul>
        <li>
            <span>
                {{msg}}
                <a href="http://baidu.com">
                    百度
                </a>
            </span>
        </li>
    </ul>
</template>
Vue.component('add-ul', {
    template: '#list',
    // ES5里面只有函数有作用域
    data() {  // 组件中data必须是函数
        return {
            msg: '你好'
        }
    }
})

new Vue({
    el: "#app",
    data: {}
})

4、组件中的方法

在组件中使用方法/函数与实例化vue对象中使用相同

例如:

 Vue.component('add-ul', {
     template: '#list',
     data() { 
         return {
             msg: '你好'
         }
     },
     methods: {
         btnClick() {
             this.msg = 'hello'
             console.log(123);
         }
     }
 })

5、父子组件之间的通信

在组件中,使用选项props来声明需要从父级接收到的数据。

​ props的值有两种方式:

​ 1.字符串数组,数组中的字符串就是传递时的名称。

​ 2.对象,对象可以设置传递时的类型:

​ String,Number,Boolean,Array, Object Date,Function,Symbol,也可以设置默认值等

5.1、父传子

1.在传递的过程中我们先要把data数据绑定在使用组件的属性上 (属性名自定义)

2.在组件中用props方法接收数据(将自定义属性放入)

3.在组件中使用数据

 <div id="app">
        <my-list :cont="txt" :link="hrf"></my-list>
 </div>
<template id="list">
    <ul>
        <li>
            <span>
                <a :href="link">
                    {{cont}}
                </a>
            </span>
        </li>
    </ul>
</template>
    new Vue({
        el: "#app",
        data: {
            txt: '跳转到百度',
            hrf: 'http://baidu.com'
        },
        components: {
            'my-list': {
                template: "#list",
                // props 是以数组的简写方式
                props: ['cont', 'link'],
            }
        }
    })

5.2.1、props的完整写法

props: {
    //自定义属性名
    cont: {
        // 设置类型
        type: String,
        // 没有传值的默认值
        default: '跳转到新浪'
    },
    link: {
        type: String,
        default: 'http://sina.com.cn'
    }
}

5.2、子传父

vue中对数据的维护要求非常严格,你的原始数据再那个组件中,和必须再那个组件里修改 子组件中不能直接修改props,因为vue是单向数据流 通知父级修改 -- emit 发射 this.$emit(事件名称,传递的参数)

1.在组件中属性方法

2.使用this.$emit(事件名称,传递的参数)

3.在父级中属性方法接受参数

4.在使用组件标签中绑定事件

例如:

<div id="app">
    <my-list :cont="txt" :link="hrf" @changecontent="changecontent" v-on:changelink="changelink"></my-list>
</div>
<template id="list">
    <ul>
        <li>
            <span>
                <a :href="link">
                    {{cont}}
                </a>
            </span>
            <button @click="btnClick">切换</button>
        </li>
    </ul>
</template>
new Vue({
    el: "#app",
    data: {
        txt: '跳转到百度',
        hrf: 'http://baidu.com'
    },
    methods:{
        changecontent(val){
            this.txt=val
        },
        changelink(val){
            this.hrf=val
        }
    },
    components: {
        'my-list': {
            template: "#list",
            props: ['cont', 'link'],
            methods: {
                btnClick() {
                    // 这是错误的 - 在那个组件只能在那个组件修改 
                    // this.cont='新浪'
                    
                    // this.$emit(事件名称,传递的参数)
                    this.$emit('changecontent','跳转到新浪'),
                    this.$emit('changelink','http://sina.com.cn')
                }
            }
        }
    }
})

6、组件抽离

我们可以将组件抽离出来,以变量的形式存放,在实例化vue对象中使用组件中调用

<div id="app">
    <my-list :cont="txt" :link="hrf" @changecontent="changecontent" v-on:changelink="changelink"></my-list>
</div>
<template id="list">
    <ul>
        <li>
            <span>
                <a :href="link">
                    {{cont}}
                </a>
            </span>
            <button @click="btnClick">切换</button>
        </li>
    </ul>
</template>
let MyList = {
    template: "#list",
    // props 是以数组简写的方式
    props: ['cont', 'link'],
    methods: {
        btnClick() {
            this.$emit('changecontent', '跳转到新浪'),
                this.$emit('changelink', 'http://sina.com.cn')
        }
    }
}
new Vue({
    el: "#app",
    data: {
        txt: '跳转到百度',
        hrf: 'http://baidu.com'
    },
    methods: {
        changecontent(val) {
            this.txt = val
        },
        changelink(val) {
            this.hrf = val
        }
    },
    components: {
        // MyList : MyList
        //ES6特性
        MyList
    }
})

7、编译作用域

父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在子级作用域内编译。

也就是说父组件上的数据,只能在父组件上修改,不能传递到子组件里修改。