您的位置:首页 > Web前端 > Vue.js

Vue学习2-3.组件;4.插槽分发;5.动态组件;6.数据处理;

2019-04-26 20:58 651 查看

目录

 

三.组件

1.data 属性

2.props  属性 

3.props  校验 

4.非 props  属性

5.自定义事件 

四.插槽分发

1 、slot  插槽

  1)子组件插槽

2)父组件分发

2 、具名插槽 

1 )定义具名插槽

2 ) 父组件分发 

3 、slot-scope 

1 )子组件定义

2 )父组件使用 

五.动态组件 

1 、使用方式

1 ) 定义多个子组件

2 )使用 component  引用 

3 )指定导航 

4 )完整代码

2 、keep-alive 

3 、refs 

六.数据处理 

1 、watch 属性

2 、$watch 

 3 、computed  属性

4 、getter 和 和 setter

三.组件

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 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: