Vue组件应用
Vue的组件是可复用的 Vue 实例,且带有一个名字 。我们可以在一个通过 new Vue 创建的 Vue 根实例中,把这个组件作为自定义元素来使用。因为组件是可复用的 Vue 实例,所以它们与 new Vue 接收相同的选项,例如 data、computed、watch、methods 以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项。
一 创建组件
Vue提供了三种不同的方式来定义组件,分别是:全局组件,私有组件,单文件组件。接下来就让我一一道来。
1,全局组件
注册全局组件非常简单,也是很常用的一种方式。
Vue.component('myCom',{
template:'<div><p>我是一个全局<span>组件</span></p></div>'
});
Vue.component()方法需要两个参数:
第一个,组件名称;
第二个,实例(初始化)对象,可以包含所有使用new方式创建Vue实例时提供的所有属性,除了el。
注意:组件的实例对象必须提供一个template属性,用作该组件的HTML代码模板,且在该模板中有且只能有一个根元素。全局组件的注册必须在创建Vue实例之前。
小技巧:由于在编写JS时,一般没有HTML代码提示,创建组件模板代码会很不方便,所有可以在HTML文件中使用<template>元素创建模板,然后在组件的template属性中使用id选择器引用该模板。
注意:<template>元素必须在new Vue实例接管的根元素外部。
<template id="tem">
<div>
<p>我是组件内的p</p>
<span>我是组件中的span</span>
</div>
</template>
<!-- 在HTML中 -->
Vue.component('myCom',{
template:'#tem'
});
//在组件中
2,私有组件
全局创建的组件在所有Vue实例中均可以使用,有时候这并不符合我们的需求。你可以通过以下方式定义Vue实例的私有组件,这些组件只能在该Vue实例根元素内部使用。
var vm = new Vue({
el:'#app',
components:{
mycom:{
template:'#tem'
}
}
});
通过Vue实例的components属性可以定义私有组件,该属性绑定一个对象,对象的属性名是组件名,属性值是组件实例对象。
3,单文件组件
Vue的单文件组件是一个以.vue为后缀名的文件。由于HTML和JavaScrip不能识别.vue文件,所以不能直接使用这种方式的组件,必须配合webpack或vue-cli工具才能正确解析.vue文件。这里的重点是Vue单文件组件,所以有兴趣的同学请移步webpack中文网。
<tempalte>
//HTML模板
</template>
<script>
//JS代码
</script>
<style>
//CSS代码
</style>
.vue文件的名称就是组件的名称,其结构非常简单、清晰:
<template>标签是组件的HTML模板;
<script>标签是逻辑代码;
<style>标签中是样式代码。
二 组件的使用
不管以哪种方式创建Vue组件,我们最终的目的是在HTML页面中展示出来。本节将详细介绍Vue组件使用方式。
1,组件标签
要把我们创建的Vue组件添加到页面中去,只需要把组件名当做标签来使用即可。
Vue.component('myCom',{
template:"#tem"
});
var vm = new Vue({
el:"#app"
});
//JS部分
<div id="app">
<my-com></my-com>
</div>
<!-- HTML部分 -->
小技巧:注册组件时,建议使用全小写形式命名,因为HTML标签要求使用小写字母。如果你一定要遵守小驼峰命名规则,那么你应该在使用组件时用“-”短横线把单词分隔开。
2,组件复用
Vue的组件可以重复使用。
<div id="app">
<my-com></my-com>
<my-com></my-com>
<my-com></my-com>
</div>
当然,全局组件可以在任何地方使用,而私有组件只能在实例接管元素内部使用。
组件不仅可以简单的重复使用,还可以嵌套。
var vm = new Vue({
el:'#app',
compontents:{
mycom1:{
template:'<div>组件一 <mycom2></mycom2></div>'
},
mycom2:{
template:'<div>组件二</div>'
}
}
});
3,另一种使用方式
var mycom = {
tempalte:'<div id="app2">hello</div>'
};
var vm = new Vue({
el:'#app',
render:function(createEl){
return createEl(mycom);
}
});
使用render方式渲染组件:给Vue实例添加render属性,该属性值是一个接收一个方法作为参数的函数。参数用于创建Vue组件,return该组件将替代Vue实例接管的#app元素。最终的表现是:页面上将不再出现#app的div,取而代之的是#app2的div。
这种方式一般配合单文件组件使用,如果要渲染多个组件,只需要创建多个Vue实例即可。
三 数据传递(通信)
1,props传递数据(父组件 --> 子组件)
通过在子组件绑定props属性,实现父组件向子组件传递数据。props属性值是一个数组,数组元素被定义用来接收父组件传递来的数据,然后通过v-bind指令指定数组元素接收哪些数据。子组件通过访问props数组元素就可以访问到父组件传递过来的数据了,就如同访问data里面的值。
<div id="app">
<mycom :fromFatherMsg="toSonMsg"></mycom>
</div>
<!-- HTML部分 -->
Vue.component({
template:"<div>{{fromFatherMsg}}</div>",
props:["fromFatherMsg"]
});
var vm = new Vue({
el:'#app',
data:{
toSonMsg:'这是给子组件的数据'
}
});
//JS部分
通过上面的例子,我们可以将这个过程简单的分为三步:
第一步,在子组件上添加一个数组属性props,在数组中定义用来接收数据的变量(以字符串形式存储);
第二步,使用子组件时通过v-bind指令,绑定预先定义的接收变量和父组件将要传递过来的值;
第三步,在子组件中,如同访问data中的数据一样,访问props数组元素接收到的数据。
2,$emit传递方法(父组件 --> 子组件)
父组件向子组件传递方法,是通过自定义事件来实现的。
监听(同时注册)自定义事件有两种方式:组件上使用v-on指令、实例的$on()方法。这里我们将使用第一种方式来做演示。
子组件通过实例的$emit()方法触发自定义事件,这里的事件名将成为$emit()方法的第一个参数。
<div id="app">
<mycom @fromFatherFun="toSonFun"></mycom>
</div>
<!-- HTML部分 -->
Vue.component({
template:"<div><button @click="myFun">点击执行来自父组件的方法</button></div>",
methods:{
myFun:function(){
this.$emit('fromFatherFun');
}
}
});
var vm = new Vue({
el:'#app',
methods:{
toSonFun(){
console.log( "这是给子组件的方法");
}
});
//JS部分
注意:和传递数据一样,子组件不能直接使用父组件的方法。子组件需要通过实例的$emit()方法间接执行来自父组件的方法。
这一过程也可以分为三步:
第一步,使用子组件时,通过v-on指令自定义一个事件;
第二步,绑定自定义事件和父组件需要传递的方法(指定回调函数);
第三步,通过子组件的$emit()方法(通过实参指定需要触发的自定义事件)触发父组件的方法执行;
3,子组件抛出值(子组件 --> 父组件)
子组件在通过$emit()触发自定义事件时,可以同时利用方法的第二个参数,向外抛出一个值。回调函数(上面父组件传递下来的方法)需要定义一个形参来接收这个子组件抛出的值。
//接上面的例子
Vue.component({
template:"<div><button @click="myFun">点击执行来自父组件的方法</button></div>",
data(){
return {name:'ren'};
},
methods:{
myFun:function(){
this.$emit('fromFatherFun',this.name);
}
}
});
var vm = new Vue({
el:'#app',
data:{
nameFromSon:null
}
methods:{
toSonFun(data){
this.nameFromSon = data;
},
});
子组件抛出一个值的原理和父组件给子组件传递方法原理是一样的,只不过是不同的用法而已。虽然有点绕,但有用哦。
4,获取子组件的引用
在使用子组件时,通过绑定ref属性,父组件可以通过Vue实例的$refs属性拿到子组件的引用,然后就可以直接访问子组件的属性或方法了。
<div id="app">
<mycom ref="sonCom"></mycom>
<button @click="printMsgFromSon">点击打印子组件的信息</button>
</div>
<!-- HTML部分 -->
Vue.component('mycom',{
data:function(){return {name:'ren'}}
});
var vm = new Vue({
el:'#app',
methods:{
printMsgFromSon:function(){
console.log(this.$refs.sonCom.name);
}
}
});
//JS部分
小技巧:ref属性不仅可以用在组件上,也可以用在其他标准HTML标签上,这样Vue实例就可以获取到原生的DOM对象了。
注意:即使子组件是Vue实例的私有组件,实例也不能直接使用组件的相关数据,还是需要通过$refs等属性来间接访问。
5,兄弟组件间传值
兄弟组件间实现通信也是采用自定义事件的形式。不过,这一般需要一个空的Vue实例作为中介,配合使用$on()和$emit()实现兄弟组件间的传值。
<div id="app">
<com1></com1>
<com2></com2>
</div>
<template id="com1">
<div>
<p>com1组件:{{name}}</p>
<button @click="send">将数据发送给com2</button>
</div>
</template>
<template id="com2">
<div>
<p>com2组件:{{name}}</p>
</div>
</template>
<!-- HTML部分 -->
var event = new Vue();
var vm = new Vue({
el:'#app',
components:{
com1:{
template:'#com1',
data(){
return{name:'ren'};
},
methods:{
send(){
event.$emit('sendMsg',this.name);
}
}
},
com2:{
template:'#com2',
data(){
return {name:null};
},
created(){//因为不知道什么时候会被触发,所以一般选择在生命周期钩子中监听
event.$on('sendMsg',name => {this.name = name;})
//这里需要使用箭头函数,使其内部的this指向com2
}
}
}
});
//JS部分
四 其他事项
1,单独的data
经过上面的学习,你可能已经发现了一个问题:组件中的data属性是一个函数返回的对象。
Vue.component("mycom",{
template:"",
data(){
return { //some code };
}
});
//这是ES6的写法,等同于data:function(){return {some code};}
由于data属性绑定的是一个对象,而对象是一个引用类型,为了保证为每个组件维护一份独立的数据,组件的data属性必须是一个函数。
2,插槽<slot>
当你读到这里时,你可能会有一个疑问:既然我们可以用标签形式使用Vue组件,那么是否可以在开始标签和结束标签之间填些内容呢?如果可以的话,该如何做呢?Vue的答案是肯定的。
首先请看下面的例子:
<div id="app">
<com>我是插槽内容</com>
</div>
<!-- HTML部分 -->
Vue.compenent('com',{
template:'<div><p>我是组件</p><slot>我是默认值<slot></div>'
});
var vm = new Vue({
el:'#app'
});
//JS部分
"我是插槽内容"将替换com组件中<slot>元素。
注意:如果在使用子组件时没有提供插槽值,那么<slot>元素中的默认值将会生效,前提是你已经定义了这些值。
上面的例子中,组件最终渲染的HTML结构如下:
<div>
<p>我是组件</p>
我是插槽内容
</div>
注意:插槽的内容不仅可以是文本内容,还可以是HTML代码,甚至另一个组件。
如果你需要在一个组件中定义多个插槽,那么你应该需要用到<slot>元素的name属性,来指定每个插槽应该拥有怎么样的模板。
<div>
<com>
<template v-slot:"header">
<!-- 单独的HTML模板 -->
</template>
<div><p>我是默认的模板</p></div>
<template v-slot:"footer">
<!-- 单独的HTML模板 -->
</template>
</com>
</div>
<!-- HTML部分 -->
Vue.component('com',{
tempalte:'<div><slot name="header"></slot><slot></slot><slot name="footer"></slot></div>'
});
var vm = new Vue({
el:'#app'
});
具名的插槽需要在使用组件时,用<template>元素单独定义模板,并通过v-slot指令以参数的形式指定:“我是xxx插槽的模板”。
其他所有没有包裹在<template>元素内的模板,将自动归为匿名的<slot>元素下面。
3,特殊的嵌套元素
有些 HTML 元素,诸如 <ul>、<ol>、<table> 和 <select>,对于哪些元素可以出现在其内部是有严格限制的。而有些元素,诸如 <li>、<tr> 和 <option>,只能出现在其它某些特定的元素内部。要怎样才能在这些元素中正确的渲染组件呢?幸好,Vue提供了is特性:
<table>
<tr is="mycom"></tr>
</table>
注意:如果你使用字符串定义组件模板(例如:template: '...')、或者单文件组件(.vue)、或者<script>标签(<script type="text/x-template">),那么你完全可以忽略掉这个限制。
Vue组件应用的更多相关文章
- vue组件
分享出来让思路更成熟. 首先组件是 Vue.js 最强大的功能之一. 可以减少很多的工作量,提高工作效率. 编写一个可复用性的组件,虽然官网上也有.... 编写可复用性的vue组件 具备一下的几个要求 ...
- vue组件的配置属性
vue组件的声明语法: Vue.component('component-name',{ template:'<p>段落{{prop1}} {{prop2}}</p>', da ...
- vue组件,撸第一个
实现此例您可以学到: vue-cli的基本应用 父组件如何向子组件传递值 单文件组件如何引入scss v-on和v-for的基础应用 源码下载 一.搭建vue开发环境 更换镜像到cnpmnpm ins ...
- vue组件最佳实践
看了老外的一篇关于组件开发的建议(强烈建议阅读英文原版),感觉不错翻译一下加深理解. 这篇文章制定一个统一的规则来开发你的vue程序,以至于达到一下目的. 1.让开发者和开发团队更容易发现一些事情. ...
- JS组件系列——又一款MVVM组件:Vue(二:构建自己的Vue组件)
前言:转眼距离上篇 JS组件系列——又一款MVVM组件:Vue(一:30分钟搞定前端增删改查) 已有好几个月了,今天打算将它捡起来,发现好久不用,Vue相关技术点都生疏不少.经过这几个月的时间,Vue ...
- vue组件大集合 component
vue组件分为全局组件.局部组件和父子组件,其中局部组件只能在el定义的范围内使用, 全局组件可以在随意地方使用,父子组件之间的传值问题等. Vue.extend 创建一个组件构造器 template ...
- 【Vue】详解Vue组件系统
Vue渲染的两大基础方式 new 一个Vue的实例 这个我们一般会使用在挂载根节点这一初始化操作上: new Vue({ el: '#app' }) 注册组件并使用—— 全局注册 通过Vue.comp ...
- 关于vue组件的一个小结
用vue进行开发到目前为止也有将近一年的时间了,在项目技术选型的时候隔壁组选 react的时候我们坚持使用vue作为前端的开发框架.虽然两者思想上的差异不大,但是vue的语法在代码的可读性以及后期的维 ...
- Vue组件基础用法
前面的话 组件(Component)是Vue.js最强大的功能之一.组件可以扩展HTML元素,封装可重用的代码.根据项目需求,抽象出一些组件,每个组件里包含了展现.功能和样式.每个页面,根据自己所需, ...
- Vue组件模板形式实现对象数组数据循环为树形结构
数据结构为数组中包含对象--树形结构,用Vue组件的写法实现以下的效果: 树形列表,缩进显示层级,第5级数据加底色,数据样式显色,点击展开折叠数据.本文为用Vue实现方式,另有一篇为用knockout ...
随机推荐
- NOIP模拟 20
来自liu_runda的善意 T1 周 究级难题,不可做,咕了. T2 任 他为什么总强调没环啊? 他为什么总强调没环啊? 他为什么总强调没环啊? ...... QAQ 因为他总是棵树,所以点的数量 ...
- 基于 Jenkins Pipeline 自动化部署
最近在公司推行Docker Swarm集群的过程中,需要用到Jenkins来做自动化部署,Jenkins实现自动化部署有很多种方案,可以直接在jenkins页面写Job,把一些操作和脚本都通过页面设置 ...
- MySQL系列:Windows 下 MySQL 8.X 的安装
之前一直使用的是MySQL5.7,但由于MySQL增加了一些新特性,所以选择了更新. 下载MySQL 进入MySQL官网下载地址,选择Windows (x86, 64-bit), ZIP Archiv ...
- canvas绘制工作流之绘制节点
上一篇我们介绍了canvas绘制工作流的大概步骤,接下来会有系列文章细致的介绍怎么用canvas绘制工作流:这篇文章主要介绍用canvas绘制流程节点. 绘制前我们需要先准备一张节点图片,例如::好了 ...
- day5-基本数据类型总结
一.数字int(..)二.字符串replace/find/join/strip/startswith/split/upper/lower/format tempalte = "i am {n ...
- redis集群节点重启后恢复
服务器重启后,集群报错: [root@SHH-HQ-NHS11S nhsuser]# redis-cli -c -h ip -p 7000ip:7000> set cc dd(error) CL ...
- 解决WordPress不能发邮件,WordPress 无法发送邮件
解决WordPress不能发邮件,WordPress 无法发送邮件,不得不说WordPress这个问题真的很烦人,研究了一下午发现不能发邮件的问题无非以下几种! 1.系统本身问题,这个直接装个插件即可 ...
- thinkphp 比RBAC更好的权限认证方式(Auth类认证)
Auth 类已经在ThinkPHP代码仓库中存在很久了,但是因为一直没有出过它的教程, 很少人知道它, 它其实比RBAC更方便 . RBAC是按节点进行认证的,如果要控制比节点更细的权限就有点困难了, ...
- [LC]26题 Remove Duplicates from Sorted Array (删除排序数组中的重复项)(双指针法)(原地实现)
①中文题目 给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成 ...
- 通过阿里云的IOT平台控制ESP8266
通过阿里云的IOT平台控制ESP8266 #include <ESP8266WiFi.h> /* 依赖 PubSubClient 2.4.0 */ #include <PubSubC ...