1、Vue的组件
-
Vue有两大核心的内容:指令和组件
-
什么是组件化?为什么要用组件?
- 为了避免多人开发造成的冲突
- 为了加快开发效率
- 为了便利更新和维护
- 组件化: 就是使用具有独立公共的一个整体【 组件 】来进行项目开发的一个趋势 【 流行 】
-
什么是组件?
- 组件是一个html css js img 等的一个聚合体
- 在Vue中使用了一个叫做单文件组件的技术来实现组件
- 它是一个 xxx.vue 文件
- 这个文件在浏览器不能运行,必须经过编译【 gulp webpack 】才能运行
-
Vue里面如何实现组件的?
-
通过Vue.extend()
/* 1. 通过实例化Vue构造器函数得到一个Vue实例,这个实例我们称之为'根实例',它是最大的父级 2. 这个根实例是以标签的形式存在的,那么我们也称之为' 根组件 ' 3. 根实例也是一个组件,但是我们得到只是根组件 4. Vue.extend() 它就是对Vue功能的扩展,这个扩展就是组件 5. Vue是通过 Vue.extend() 来实现【 扩展 】 Vue的功能的,这个功能就是组件 6. 思考: Vue.extend如何使用? - 通过new Vue.extend() 发现和new Vue一样了 排除了 - 组件就是一个以标签化呈现的东西,所以我应该像标签一样使用 - 但是无论是 html3 还是 html5 肯定不会同意它随意来个标签的 - Vue会将组件编译成html结构 - Vue的这个处理过程,称之为 ' 组件注册 ' 总结: 1. Vue是通过Vue.extend() 来实现组件的 2. Vue的组件的使用时需要注册的 */ console.log( Vue ) console.log( Vue.extend()) new Vue({ el: '#app' })
-
-
Vue中如何使用组件的
-
组件的起名规则
- 1、大驼峰 例:HeadTitle 使用时:
- 2、小写横杠 例:head-title 使用时:
- 3、一个单词 例: Hello 使用时: 或者 【推荐使用,便于与原生标签进行区分】
-
组件注册
-
全局注册
实例化:
/* 全局注册 格式: Vue.component() */ //1、详细实现 // const Hello = Vue.extend( options ) //此处的options与new Vue中的options相同 const Hello = Vue.extend({ template: '<div> Hello 组件 </div>' }) // Vue.component( 组件的名称,组件的配置 ) Vue.component('Hello', Hello) //2、简写形式 Vue.component( 'Hello', { template: '<div> Hello 组件 </div>' }) new Vue({ el: '#app'//根组件并不一定是唯一的 }) new Vue({ el: '#root' })
V的实现:
//全局注册在两个根实例中都可以被解析 <div id="app"> <Hello></Hello> <hello></hello> </div> <div id="root"> <Hello></Hello> </div>
-
局部注册
/* 局部注册使用 components来完成 局部注册只在当前注册的实例范围内有效 */ new Vue({ el: '#app', components: { //局部注册组件的选项 // 组件的名称: 组件的选项 'Hello': { template: '<div> Hello 这里是局部注册 </div>' } } }) new Vue({ el: '#root' })
V的实现:
<div id="app"> <Hello></Hello> //此实例中的组件可以被解析 <hello></hello> </div> <div id="root"> <Hello></Hello>//此实例中的组件不可以被解析 </div>
-
-
2、组件的使用规则
-
具有直接父子级关系的标签,会出现渲染问题,我们通过is属性来解决
-
业务: 给下面的表格增加一个行,这一行用一个组件表示。
<body> <div id="app"> <table border="1"> <tr> <td>1</td> <td>2</td> <td>3</td> </tr> <tr is = "Hello"></tr> </table> </div> </body> <script src="../../lib/vue.js"></script> <script> Vue.component('Hello',{ template: ` <tr> <td>4</td> <td>5</td> <td>6</td> </tr>` }) new Vue({ el: '#app' }) </script>
3、动态组件
-
动态组件指的是通过 Vue 提供的 component组件 + is 属性来实现
-
keep-alive组件实现缓存,可以提高加载速度
-
业务: 点击开关切换两个组件(注意:template模板内直接子元素有且只能有一个)
<body> <div id="app"> <button @click = "typeChange"> 点击 </button> <keep-alive> <component :is = "type"></component> </keep-alive> </div> //template模板内直接子元素有且仅有一个 <template id="hello-box"> <div> <h3> 手机号登录 </h3> <div> 123 </div> </div> </template> </body> <script src="../../lib/vue.js"></script> <script> new Vue({ el: '#app', data: { type: 'PhoneLogin' }, methods: { typeChange () { // this.type = this.type === 'PhoneLogin' ? 'UserLogin': 'PhoneLogin' this.type = (this.type === 'PhoneLogin') && 'UserLogin' || 'PhoneLogin' } }, components: { 'PhoneLogin': { template: '#hello-box' }, 'UserLogin': { template: '<div> 用户名密码登录</div>' } } }) </script>
4、组件的通信
-
组件的嵌套(子组件以标签的形式在父组件的模板中使用)
-
局部注册写法
<body> <div id="app"> <Father></Father> </div> <template id="father"> <!-- 唯一根元素 --> <div> <h3> 这里是父组件 </h3> <hr> //子组件以标签的形式要在父组件的模板中使用 <Son></Son> </div> </template> <template id="son"> <div> <h3> 这里是子组件 </h3> </div> </template> </body> <script src="../../lib/vue.js"></script> <script> new Vue({ el: '#app', //以下即为局部注册的嵌套写法 components: { 'Father': { template: '#father', components: { 'Son': { template: '#son' } } } } }) </script>
-
全局注册写法
<body> <div id="app"> <Father></Father> </div> <template id="father"> <div> <h3> 这里是父组件 </h3> <hr> <Son></Son> </div> </template> <template id="son"> <div> <h3> 这里是子组件 </h3> </div> </template> </body> <script src="../../lib/vue.js"></script> <script> //全局写法 Vue.component('Father', { template: '#father' }) Vue.component('Son', { template: '#son' }) new Vue({ el: '#app' }) </script>
-
-
组件中数据的定义
Vue.component('Hello',{ template: '#hello', data () { return { msg: 'hello 组件' // 组件的数据,使用范围只能在组件的模板中 } } })
- 为什么组件中的data选项是一个函数,而根实例中是对象?
- 组件是一个独立的整体,那么数据也应该是一个独立的
- javascript最大的特点: 函数式编程,而函数本身就有一个独立作用域
- 多人开发,数据如果不是独立的,那么数据会冲突
- 为什么组件中的data函数要有返回值,并且返回值是一个对象,不能是其他的吗?
- 因为data选项要经过es5 Object.defineProperty 属性进行getter和setter设置
- 组件中数据的使用范围?
- 组件的数据,使用范围只能在所定义的组件的模板中
- 为什么组件中的data选项是一个函数,而根实例中是对象?
-
组件的通信
-
父子组件通信
父子组件通信的步骤:
- 父组件中定义一个数据
- 在父组件的模板中,用 v-bind 将父组件的数据绑定在子组件身上
- 在子组件的选项中,通过props选项来接收这个属性
- 这个属性可以在子组件的模板中以全局变量的形式使用
<body> <div id="app"> <Father/>//组件可以使用单标签也可以使用双标签 </div> <!-- father 组件 --start --> <template id="father"> <div> <h3> 这里是父组件 </h3> <hr> <Son :aa = "money"></Son> </div> </template> <!-- father 组件 --end --> <!-- son组件 --start --> <template id="son"> <div> <h4> 这里是子组件 </h4> <p> 老爸给了我 {{ aa }} 生活费 </p> </div> </template> <!-- son组件 --end --> </body> <script src="../../lib/vue.js"></script> <script> Vue.component('Father',{ template: '#father', data () { return { money: 3000 } } }) Vue.component('Son',{ template: '#son', props: ['aa'] /* */ }) new Vue({ el: '#app' }) </script>
-
Props属性验证:
-
1.props可以是一个对象
-
2.props中的validator函数
-
3.props第三方属性验证: vue-validator-help
//属性验证之验证数据类型 props: { 'aa': Number } //属性验证之比较大小 props: { 'aa': { validator ( val ) { return val > 2000 } } }
-
-
子父组件通信
子父组件通信的步骤:
- 先在子组件中定义一个数据
- 在父组件中也定义一个数据,这个数据用来接收子组件传递过来的数据
- 在父组件中定义一个事件处理程序,用于改变父组件定义的数据,这个事件处理程序是有参数的,这个参数就是子组件传递过来的数据
- 将这个事件处理程序通过事件绑定的形式绑定在子组件身上
- 在子组件中定义一个事件处理程序,这事件处理程序中通过 this.$emit来触发自定义事件,并传递一个参数给父组件
<body> <div id="app"> <Father /> </div> <!-- father 组件 --start --> <template id="father"> <div> <h3> 这里是父组件 </h3> <p> 我的钱有: {{ bank }} </p> <hr> //4.将这个事件处理程序通过事件绑定的形式绑定在子组件身上 <Son @aa="bankAdd"></Son> </div> </template> <!-- father 组件 --end --> <!-- son组件 --start --> <template id="son"> <div> <h4> 这里是子组件 </h4> <button @click=" give "> 给老爸红包 </button> </div> </template> <!-- son组件 --end --> </body> <script src="../../lib/vue.js"></script> <script> Vue.component('Father', { template: '#father', //2. 在父组件中也定义一个数据,这个数据用来接收子组件传递过来的数据 data() { return { bank: 1000 } }, //3.在父组件中定义一个事件处理程序,用于改变父组件定义的数据,这个事件处理程序是有参数的,这个参数就是子组件传递过来的数据 methods: { bankAdd(val) { //val就是子组件给的数据 this.bank += val } } }) Vue.component('Son', { template: '#son', //1. 先在子组件中定义一个数据 data() { return { money: 1000 } }, // 5.在子组件中定义一个事件处理程序,这事件处理程序中通过 this.$emit来触发自定义事件,并传递一个参数给父组件 methods: { give() { // this.$emit('aa',传递给父组件的参数) this.$emit('aa', this.money) } } }) new Vue({ el: '#app' }) </script>
-
非父子组件通信
-
ref
<body> <div id="app"> <Father /> </div> <template id="father"> <div> <h3>这里是father组件</h3> <hr> <Girl :fn="emitCry"></Girl> <hr> <Son ref="son"></Son> </div> </template> <template id="son"> <div> <h3> 这里是son组件 </h3> <img v-if="flag" style="width: 100px;height: 100px;" src="https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1564471527&di=2c4707955cefb24c325842ea288b9647&src=http://b-ssl.duitang.com/uploads/item/201702/16/20170216145320_wyNiK.jpeg" alt=""> </div> </template> <template id="girl"> <div> <h3> 这里是girl 组件 </h3> <button @click="fn"> 揍弟弟 </button> </div> </template> </body> <script src="../../lib/vue.js"></script> <script> Vue.component('Father', { template: '#father', methods: { emitCry() { this.$refs.son.cry() } } }) Vue.component('Son', { template: '#son', data() { return { flag: false } }, methods: { cry() { this.flag = true } } }) Vue.component('Girl', { template: '#girl', props: ['fn'] }) new Vue({ el: '#app' }) </script>
-
bus事件总线
<body> <div id="app"> <Girl></Girl> <Son></Son> </div> <template id="girl"> <div> <h3> 这里是girl </h3> <button @click="kick"> 揍弟弟 </button> </div> </template> <template id="son"> <div> <h3> 这里是son </h3> <img style="width: 100px;height: 100px;" v-if="flag" src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1564481613744&di=22ebae5b3c4655691a1244e46682d7c9&imgtype=0&src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201702%2F16%2F20170216145320_wyNiK.jpeg" alt=""> </div> </template> </body> <script src="../../lib/vue.js"></script> <script> var bus = new Vue() Vue.component('Son', { template: '#son', data() { return { flag: false } }, methods: { cry() { this.flag = true } }, mounted() { //这个选项表示组件挂载结束 这个方法时自定执行,只要组件创建,它就自动执行 // bus.$on(自定义事件的名称,自定义事件的处理程序) var _this = this bus.$on('aa', function () { // 通过$on自定义一个叫做aa的事件 _this.cry() }) } }) Vue.component('Girl', { template: '#girl', methods: { kick() { bus.$emit('aa') } } }) new Vue({ el: '#app' }) </script>
-
-
多组件状态共享
- Vuex
-