一,初始版使用Vue组件开发的三个步骤
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!--第三步使用模板-->
<cpn></cpn>
</div>
<script src="../js/vue.js"></script>
<script>
<!--第一步创建模板-->
const cpn=Vue.extend({
template:`<h1>你好</h1>`
})
<!--第二步注册模板-->
Vue.component('cpn',cpn)
const app=new Vue({
el: '#app',
data:{
msg: 'Hello Vue'
}
})
</script>
</body>
</html>
二,全局组件和局部组件
全局组件就是可以在任何Vue实例中使用的组件,是直接使Vue.component进行注册的组件,而局部组件则是在Vue实例中注册的,只能在注册的Vue实例下使用。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn></cpn>
</div>
<div id="app2">
<cpn></cpn>
</div>
<script src="../js/vue.js"></script>
<script>
/*<!--不在Vue实例中注册的组件就是全局组件,可以在多个Vue实例中使用-->*/
const cpn=Vue.extend({
template: `<h1>你好</h1>`
})
/*全局组件*/
/*Vue.component('cpn',cpn)*/
const app=new Vue({
el: '#app',
data:{
msg: 'Hello Vue'
},
<!--在Vue实例中注册的组件就是局部组件,只能在当前实例中使用-->
components: {
<!--前者为使用的标签名-->
cpn:cpn
}
})
const app2=new Vue({
el: '#app2',
data:{
msg: 'Hello Vue'
}
})
</script>
</body>
</html>
三 ,组件化开发语法糖式写法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<s1></s1>
<s2></s2>
</div>
<script src="../js/vue.js"></script>
<script>
/*全局组件语法糖写法*/
Vue.component('s1',{
template:`
<h1>我是全局组件</h1>`
})
const app=new Vue({
el: '#app',
data:{
msg: 'Hello Vue'
},
/*局部组件语法糖写法*/
components:{
's2':{
template: `<h1>我是局部组件</h1>`
}
}
})
</script>
</body>
</html>
四 ,组件化开发模板分离式写法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<te></te>
</div>
<!--第一种写法 使用script标签-->
<!--<script type="text/x-template" id="cpn">
<div>
<h1>组件分离式写法之script</h1>
</div>
</script>-->
<!--第二种使用template标签-->
<template id="cpn">
<div>
<h1>组件分离写法之template标签</h1>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
//全局式写法
/*Vue.component('te',{
template:'#cpn'
})*/
const app=new Vue({
el: '#app',
data:{
msg: 'Hello Vue'
},
//局部式写法
components: {
te:{
template: '#cpn'
}
}
})
</script>
</body>
</html>
五,为什么组件中的data是一个函数,且必须返回一个对象?
因为如果你的data不是一个函数,而是一个对象,那么你的组件在复用的时候,每次都将返回一样的数据。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<te></te>
</div>
<template id="cpn">
<div>
<h1>当前计数:{{count}}</h1>
<button @click="add">+</button>
<button @click="sub">-</button>
</div>
</template>
<!--那么为什么组件中的data是个函数,且必须返回一个对象呢
因为组件是重复使用的,如果data是一个对象,那么所有用组件的数据都是一样的
即使发生改变也是一起改变,所以data必须是个函数且返回值是个对象-->
<script src="../js/vue.js"></script>
<script>
Vue.component('te',{
template: '#cpn',
data(){
return {
count:0
}
},
methods: {
add(){
this.count++
},
sub(){
this.count--
}
}
})
const app=new Vue({
el: '#app',
data:{
msg: 'Hello Vue'
}
})
</script>
</body>
</html>
六,父组件和子组件
子组件是在父组件中注册的。在父组件中注册,就要在父组件中的模板使用才会生效。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<fa></fa>
</div>
<script src="../js/vue.js"></script>
<script>
const son=Vue.extend({
template:`<h1>子组件</h1>`
})
/*子组件在父组件注册,父组件在Vue的实例中注册,然后父组件中就可以用子组件了*/
const father=Vue.extend({
template:`<h1>父组件
//子组件在父组件模板中使用
<son></son>
</h1>`
,
components:{
son:son
}
})
const app=new Vue({
el: '#app',
data:{
msg: 'Hello Vue'
},
components: {
fa:father
}
})
</script>
</body>
</html>
七,父组件向子组件传值
子组件使用props关键字指定接收父组件数据的字段,然后在父组件的模板中使用子组件模板并且使用v-bind:绑定父组件的数据字段。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!--第二步使用bind将子组件数据和父组件数据绑定-->
<te1 :msg1="msg" :cmovies="movies"></te1>
</div>
<template id="cpn">
<h1>
<!--第三步在组件中使用子组件数据代替-->
你好,{{msg1}}
<ul>
<li v-for="item in cmovies">{{item}}</li>
</ul>
</h1>
</template>
<script src="../js/vue.js"></script>
<script>
const te={
template: '#cpn',
/*使用组件开发的第一步,指定props接收父组件的值
* props有两种形式,一种是数组,一种是对象*/
/*props:['msg1','cmovies']*/
props: {
/*使用对象方式可以指定数据类型还可以指定属性默认值*/
msg1:{
type:String,
default:'aaaa',
required: true /*使用这个的时候表示用此组件必须给这个变量设值*/
}
}
}
const app=new Vue({
el: '#app',
data:{
msg: 'Vue',
movies:['西游记','红楼梦','三国演义']
},
components: {
te1:te
}
})
</script>
</body>
</html>
八,子组件通过自定义事件传数据到父组件
首先在子组件中设定方法,并使用this.$emit(‘自定义事件名称’,数据),然后在子模板中使用 v-on:自定义事件名称=‘父组件方法名’,父组件的方法就可以自动接收到数据。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!--第三步使用自定义事件触发父组件中的方法,其中@是v-on的简写
之前都是@click,但是现在接的是自定义的事件-->
<te @fatherbtn="fabtn"></te>
</div>
<template id="cpn">
<div>
<!--子组件向父组件穿数据第一步:创建点击事件-->
<button @click="btnclick(item)" v-for="item in pro">
{{item.name}}
</button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const te={
template: '#cpn',
data(){
return {
pro: [
{'id':1,"name":'家用器具'},
{'id':2,"name":'手机电脑'},
{'id':3,"name":'智能家居'}
]
}
},
methods: {
btnclick(item){
<!--第二步,自定义事件,$emit的意思是发射,第一个参数的
是发射事件的名称,第二个参数是携带的参数-->
this.$emit('fatherbtn',item)
}
}
}
const app=new Vue({
el: '#app',
data:{
msg: 'Hello Vue',
},
components: {
te
},
methods: {
fabtn(item){
console.log('fabtn--->'+item)
}
}
})
</script>
</body>
</html>
九,父组件取子组件的值
首先在子组件的模板中加入ref属性,这个属性可以指定一个名称,例如
ref=‘aaa’,那么这个子组件在父类中就可以以this.$refs.aaa获取到。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
//子组件模板加入ref属性指定名称
<te ref="aaa"></te>
<button @click="get">按钮</button>
</div>
<template id="cpn">
<h1>我是子组件</h1>
</template>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el: '#app',
data:{
msg: 'Hello Vue'
},
methods: {
get(){
<!--父组件获取子组件的值,通过$refs获取,前提是子组件中使用了ref=""设置-->
alert(this.$refs.aaa.name);
}
},
components: {
te: {
template: '#cpn',
data(){
return {
name: 'ls'
}
}
}
}
})
</script>
</body>
</html>
十,插槽的使用
插槽就是在组件中预留一个位置在使用组件的时候可以随便在插槽的位置使用任意元素替代。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<tep></tep><!--没使用插槽-->
<tep><h1><a href="">超链接</a></h1></tep><!--使用插槽-->
</div>
<template id="tep">
<div>
<h1>hello Vue</h1>
<h1>Hello world</h1>
<slot></slot><!--设置插槽在使用的时候进行替换,不使用则只显示上面的元素-->
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el: '#app',
data:{
msg: 'Hello Vue'
},
components: {
tep: {
template: '#tep'
}
}
})
</script>
</body>
</html>
具名组件
具有名字的组件,在具有多个组件的时候,可以针对性的替换对应名字的插槽。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn>
<span slot="left">替换了左边的</span><!--替换名字为left的插槽-->
<span slot="right">替换了右边的</span><!--替换名字为right的插槽-->
</cpn>
</div>
<template id="cpn">
<!--在组件中设置带有名字的插槽,在使用组件的时候可以用名字进行替换-->
<div>
<slot name="left"><span>左边</span></slot>
<slot name="center"><span>中间</span></slot>
<slot name="right"><span>右边</span></slot>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el: '#app',
data:{
msg: 'Hello Vue'
},
components: {
cpn:{
template: '#cpn'
}
}
})
</script>
</body>
</html>
插槽还可以指定默认内容,当不想使用默认的插槽元素时,重新写一个元素即可。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn></cpn>
<cpn><a href="">超链接插槽</a></cpn>
<cpn></cpn>
</div>
<template id="cpn">
<h1>
我是组件
<slot><button>按钮</button></slot>
</h1>
<!--
插槽的使用其实就是在组件中预留一个位置,
等到使用插槽的时候可以在插槽的位置写任意标签
还可以在插槽中设置默认标签,如果不想使用默认则自己在使用组件其中添加标签-->
</template>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el: '#app',
data:{
msg: 'Hello Vue'
},
components: {
cpn :{
template:'#cpn'
}
}
})
</script>
</body>
</html>
编译作用域
所谓的编译作用域就是对应模板只能使用对应组件中的数据。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--所谓的编译作用域就是在什么模板里面那么数据都取的是所在模板的数据-->
<div id="app">
<tep v-show="isShow"></tep>
<!--此时在Vue的模板之下,
所以isShow取的是Vue里面的isShow,所以会显示-->
</div>
<template id="tep">
<div>
<h1>Hello world</h1>
<button v-show="isShow">
按钮
</button>
</div>
<!--此时在tep的模板之下,所以会取tep里面的isShow,所以不会显示-->
</template>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el: '#app',
data:{
msg: 'Hello Vue',
isShow: true
},
components: {
tep: {
template: '#tep',
data(){
return {
isShow: true
}
}
}
}
})
</script>
</body>
</html>
作用域插槽
就是针对于子组件遍历的数据样式不满意,在父组件中重新遍历并作出新样式。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--父组件中插槽想使用子组件中的数据,使用slot-scope使用指定slot对象-->
<div id="app">
<tep>
<div slot-scope="slot">
<span v-for="item in slot.data">{{item}}-</span>
</div>
</tep>
</div>
<template id="tep">
<div>
<h1>作用域插槽</h1>
<!--这个data可以随便改,但是上面对应的遍历也需要改,
data=""的值是对应要遍历的数组-->
<slot :data="fu" >
<ul>
<li v-for="item in fu">{{item}}</li>
</ul>
</slot>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el: '#app',
data:{
},
components: {
tep: {
template: '#tep',
data(){
return{
pl: ['Java','C','C++','C#','Vue'],
fu: ['apple','banane','orange','huolong']
}
}
}
}
})
</script>
</body>
</html>