-
什么是组件化?
组件其实就是页面组成的一部分,好比是电脑中的每一个元件(如硬盘、键盘、鼠标),它是一个具有独立的逻辑和功能或界面,同时又能根据规定的接口规则进行相互融化,变成一个完整的应用。页面只不过是这样组件的容器,组件自由组合形成功能完整的界面,当不需要某个组件,或者想要替换某个组件时,可以随时进行替换和删除,而不影响整个应用的运行。
前端组件化的核心思想就是将一个巨大复杂的东西拆分成粒度合理的小东西。
-
组件的优缺点
组件更加清晰直观,组件关系更加清晰,结果可以预测
最小化了重绘(diff算法) 避免了不必要的dom操作
-
注册组件的过程
- Vue.extend():
- 调用Vue.extend()创建的是一个组件构造器
- 通常在创建组件构造器时,传入template代表自定义的组件模板
- 该模板就是要显式的HTML代码。
-
Vue.component():
调用Vue.component()将组件构造器注册成一个组件,并给它起一个组件的标签名称
需要传递两个参数:1.注册组件的标签名 2.组件构造器
-
组件必须挂载在Vue的实例下,否则不会生效
<html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> <my-cpn></my-cpn> <my-cpn></my-cpn> <my-cpn></my-cpn> </div> </body> <script src="../js/vue.js"></script> <script> // 1.创建组件构造器对象 const cpnC = Vue.extend({ template: ` <div> <h2>标题</h2> <p>内容111</p> </div>` }) // 2.注册组件 Vue.component('my-cpn', cpnC) //全局注册 ,全局组件可以在多个vue实例中使用 const app = new Vue({ el: "#app", data: { }, //局部组件, 只能在指定的vue实例中使用 components: { cpn: cpnC } }) </script> </html>
-
注册组件的语法糖
省略 Vue.extend() 直接使用对象代替
// 全局注册 Vue.component('cpn1', { template: ` <div> <h2>标题1</h2> <p>内容111</p> </div>` }) const app = new Vue({ el: "#app", data: { }, // 局部注册 components: { cpn2: { template: ` <div> <h2>标题2</h2> <p>内容222</p> </div>` } } })
-
模板分离的写法
- script标签写法
<!-- script标签,类型必须是text/x-template --> <script type="text/x-template" id="cpn"> <div> <h2>标题1</h2> <p>内容111</p> </div> </script> Vue.component('cpn', { template: '#cpn' })
- 通过template标签
<template id="cpn"> <div> <h2>标题2</h2> <p>内容222</p> </div> </template> Vue.component('cpn', { template: '#cpn' })
-
组件存放数据
组件对象也可以通过data属性存放数据,但data必须是一个函数,而且需要返回一个对象,对象内部存放数据。
<template id="cpn"> <div> <h2>{{title}}</h2> <h2>标题2</h2> <p>内容222</p> </div> </template> <script> Vue.component('cpn', { template: '#cpn', data() { return { title: 'abc' } } }) </script>
-
父子组件通信
子组件不能引用父组件或者Vue实例中的数据,但实际开发中需要将数据从父组件传递给子组件,或者子组件发送给父组件。比如: 服务器返回的数据有一部分是要给子组件展示的,这个时候就需要父传子了。
通过props向子组件传递数据
通过事件向父组件发送消息
- 父组件向子组件传递数据
//1.首先在父组件中注册子组件, //2.在子组件中通过props定义变量接收, //3.通过绑定属性的形式将值传递给子组件<cpn :cmovies="movies" :cmessage="message"></cpn> //4.子组件中就可以使用传递过来的值了。 <body> <div id="app"> <cpn :cmovies="movies" :cmessage="message"></cpn> </div> <template id="cpn"> <div> {{cmovies}} <h2>{{cmessage}}</h2> </div> </template> </body> <script src="../js/vue.js"></script> <script> // 父传子 props const cpn = { template: '#cpn', // props: ['cmovies', 'cmessage'] props: { cmessage: { // 类型限制 type: String, // 默认值 default: '我很好', required: true }, cmovies: { type: Array, default() { return ['aaa', 'bbb'] } } } } const app = new Vue({ el: "#app", data: { message: "你好啊", movies: ['海王', '海贼王', '海尔兄弟'] }, components: { cpn } }) </script>
- 子组件向父组件传递数据
//1.在子组件中通过$emit发射自定义事件 //2.在父组件中监听自定义事件 <!-- 子组件 --> <template id="cpn"> <div> <button v-for="item in categories" @click="btnClick(item)"> {{item.name}} </button> </div> </template> <!-- 父组件 --> <div id="app"> <cpn @item-click="cpnClick"></cpn> </div> <script> // 子组件 const cpn = { template: '#cpn', data() { return { categories: [ { id: 'aaa', name: '热门推荐' }, { id: 'bbb', name: '手机数码' }, { id: 'ccc', name: '家用电器' }, { id: 'ddd', name: '电脑办公' }, ] } }, methods: { btnClick(item) { // 子组件发射事件 this.$emit('item-click', item) } } } const app = new Vue({ el: "#app", methods: { cpnClick(item) { console.log('cpnClick', item) } }, components: { cpn } })
-
父子组件直接访问
-
父组件通过$children直接访问子组件
在父组件中通过$children获取的是一个vue组件数组,可以调用里面的方法
-
组件通过$refs直接访问子组件
默认返回的是一个空对象,需要在应用子组件的地方加上
ref="xxx"
<!-- 父组件 --> <div id="app"> <cpn></cpn> <cpn ref="aaa"></cpn> <button @click="btnClick">点击</button> </div> <!-- 子组件 --> <template id="cpn"> <div> 子组件 </div> </template> </body> <script src="../js/vue.js"></script> <script> const cpn = { template: '#cpn', data() { return { } }, methods: { showMessage() { console.log('showMessage111') }, } } const app = new Vue({ el: "#app", methods: { btnClick() { // console.log(this.$children); // this.$children[0].showMessage(); // refs 对象类型, console.log(this.$refs.aaa); } }, components: { cpn } }) </script>
-
网友评论