Vue 中的组件
VUE中的组件
一个自定义的标签,vue就会把他看成一个组件,vue可以给这些标签赋予一定意义;一个页面就是一个组件
好处:
- 1、提高开发效率
- 2、方便重复使用
- 3、便于协同开发
- 4、更容易被管理和维护
自定义标签的书写规范:
1、组件名不支持大写字母(首字母可支持大写)
2、html中采用多个单词用-隔开命名法,js中转换为对应的驼峰命名法
注意:组件中的动态数据data数据必须是函数数据类型的,返回一个实例作为组件的数据。这样做是为了防止子组件之间公用数据导致的同时更新;(下面局部组件中有案例)
全局组件
用法:声明一次可以在任何地方使用
//必须要先用component赋予自定义标签意义,然后再初始化实例
Vue.component('my-hand',{
template:'<div>{{msg}}</div>',
data(){
return {msg:'我很英俊'}
}
});
let vm=new Vue({
el:'#app'
})
//页面中使用
<div id="app">
<my-hand></my-hand>
</div>
局部组件
用法:必须告诉这个组件属于谁,组件之间是相互独立的,不能直接跨作用域,vue的实例也是一个组件,拥有生命周期函数,理论上可以无限嵌套
1、创建局部组件(js)
2、注册这个组件(js)
3、在HTML中使用这个组件
注意事项:
1、子组件不能直接使用父组件的数据
2、组件理论上可以无限嵌套
3、子组件之间如果共用了数据,而且不把data写为返回一个对象的形式,会导致同时更新;
//创建一个局部组件
let handsome={
template:'<div>{{msg}}</div>',
//组件中的data必须是函数类型的,返回一个值作为组件的数据
data(){
return {msg:'我很英俊'}
}
};
let handsome1={
template:'<div>{{msg}}</div>',
data(){
return {msg:'我是在外部创建的局部组件'}
}
};
let vm=new Vue({
el:'#app',
components:{
//在components中注册局部组件
handsome:handsome,
handsome1:handsome1
//在ES6中属性名和值相同可只写一个(上面的可简写为如下的形式)
handsome,handsome1,
//也可直接在components中直接创建和注册子组件
handsome2:{
template:'<div>{{msg}}</div>',
data(){
return {msg:'我是在components中创建和注册的局部组件'}
}
}
}
})
//在页面中使用局部组件
<div id="app">
<handsome></handsome>
<handsome1></handsome1>
<handsome2></handsome2>
</div>
子组件之间公用数据导致的同时更新的问题;
let obj={school:'zfpx'};
let component1 = {
template: `<div @click="school='hello'">组件一{{school}}</div>`,
data(){
return obj;//此种写法是错误的,点击组件一的时候会导致obj的数据更新,结果也会反映到组件二上
}
};
let component2 = {
template: '<div>组件二{{school}}</div>',
data(){
return obj;
}
};
let vm=new Vue({
el:'#app',
components:{
component1,component2
}
})
//页面中使用
<div id="app">
<component1></component1>
<component2></component2>
</div>
子组件与父组件之间的数据传递和嵌套
嵌套
//创建局部组件,相当于给grandson这个标签赋予了实际的意义
//一定要先创建最内层的组件(即孙子)
let grandson={
template:'<div>{{msg}}</div>',
data(){return {msg:'我是孙子'}}
};
let son={
template:'<div>{{msg}}<grandson></grandson></div>',
data(){return{msg:'我是儿子'}},
components:{
//在儿子中嵌套孙子组件
//在son的components中注册了孙子组件后,才可在son的模版中使用grandson标签(但是依然不能在页面中使用son标签)
grandson
}
};
let parent={
template:'<div>{{msg}}<son></son></div>',
data(){return{msg:'我是父亲'}},
components:{son}
};
let vm=new Vue({
el:'#app',
components:{
//在vue的实例中注册了parent组件之后才能在页面中使用parent标签
parent
}
})
//在页面中使用局部组件
<div id="app">
<parent></parent>
</div>
数据传递
父传递给子
可以通过给子组件设置自定义属性的方式拿到父组件的属性值,子组件用props方法来获取到自定义属性的值就可以直接在子组件的模版中使用了;
let vm=new Vue({
el:'#app',
data:{
msg:100
},
components:{
child:{
//props属性写成数组的形式不能进行校验
props:['m'],//相当于取到子组件自定义的m属性,值是父亲的
//写成对象的形式可以校验其值的类型
props:{
m:{
//校验类型拿到的值是否属于下面的类型,不属于也会进行渲染,控制台会提示类型错误
type:[Number,String,Function,Object,Array],
default:0//如果子组件没有m属性,则m值默认取0
//如果m属性是必须的,则可增加required:true(不可与default同用)
required:true
},
},
template:'<div>儿子{{m}}</div>'//这里就可以直接用m
}
}
})
//在页面中使用局部组件
<div id="app">
父亲:{{msg}}
<!--m属于子组件的自定义的属性,前面加了:之后,m的值就变为动态的了->
<child :m="msg"></child>//msg:拿到的是父的数据
</div>
子传递给父
为了防止子组件无意间修改了父组件的状态,props采用的是单向绑定。所以子组件传递给父组件数据就不能通过设置自定义属性的方法,而要通过发布订阅模式来传递;
let vm=new Vue({
el:'#app',
data:{
money:400
},
methods:{
things(val){//val:儿子触发事件时传过来的数据
this.money=val;
}
},
components:{
child:{
props:['m'],
//给儿子的按钮添加点击事件,当点击的时候触发发布订阅模式,执行绑定在子组件上的事件
template:'<div>儿子{{m}} <button @click="getMoney()">多要钱</button></div>',
methods:{
getMoney(){//此处的this指的是子组件的实例
//触发自定义事件(child),让父亲的方法(things)执行
this.$emit('child',800);
}
}
}
}
});
//在页面中使用子组件
<div id="app">
父亲:{{money}}
<child :m="money" @child="things"></child>
</div>
组件中的插槽(slot标签)
slot标签的作用:定制模版
slot相当于一个插槽,可以把组件中的对应标签拿到之后替换自己里面的内容
slot中可以放一些默认的内容,如果组件中对应slot值的标签有内容则会被替换掉,如果没有则会使用slot中的默认内容
//js
let model={
template:'#model'
};
let vm=new Vue({
el:'#app',
data:{msg:'zf'}
methods:{
fn(){alert('是')}
},
components:{
model
}
})
//html
<div id="app">
<!--这里放的内容均属于父级模版的(如fn方法),所以必须在父模版的methods中写fn方法。msg属性也是父模版的。只有自定义的属性名是属于组件的(如m属性)-->
<model :m="msg">
<!--下面标签中的slot值与template中的slot是对应的,没有slot值的都会被放到default中-->
<a href="www.baidu.com">百度一下</a>
<p slot="content">确认删除?</p>
<h1 slot="title" @click="fn">是否删除?</h1>
<a href="www.baidu.com">百度一下</a>
</model>
</div>
<!--模版中只能有一个根元素-->
<!--slot作用,定制模版-->
<!--slot相当于一个插槽,可以把组件中的对应标签拿到之后替换自己的内容-->
<!--如果组件中没有标签,则使用slot中默认的内容-->
<template id="model">
<div>
<slot name="title">默认标题</slot>
<slot name="content">默认内容</slot>
<slot name="default">这是一个默认标题</slot>
</div>
</template>
如何在父组件中调用子组件中的方法
通过给子组件设置ref值为xxx,在父组件中可通过
this.$refs.xxx找到对应ref值的子组件的vue对象。(子组件的方法也挂载到了它的vue对象上)
由于在mounted执行时,子组件的DOM结构才加载完成,所以只有在mounted函数中才能用this.$refs.xxx.$el拿到对应子组件的DOM元素;
let loading={
data(){
return{flag:true}
},
template:'<div>正在加载中……</div>',
//子组件的方法
methods:{
hide(){
//此方法中的this是子组件的vue对象
//hide执行的时候会把子组件的DOM元素背景色改为红色
this.$el.style.background='red';
}
},
};
let vm=new Vue({
el:'#app',
mounted(){
//在此处实现父组件调用子组件的方法
//此处的this是vm,this.$refs获取的不是子组件的DOM而是vue对象;
// 可用this.$refs.load.$el来获取对应的DOM结构;
this.$refs.load.hide();
},
components:{
loading
}
})
//Html
<div id="app">
<loading ref="load"></loading>
</div>
动态组件
component标签
通过使用component标签,我们可以让多个组件使用同一个挂载点,并根据component内置的is属性来实现动态切换(is属性可以理解为是哪一个组件);
let home={
template:'<div>home</div>',
//如果放在了keep-alive标签中,则可以保留它的状态来避免以后点击重新渲染。只在第一次渲染的时候会弹出1
mounted(){alert(1)}
};
let list={
template:'<div>list</div>',
//如果放在了keep-alive标签中,则只在第一次点击的时候弹出2
mounted(){alert(2)}
};
let vm=new Vue({
el:'#app',
data:{radio:'home'},
components:{home,list}
})
//html
<div id="app">
<input type="radio" v-model="radio" value="home">home
<input type="radio" v-model="radio" value="list">list
<!--keep-alive标签一般用来缓存:现在讲是为了后面的路由做准备,如果缓存了,只会走beforeUpdate与之后的阶段-->
<keep-alive>
<component :is="radio"></component>
</keep-alive>
</div>
keep-alive标签
如果想把切换出去的组件保留在内存中,可以保留它的状态或避免重新渲染。可以把需要缓存的标签外面包一个 keep-alive 标签
<keep-alive>
<component :is="radio"></component>
</keep-alive>
$nextTick的用法
子组件和父组件都有mounted方法时,会先执行子组件的mounted方法:因为要保证子组件挂载完成再触发父组件的挂载
let vm=new Vue({
el:'#app',
mounted(){//想操作最新的DOM,就需要用$nextTick方法(异步的来获取)
//未加$nextTick方法,获取的不是最新的DOM
console.log(this.$refs.child.$el.innerHTML);//结果为1,2,3
//为了保证操作的是最新的DOM,则需要用$nextTick方法
this.$nextTick(()=>{
console.log(this.$refs.child.$el.innerHTML);//4,5,6(获取到的是最新的结果)
})
},
components:{
child:{
data(){
return {arr:[1,2,3]}
},
template:'<div><li v-for="a in arr">{{a}}</li></div>',
mounted(){//先执行子组件的mounted方法之后再同步执行父组件的mounted方法
this.arr=[4,5,6]//此步骤涉及到DOM渲染,所以说是异步的,而执行父组件的mounted方法时,此步骤还未实现
}
}
}
})
//html
<div id="app">
<child ref="child"></child>
</div>同级组件之间的数据传递通过EventBus(不用,但要了解)
为了保证订阅和执行的是同一个对象,需要借助第三方实例,通过第三方实例实现发布订阅
EventBus就是用来创建第三方实例的,可用来保证订阅和执行的时候是同一个对象
Vue 中的组件的更多相关文章
- vue中自定义组件(插件)
vue中自定义组件(插件) 原创 2017年01月04日 22:46:43 标签: 插件 在vue项目中,可以自定义组件像vue-resource一样使用Vue.use()方法来使用,具体实现方法: ...
- Vue中父子组件执行的先后顺序
Vera Vue中父子组件执行的先后顺序探讨(转载) 前几天,朋友向我提出了一个关于Vue中父子组件执行的先后顺序问题,相信很多朋友在学习的过程中也会遇到这个问题,所以我就在此提出我自己的一些小看 ...
- Vue中父子组件执行的先后顺序探讨
前几天,朋友向我提出了一个关于Vue中父子组件执行的先后顺序问题,相信很多朋友在学习的过程中也会遇到这个问题,所以我就在此提出我自己的一些小看法. 问题如下:请问下图中父子组件执行的先后顺序? 首先, ...
- Vue中父组件向子组件传值
Vue中父组件向子组件传值 相关Html: <!DOCTYPE html> <html lang="en"> <head> <meta c ...
- Vue 中数据流组件
好久不见呀,这两年写了很多很多东西,也学到很多很多东西,没有时常分享是因为大多都是我独自思考.明年我想出去与更多的大神交流,再修筑自己构建的内容. 有时候我会想:我们遇到的问题,碰到的界限,是别人给的 ...
- 简述vue中父子组件是怎样相互传递值的(基础向)
前言 首先,你需要知道vue中父组件和子组件分别指的是什么? 父组件:vue的根实例——用new Vue()构造函数创建的vue实例(实例会有一个挂载点,挂载点里的所有内容可理解为父组件的内容) ...
- 解决vue中element组件样式修改无效
vue中element组件样式修改无效 <style> .detail{ .el-input__inner { height: 48px; } } </style> 直接写st ...
- Vue中keep-alive组件的理解
对keep-alive组件的理解 当在组件之间切换的时候,有时会想保持这些组件的状态,以避免反复重渲染导致的性能等问题,使用<keep-alive>包裹动态组件时,会缓存不活动的组件实例, ...
- vue中的组件化
组件化 1.定义全局组件 1.要在父实例中使用某个组件,组件必须在实例值之前定义2.组件其实也是一个Vue实例,因此它在定义时也会接收:data.methond.生命周期函数等3.不同的组件不会与页面 ...
随机推荐
- iOS 系统原生分享图片 文字 音乐 纯视频 网页
为了方便使用,我封装了一个分享的工具类LFSystemShareUtil.工程要引Social.framework. LFSystemShareUtil.h #import <Foundatio ...
- fedora19/opensuse13.1 配置openvpn client
Date: 20140207Auth: Jin 1.install # yum -y install openvpn #zypper install openvpn 2.copy user key # ...
- 手Q游戏中心上线 完美释放娱乐基因
今年A股市场上手游概念股的表现可谓“独当一面”,不少和手游沾边的公司股价都翻了倍.在笔者看来,这些手游企业的股价明显高得离谱,这轮行情可以证明资本市场对手游的关注度非常高,但并不意味着这些手游 ...
- Web安全测试指南--文件系统
上传: 编号 Web_FileSys_01 用例名称 上传功能测试 用例描述 测试上传功能是否对上传的文件类型做限制. 严重级别 高 前置条件 1. 目标web应用可访问,业务正常运行. 2. 目 ...
- devfs、sysfs、udev介绍
转:http://www.360doc.com/content/11/1203/09/7378000_169310928.shtml 一.devfs linux下有专门的文件系统用来对设备进行管理,d ...
- quartz做集群配置较短的时间间隔会重复执行任务的问题
quartz.properties org.quartz.jobStore.misfireThreshold = 60000 这个参数(单位为毫秒)设置了以后就是超时1min的就不执行,小于1min会 ...
- appium+python自动化51-adb文件导入和导出(pull push)
前言 用手机连电脑的时候,有时候需要把手机(模拟器)上的文件导出到电脑上,或者把电脑的图片导入手机里做测试用,我们可以用第三方的软件管理工具直接复制粘贴,也可以直接通过adb命令导入和导出. adb ...
- C,C++经典问题
C,C++经典问题 1 编程基础 1.1 基本概念 1.1.1 指针的理解:const char*, char const*, char*const的区别问题几乎是C++面试中每次都会有的题目. ...
- IP编址
IP地址 /include/linux/inetdevice.h,定义IPV4专用的网络设备相关的结构.宏等 /net/ipv4/devinet.c.支持IPV4特性的设备操作接口 数据组织 net_ ...
- LINUX之文件操作权限讲解
r(Read,读取):对文件而言,具有读取文件内容的权限:对目录来说,具有浏览目 录的权限. w(Write,写入):对文件而言,具有新增.修改文件内容的权限:对目录来说,具有删除.移动目录内文件的权 ...