Vue——组件的创建
16-组件的创建(注:Vue的自定义事件中的变量不能用驼峰体)
vue的核心基础就是组件的使用,玩好了组件才能将前面学的基础更好的运用起来。组件的使用更使我们的项目解耦合。更加符合vue的设计思想MVVM。
那接下来就跟我看一下如何在一个Vue实例中使用组件吧!
这里有一个Vue组件的示例:
Vue.component('Vheader',{ data:function(){ return { } }, template:`<div class="header"> <div class="w"> <div class="w-l"> <img src="./logo.png"/> </div> <div class="w-r"> <button>登录</button><button>注册</button> </div> </div> </div>` })
组件是可复用的Vue实例,并且带有一个名字:在这个例子中是 <Vheader>
。我们可以在一个通过 new Vue
创建的 Vue 根实例中,把这个组件作为自定义元素来使用:
<div id="app"> <Vheader></Vheader> </div>
var app = new Vue({ el:'#app', data:{ } })
效果显示:
因为组件是可复用的 Vue 实例,所以它们与 new Vue
接收相同的选项
全局组件
代码示例:
一个关于弹一弹的代码实例<!DOCTYPE html><html lang="en">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="D:\VsCode_projectsfiles\vue_file\inputfiles\vue.js"></script> </head> <body> <div id = 'app'>
// 使用组件 <tan></tan> </div> <script> //定义一个全局组件 Vue.component('tan',{ template:`<button v-on:click='jumpOut'>弹出靓白肌肤</button>`, methods:{ jumpOut:function(){ alert(666); } } }) var vm = new Vue({ el:"#app", }) </script> </body> </html>
组件的复用
<div id="app"> <Vheader></Vheader> <br> <Vheader></Vheader> <br> <Vheader></Vheader> </div>
效果显示:
给Vheader组件中添加一个按钮,绑定数据属性count,然后你会发现点击按钮时,每个组件都会各自独立维护它的 count
。因为你每用一次组件,就会有一个它的新实例被创建。
在创建组件过程中第一个参数是组件的名字,第二个参数是跟new Vue实例一样的options。跟实例对象不同的是有两点:
关于组件名的起名:https://cn.vuejs.org/v2/guide/components-registration.html
1、组件中没有el,因为el仅仅的是绑定Vue的根元素。
2、data属性不再是返回对象,而是返回一个函数。而且必须返回一个函数。
注册自定义组件
代码如下:
注册一个自定义的全局组件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src = '../../inputfiles/vue.js'></script> </head> <body> <div id = 'app'> <tan></tan> <tan></tan> <tan></tan> <tan></tan> <tan></tan> <tan></tan> </div> <script> //注册一个自定义组件 Vue.component('tan',{ template:`<button v-on:click='jump'>弹奏鱼尾纹{{count}}</button>`, //这里的data必须是一个方法,每次调用一个注册好的组件时,都会触发一个data方法 data:function(){ return { count:0 } }, methods:{ jump:function(){ this.count += 1 } } }) var vm = new Vue({ el:"#app", data:{}, }) </script> </body> </html>
ok。介绍到这里相信大家都明白了组件的创建了。
那么通常一个应用会一颗嵌套的组件🌲的形式来组织。
例如,你可能会有页头、侧边栏、内容区等组件,每个组件又包含了其它的像导航链接、博文之类的组件
如果说就拿上面那个导航的例子,我们把整个Vheader组件看作是全局注册的组件。
不管怎样,比如有A、B、C三个全局注册的组件。
如果我们使用webpack这样的构建系统,它会扫描我们整个文件。大家会发现全局注册的组件意味着哪怕是你不想去使用了,webpack仍然很卖力的将这些组件构建在结果中。这会造成用户下载JavaScript的无谓的增加。
到此我们仅仅的是通过Vue.component
实现全局注册的组件,那么局部组件又是如何玩的呢?
注册局部组件
代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="../../inputfiles/vue.js"></script>
</head>
<body>
<div id="app">
<tan></tan>
<tan></tan>
<tan></tan>
<tan></tan>
<tan></tan>
</div>
<script>
// 注册一个局部组件
const tanComponent=({
template:`<button v-on:click='jump'>跳一跳{{count}}</button>`,
data:function(){
return {
count:0
}
},
methods:{
jump:function(){
this.count += 1;
}
}
})
var vm=new Vue({
el:'#app',
data:{},
methods:{},
components:{
tan:tanComponent
}
})
</script>
</body>
</html>
当然,我们也可以使用JavaScript对象来定义组件:
var A = {/*......*/}; var B = {/*......*/}; var C = {/*......*/};
然后在compoents选项中定义你想要使用的组件:
new Vue({ el: '#app' components: { A B } })
在对象中放一个类似A
的变量名其实是A:A
的缩写,即这个变量名同时是:
- 用在模板中的自定义元素的名称
- 包含了这个组件选项的变量名
父组件向子组件传值
示例一:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="../../inputfiles/vue.js"></script> </head> <body> <div id="app"> // 通过在外围定义的"name"的值绑定给template中的“name"(下面加引号的时外部的name值) <tan v-bind:name="name"></tan> </div> <script> // 注册一个局部组件 const tanComponent={ template:`<button v-on:click='jump'>{{name}}{{count}}</button>`, data:function(){ return { count:0 } }, // 父组件向子组件传值/外面向里面传值 必须定义props的属性 props:{ name:String }, methods:{ jump:function(){ this.count += 1 } } } var vm=new Vue({ el:"#app", data:{ name:"弹指一挥间" }, methods:{}, components:{ tan:tanComponent } }) </script> </body> </html>
配上一张图:
示例二:
通过Prop像子组件传递数据
上面咱们看到了我们做的导航栏。如果你不能向这个组件传递某一篇博文的标题或内容之类的我们想展示的数据的话,它是没有办法使用的。这也正是 prop 的由来。
Prop 是你可以在组件上注册的一些自定义特性。当一个值传递给一个 prop 特性的时候,它就变成了那个组件实例的一个属性。为了给导航栏传递一个标题
Vue.component('Vheader',{ data:function(){ return { count:0 } }, props:['title'], template:`<div class="header"> <div class="w"> <div class="w-l"> <img src="./logo.png"/> <span>{{title}}</span> </div> <div class="w-r"> <button>登录</button><button>注册</button> </div> </div> </div>` })
<div id="app"> <Vheader title='路飞学城'></Vheader> </div>
另外我们还可以使用 v-bind
来动态传递 prop。
单个根元素
可能有很多同学在写代码的时候往往会在组件中这样去写:
<h3>{{ title }}</h3> <div v-html="content"></div>
然而如果你在模板中尝试这样写,Vue 会显示一个错误,并解释道 every component must have a single root element (每个组件必须只有一个根元素)。你可以将模板的内容包裹在一个父元素内,来修复这个问题,例如:
<div> <h3>{{ title }}</h3> <div v-html="content"></div> </div>
这里面有提到了v-html:双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用 v-html
指令。
通过事件向父组件传递数据
示例一:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="../../inputfiles/vue.js"></script> </head> <body> <div id="app"> <p>总消费量:{{totalCount}}</p> <tan v-bind:name="name" v-on:tank='add'></tan> </div> <script> const tanComponent={ template:`<button v-on:click='jump'>{{name}}{{count}}</button>`, data:function(){ return { count:0 } }, props:{ name:String }, methods:{ jump:function(){ this.count += 1 this.$emit('tank') }, } } var vm=new Vue({ el:"#app", data:{ totalCount:0, name:"古剑奇谭", }, components:{ tan:tanComponent }, methods:{ add:function(){ console.log(this.totalCount) this.totalCount += 1; } } }) </script> </body> </html>
示例二:
看个例子,比如现在我想点击导航的某个按钮,想让导航上的字体变大。那么我们需要:
在其父组件中,可以通过添加一个postFontsize数据属性来支持此功能。
var app = new Vue({ el:'#app', data:{ postFontSize:16 }, methods:{ clickHandler(){ this.postFontSize ++; } } })
它可以在模板中用来控制所有导航栏上文字的字号。
<Vheader title='路飞学城' :style="{ fontSize: postFontSize + 'px' }"></Vheader>
现在给导航栏上添加一个按钮来放大字号:
<div class="w-r"> <button>登录</button><button>注册</button><button>放大文字</button> </div>
然后再让添加的按钮干活!
<button @click='largeHandler'>放大标题</button>
methods:{ largeHandler(){ this.$emit('luffy-title-size') } }
然后我们可以用 v-on
在导航栏组件上监听这个事件,就像监听一个原生 DOM 事件一样:
<Vheader title='路飞学城' @luffy-title-size='clickHandler(res)' :style="{ fontSize: postFontSize + 'px' }"></Vheader>
另外我们还可以使用时间抛出一个值:
在导航栏组件中:
methods:{ largeHandler(){ this.$emit('luffy-title-size',1) } }
在父组件中:
methods:{ clickHandler(size){ this.postFontSize +=size; } }
此时这个size就是导航栏组件传过来的数值1.
关于组件的注意事项及补充:
(1)关于组件的替换
如果如图:替换的标签是内层标签,需要依赖外层标签,那么就需要用这种方式再定义 is="组建名称"来正常使用该标签。
(2)关于子组件触发原生事件:
在子组件中触发父组件中的方法:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="../../inputfiles/vue.js"></script> </head> <body> <div id = "app"> <tao v-on:click.native='taozou'></tao> </div> <script> var vm=new Vue({ el:"#app", data:{}, methods:{ taozou:function(){ alert("哈哈哈,成功逃课!!!") } }, components:{ tao:{ template:`<button>哈哈哈,逃课喽</button>` }, }, }) </script> </body> </html>
好的,同学们,介绍完组件的基本使用、组件注册、父子组件传值,那么vue的基础内容就给大家介绍完了。
那么,接下来我们就得听官网的话,学完了基础,我们就开始使用vue-cli这些脚手架工具来一键搭建我们的项目。