Vue学习2-3.组件;4.插槽分发;5.动态组件;6.数据处理;
目录
三.组件
1.data 属性
通过 data 属性指定自定义组件的初始数据,要求 data 必须是一个函数,如果不是函数就会报错。
实例:
[code]Vue.component('my-component',{ template:'<button @click="count += 1">计数 {{count}}</button>', data: function () { return{count:0} } });
2.props 属性
组件可以嵌套使用,叫做 父子组件。那么父组件经常要给子组件传递数据这叫做 父子组件通信。父子组件的关系可以总结为 props 向下传递,事件向上传递。父组件通过 props 给子组件下发数据,子组件通过事件给父组件发送消息。看看它们是怎么工作的:
[code]1 )明 声明 props Vue.component('child', { //声明 props props:['a','b'], //使用父组件传递的数据 template:'<span>{{a}} == {{b}}</span>' }) 2 )父组件 var app = new Vue({ el:'#app', data:{ msg:'来自父组件的消息', greetText:'你好 Child' } }); 3 )用指定 props 传递数据 <div id="app"> <!-- v-bind:a 简写成 :a --> <child :a="msg" :b="greetText"></child> </div>
3.props 校验
子组件在接收父组件传入数据时, 可以进行 props 校验,来确保数据的格式和是否必传。可以指定一下属性:
1) type: 指定数据类型 String Number Object ...注意不能使用字符串数组,只能是对象大写形式
2) required: 指定是否必输;
3) default: 给默认值或者自定义函数返回默认值
4) validator: 自定义函数校验
4.非 props 属性
引用子组件时,非定义的 props 属性,自动合并到子组件上,class 和 style 也会自动合并。
实例:
[code]<div id="app"> <child data-index="0" class="cont" style="font-size: 20px;"></child> </div> <script> /*** * 引用子组件: 非定义的props属性,自动合并到子组件上,class和style也 会自动合并 * */ Vue.component('child', { template:'<span class="item" style="color:red;">我是 child</span>' }); var app = new Vue({ el:'#app' }); </script>
5.自定义事件
父组件给子组件传值使用 props 属性, 那么需要子组件更新父组件时,要使用自定义事件$on 和$emit:
$on 监听: 不能监听驼峰标示的自定义事件, 使用全部小写(abc)或者-(a-b-c)
$emit 主动触发: $emit(事件名,传入参数)
实例:
[code]1 )声明父组件 var app = new Vue({ el:'#app', data:{ count:0 }, methods:{ //定义计数方法 changeCount:function(value){ console.log(value); //计数 this.count += 1; } } }); 2 )自定义事件 <div id="app"> <!-- 自定义事件 --> <child v-on:update-count="changeCount"></child> <p>{{count}}</p> </div> 3 )定义子组件 Vue.component('child', { template:'<button v-on:click="update">子组件 Child</button>', methods:{ update: function () { console.log('update'); //主动触发事件执行 this.$emit('update-count', '子组件参数'); } } }); 子组件 child 中定义的 update 方法,内部通过$emit('update-count')主动触 发父元素事件的执行 4 )主动挂载 自定义事件不仅可以绑定在子组件,也可以直接挂载到父组件, 使用$on 绑定和$emit 触发。 var app = new Vue({ el:'#app', data:{ count:0 }, methods:{ changeCount:function(value){ console.log(value); //计数 this.count += 1; } } }); //主动挂载 app.$on('update-count', function(value){ console.log(value); //计数 this.count += 1; }); app.$emit('update-count',123);
四.插槽分发
父子组件使用时,有时需要将父元素的模板跟子元素模板进行混合,这时就要用到slot 插槽进行内容分发, 简单理解就是 在子模板中先占个位置<slot> 等待父组件调用时进行模板插入。
1 、slot 插槽
1)子组件插槽
[code]<template id="child-template"> <div> <div>我是子组件</div> <div>{{msg}}</div> <!-- 定义 slot 插槽进行占位 --> <slot>我是默认内容,父组件不传入时我显示</slot> </div> </template> Vue.component('child', { template:'#child-template', props:['msg'] });
在子组件模板中使用<slot>标签定义插槽位置,标签中可以填写内容,当父组件不传入内容时显示此内容
2)父组件分发
[code]<div id="app"> <!-- 传入数据 --> <child :msg="msgText"> <!-- 传入模板,混合子模板 --> <h4>父组件模板</h4> <h5>模板混入....</h5> </child> </div>
在引用<child>子组件时,标签中的内容会放在子组件的<solt>插槽中
2 、具名插槽
具名插槽 slot, 就是给插槽起个名字。在子组件定时可以定定义多个<slot>插槽,同时通过 name 属性指定一个名字,如:<slot name='header'>,父组件引用时使用<slot='header'>进行插槽选择 .
1 )定义具名插槽
[code]<template id="child-template"> <div> <!-- 插槽 header --> <slot name="header"></slot> <div>我是子组件</div> <div>{{msg}}</div> <!-- 插槽 footer --> <slot name="footer"></slot> </div> </template>
模板定义了两个插槽 header 和 footer,分别使用 name 属性进行名称的指定
2 ) 父组件分发
[code]<div id="app"> <!-- 传入数据 --> <child :msg="msgText"> <!-- 传入模板,混合子模板 --> <h4 slot="header">头部</h4> <h4 slot="footer">底部</h4> </child> </div>
通过 slot 属性,来确定内容需要分发到那个插槽里面
3 、slot-scope
作用域插槽 slot-scope,父组件通过<slot>插槽混入父组件的内容, 子组件也可以通过 slot 作用域向插槽 slot 内部传入数据,使用方式:<slot text=' 子组件数据'>,父组件通过<template slot-scope="props">进行引用。
1 )子组件定义
[code]<template id="child-template"> <div> <!-- 插槽 text 值 --> <slot text="子组件数据" ></slot> </div> </template>
在 slot 标签中指定属性值,类似于 props 属性的使用
2 )父组件使用
[code]<div id="app"> <!-- 传入数据 --> <child> <template slot-scope="props"> <div>{{msgText}}</div> <div>{{props.text}}</div> </template> </child> </div>
引用时用 template 标签指定,slot-scope 属性指定接收数据的变量名,就可以使用花括号形式取值了
五.动态组件
使用<component>标签的 is 属性,动态绑定多个组件到一个挂载点,通过改变 is 绑定值,切换组件。
1 、使用方式
1 ) 定义多个子组件
[code]Vue.component('index', { template:'<h5>首页</h5>' }); Vue.component('news', { template:'<h5>新闻页</h5>' }); Vue.component('login', { template:'<h5>登陆页</h5>' });
2 )使用 component 引用
[code]<component :is="page"></component>
3 )指定导航
[code]/ <a href='#' @click.prevent="page='index'">首页</a> / <a href='#' @click.prevent="page='news'">新闻</a> / <a href='#' @click.prevent="page='login'">登陆</a>
4 )完整代码
[code]<div id="app"> / <a href='#' @click.prevent="page='index'">首页</a> / <a href='#' @click.prevent="page='news'">新闻</a> / <a href='#' @click.prevent="page='login'">登陆</a> <hr> <component :is="page"></component> </div> <script> /*** * 使用<component>标签的 is 属性,动态绑定多个组件到一个挂载点, * 通过改变 is 绑定值,切换组件 * */ Vue.component('index', { template:'<h5>首页</h5>' }); Vue.component('news', { template:'<h5>新闻页</h5>' }); Vue.component('login', { template:'<h5>登陆页</h5>' }); var app = new Vue({ el:'#app', data:{ page:'index' } }); </script>
2 、keep-alive
如果把切换出去的组件保留在内存中,可以保留它的状态或避免重新渲染。为此可以添加一个 keep-alive 指令
[code]<div id="app"> / <a href='#' @click.prevent="page='index'">首页</a> / <a href='#' @click.prevent="page='news'">新闻</a> / <a href='#' @click.prevent="page='login'">登陆</a> <hr> <keep-alive> <component :is="page"></component> </keep-alive> </div>
使用 keep-alive 嵌套 component.
[code]Vue.component('index', { template:'<h5>首页</h5>', mounted: function () { console.log('挂载...首页'); } }); Vue.component('news', { template:'<h5>新闻页</h5>', mounted: function () { console.log('挂载...新闻页'); } }); Vue.component('login', { template:'<h5>登陆页</h5>', mounted: function () { console.log('挂载...登陆页'); } });
用生命周期中的 mounted(挂载)钩子函数进行组件渲染监听,当组件第一次被渲染后就保存在内存中,下次切换不会被重新渲染。
3 、refs
使用 ref 给每个组件起一个固定的名字,方便后续直接引用操作,在父组件中使用$refs 访问子组件
[code]<div id="app"> <child ref="btn1"></child> <child ref="btn2"></child> </div> <script> /*** * ref 给每个组件起一个固定的名字,方便后续直接引用操作 * */ Vue.component('child', { template:'<button>{{count}}</button>', data:function(){ return {count:0} } }); var app = new Vue({ el:'#app' }); app.$refs.btn1.count = 1; app.$refs.btn2.count = 2; </script>
六.数据处理
1 、watch 属性
在 Vue 组件中,使用 watch 属性来监听数据的变化,同时可以指定监听那个属性。
[code]<div id="root"></div> <script> var vm = new Vue({ el:'#root', data:{ name:'Tim' }, watch:{ name: function (newValue, oldValue) { console.log('newValue:'+newValue+';oldValue'+oldValue); } } }); //改变 name vm.name = 'Cat';//newValue:Cat;oldValueTim </script>
例子中通过 watch 监听 name 属性的变化,回调函数中第一个参数是新值,第二个参数是旧值。
[code]<div id="root"> <p> firstName: <input type="text" v-bind:value="firstName" @keyup="changeFirstName($event);"> </p> <p> lastName: <input type="text" v-bind:value="lastName" @keyup="changeLastName($event)"> </p> <h4>{{fullName}}</h4> </div> <script> var vm = new Vue({ el:'#root', data:{ firstName:'Hello', lastName:'Kitty', fullName:'Hello Kitty' }, watch:{ firstName: function (newValue, oldValue) { console.log('newValue:'+newValue+';oldValue'+oldValue); this.fullName = newValue+' '+this.lastName;//更新 fullname }, lastName: function (newValue, oldValue) { console.log('newValue:'+newValue+';oldValue'+oldValue); this.fullName = this.firstName+' '+newValue;//更新 fullname } }, methods:{ changeFirstName: function (event) { this.firstName = event.target.value; }, changeLastName: function (event) { this.lastName = event.target.value; } } }); </script>
fullName 由 firstName 和 lastName 共同决定,当改变 firstName 时需要重新计算 fullName,改变 lastName 也一样。那么就需要监听这两个属性的变化去更新fullName,这时候就可以使用 watch 监听。
2 、$watch
除了在组件内部使用 watch 也可以使用内部命令$watch 进行属性监听。
[code]<div id="root"></div> <script> var vm = new Vue({ el:'#root', data:{ name:'Tim' } }); //$watch 使用 var unwatch = vm.$watch('name',function (newValue, oldValue) { console.log('newValue:'+newValue+';oldValue'+oldValue); }); //改变 name vm.name = 'Cat'; //unwatch(); 取消监听 </script>
$watch 第一个参数是需要监听的属性,第二个是回调函数用法和 watch 一样。需要取消监听只需拿到监听对象的引用,这个引用是返回一个函数对象,执行该对象就可以取消监听。
同时监听多个属性,可以不指定属性
[code]<div id="root"></div> <script> var vm = new Vue({ el:'#root', data:{ name:'Tim', age:12 } }); //$watch 使用 vm.$watch(function(){ return this.name+this.age; },function (newValue, oldValue) { console.log('newValue:'+newValue+';oldValue'+oldValue); }); //改变 name vm.name = 'Cat'; vm.age = 15; //newValue:Cat15;oldValueTim12 </script>
3 、computed 属性
computed 计算属性用于定义比较复杂的属性计算,比如上边计算 fullName 的时候,需要使用 watch 两个属性:firstName 和 lastName,比较繁琐,但是使用 computed就很简单。
[code]<div id="root"> <p> firstName: <input type="text" v-bind:value="firstName" @keyup="changeFirstName($event);"> </p> <p> lastName: <input type="text" v-bind:value="lastName" @keyup="changeLastName($event)"> </p> <h4>{{fullName}}</h4> </div> <script> var vm = new Vue({ el:'#root', data:{ firstName:'Hello', lastName:'Kitty' }, computed:{ fullName: function () { return this.firstName+' '+this.lastName;//计算 fullname } }, methods:{ changeFirstName: function (event) { this.firstName = event.target.value; }, changeLastName: function (event) { this.lastName = event.target.value; } } }); </script>
此时注意,不在 data 中定义 fullName 而是在 computed 属性中指定,回调函数返回值就是 fullName 的值,这样不管 firstName 和 lastName 谁发生变化都会更新fullName
computed 和 和 methods 区别:
计算属性使用 computed 定义, 方法使用 methods 定义
计算属性使用时不加括号执行符
计算属性是基于它们的依赖进行缓存的,计算属性只有在它的相关依赖发生改变时才
会重新求值。否则返回之前计算好的值,性能更高!
4 、getter 和 和 setter
在 computed 中,同样可以指定 setter 进行数据更新。上述例子中都是通过firstName 和 lastName 来计算 fullName,那么也可以通过 fullName 来更新firstName 和 lastName。
[code]<div id="root"> <p> fullName: <input type="text" v-bind:value="fullName" @keyup="changeFullName($event);"> </p> <h4>firstName: {{firstName}}</h4> <h4>lastName: {{lastName}}</h4> </div> <script> var vm = new Vue({ el: '#root', data: { firstName: 'Hello', lastName: 'Kitty' }, computed: { fullName: { //getter get: function () { return this.firstName + ' ' + this.lastName;// 计算 fullname }, //setter set: function (newValue) { var names = newValue.split(' '); this.firstName = names[0]; this.lastName = names[names.length - 1]; } } }, methods: { changeFullName: function (event) { this.fullName = event.target.value; } } }); </script>
此时改变 fullName 就可以同步更新 lastName 和 firstName
- Vue 2.0学习笔记:Vue组件内容分发(slot)
- 常用js框架之vue.js(深入四:组件2,slot内容分发,编译作用域,动态切换组件)
- vue-插槽,动态组件和过滤器
- Vue------第五天(关于组件的一些基础了解,包括组件的注册、Prop、自定义事件、使用插槽分发内容等)
- Vue组件-使用插槽分发内容
- 使用Vue的slot插槽分发父组件内容实现高度复用、更加灵活的组件
- vue组件(父子组件传值、非props特性、作用域插槽、动态组件、v-once)
- vue学习之——动态插槽名
- 使用Vue的slot插槽分发父组件内容实现高度复用、更加灵活的组件(推荐)
- vue动态组件和slot插槽
- VUE入门到实战--Vue非父子组件传值、插槽、动态组件和v-once
- vue(9)----组件(2)slot插槽 动画过渡 动态组件
- 带着实例继续学习(4):下拉框数据填充、组件生命周期、动态绑定事件
- vue学习一 组件之间的数据传递
- vue父组件向子组件动态传值的两种方法
- 深入解析vue使用插槽分发内容slot的用法
- 【音乐App】—— Vue-music 项目学习笔记:播放器内置组件开发(一)
- 打通前后端全栈开发node+vue进阶【课程学习系统项目实战详细讲解】(3):用户添加/修改/删除 vue表格组件 vue分页组件
- Vue中的slot使用插槽分发内容的方法
- vue.js 中 :is 与 is 的用法和区别,学习全局与局部注册组件