一:组件
全局组件
组件使用的规则:创建组件,引用组件,使用组件
创建组件
调用Vue.extend()方法 创建组件构造器
调用Vue.component()方法 ,祖册组件
在Vue实例的范围内使用组件
<body>
<div id="app">
<test-comp></test-comp>
</div>
<script>
//创建组件
//返回一个构造函数
var comp = Vue.extend({//选项对象,对组件进行描述
template:`<div>hello</div>`
});
//全局注册组件
Vue.component('test-comp',comp)
//使用组件
new Vue({
el:"#app"
})
</script>
</body>
<body>
<div id="app">
<test-comp></test-comp>
</div>
<script type="text/x-template" id="temp">
<div>hello</div>
</script>
//或者直接用html的原生模板 template
<template id="temp">
<div>hello</div>
</template>
<script>
//模板的内容多的时候 定义在 外部
var comp = Vue.extend({//选项对象,对组件进行描述
template:"#temp"
});
//全局注册组件
Vue.component('test-comp',comp)//可以直接写成下面的格式
//可以直接写成 自动调用 vue.extend()
Vue.component('test-comp',{
template:"#temp"
})
//使用组件
new Vue({
el:"#app"
})
</script>
</body>
局部组件
<body>
<div id="app">
<test-comp></test-comp>
</div>
<script>
//局部组件 只能用在 这个实例的范围的模板中
new Vue({
id:"#app",
components:{
'test-comp':{
template:"<div>我是局部组件,只能用在app中 </div>"
}
}
})
</script>
</body>
总结:
1:每个组件的选项对象没有el
2:data不同,每个组件的选项对象的data是一个工厂函数,返回一个对象
多个组件的title不能共用同一个对象,每次调用 data函数,都会返回一个新的对象
<body>
<div id="app">
<test-comp></test-comp>
</div>
<template id="temp">
<p>{{title}}</p>
</template>
<script>
Vue.component("test-comp",{
data(){
return {
title:"你好"
}
},
template:"#temp"
})
new Vue({
el:"#app"
})
</script>
</body>
二:props 父组件--->子组件 传参
<body>
<div id="app">
<test-comp :title='news.title' :list='news.list'></test-comp>
//组件是公用的 ,通过props传递不同的参数
<test-comp :title='yule.title' :list='yule.list'></test-comp>
</div>
<template id="temp">
<div>
<h2>{{title}}</h2>
<ul>
<li v-for="item in list">{{item}}</li>
</ul>
</div>
</template>
<script type="text/javascript">
// props 传递参数 父组件-->子组件 使用子组件标签时写在行间
// :key = "数据" key是子组件规定
Vue.component('test-comp',{
props:['title','list'],//接收父组件传过来的参数 props属性 都会放在当前组件的实例上
template:'temp'
})
var news = {
title:"新闻",
list:["新闻1","新闻2"]
}
var list = {
title:"娱乐",
list:["娱乐1","娱乐2"]
}
new Vue({
el:"#app",
data:{
news,
yule
}
})
</script>
</body>
props验证
<body>
<div id="app">
<test-comp :title='news.title' :list='news.list'></test-comp>
//组件是公用的 ,通过props传递不同的参数
<test-comp :title='yule.title' :list='yule.list'></test-comp>
</div>
<template id="temp">
<div>
<h2>{{title}}</h2>
<ul>
<li v-for="item in list">{{item}}</li>
</ul>
</div>
</template>
<script type="text/javascript">
// props 传递参数 父组件-->子组件 使用子组件标签时写在行间
// :key = "数据" key是子组件规定
Vue.component('test-comp',{
//props:['title','list'],//props属性 都会放在当前组件的实例上
//props验证
props:{
title:{
type:String,
default:'这是标题'
},
list:{
type:Array,
required:true,
//数组/对象不填时给的默认值不能直接写成下面的
// default:[]
//写成工厂函数,把对象返回回去
default(){
return []
}
}
}
template:'temp'
})
var news = {
title:"新闻",
list:["新闻1","新闻2"]
}
var list = {
title:"娱乐",
list:["娱乐1","娱乐2"]
}
new Vue({
el:"#app",
data:{
news,
yule
}
})
</script>
</body>
修改prop传过来的某个值 不能直接修改props,可以修改自己内部属性data的值 ,把父级传过来的数据,作为data 的初始值
<body>
<div id="app">
<test-comp :title='news.title' ></test-comp>
//组件是公用的 ,通过props传递不同的参数
<test-comp :title='yule.title' ></test-comp>
</div>
<template id="temp">
<div>
<h2>{{title}}</h2>
<button @click="changeTitle">改变title</button>
</div>
</template>
<script type="text/javascript">
// props 传递参数 父组件-->子组件 使用子组件标签时写在行间
// :key = "数据" key是子组件规定
Vue.component('test-comp',{
//内部不能直接修改外部传过来的 props值,可以改变自己data中的值
props:{
title:{
type:String,
default:'这是标题'
},
list:{
type:Array,
required:true,
default(){
return []
}
}
},
data(){//这变可以改变,把父级传过来的数据,作为自己组件状态得初始值
myTitel = this.title
}
template:'temp',
methods:{
changeTitle:(){
this.myTitel = '我是自己组件的初始值,我可以改变了'
}
}
})
var news = {
title:"新闻",
list:["新闻1","新闻2"]
}
var list = {
title:"娱乐",
list:["娱乐1","娱乐2"]
}
new Vue({
el:"#app",
data:{
news,
yule
}
})
</script>
</body>
$emit 子组件发布事件,通知父组件 $emit("事件名","参数")
<body>
<div id="app">
//@change父组件监听
<test-comp :title='news.title' @change="changeHandle"></test-comp>
</div>
<template id="temp">
<div>
<h2>{{title}}</h2>
<button @click="changeTitle">改变title</button>
</div>
</template>
<script type="text/javascript">
Vue.component('test-comp',{
// $emit()发布事件 通知父组件
props:{
title:{
type:String,
default:'这是标题'
}
},
template:'temp',
methods:{
changeTitle(){
//子组件发布事件,change 自定义事件名,第二个参数,是传给父组件监听触发额方法的参数
this.$emit("change","传递的参数")
}
}
})
var news = {
title:"新闻",
list:["新闻1","新闻2"]
}
var list = {
title:"娱乐",
list:["娱乐1","娱乐2"]
}
new Vue({
el:"#app",
data:{
news,
yule
},
methods:{
changeHandle(title){
this.news.title = title
}
}
})
</script>
</body>
平行组件通信 event-bus var eventBus = new Vue();
缺点 :每个组件都能发布事件,会导致多个组件操作同一个属性
<body>
<div id="app">
<test1 @change="changeTest2"></test1>
<test2 :title="title"></test2>
</div>
<script type="text/javascript">
Vue.component('test1',{
template:`
<div>
<h2>我是标题1</h2>
<button @click="changeTitle">改变title</button>
</div>
`,
methods:{
changeTitle(){
this.$emit("change","我来自test1")
}
}
})
Vue.component('test2',{
props:['title']
template:`
<div>
<h2>我是标题2</h2>
<p>{{title}}</p>
</div>
`
})
new Vue({
el:"#app",
data:{
title:"给test2"
},
methods:{
changeTest2(title){
this.title = title
}
}
})
</script>
</body>
<body>
<div id="app">
<test1></test1>
<test2 :title="title"></test2>
</div>
<script type="text/javascript">
Vue.component('test1',{
template:`
<div>
<h2>我是标题1</h2>
<button @click="changeTitle">改变title</button>
</div>
`,
methods:{
changeTitle(){
//this.$emit("change","我来自test1")
root.$emit("change","我来自test1")
}
}
})
Vue.component('test2',{
props:['title']
template:`
<div>
<h2>我是标题2</h2>
<p>{{title}}</p>
</div>
`
})
let root = new Vue({
el:"#app",
data:{
title:"给test2"
}
})
//不需要再在父组件监听change了
root.$on('change',function(title){
this.title = title
})
</script>
</body>
slot :订制html
<body>
<div id="app">
<modal>
<p slot="content">我要出入新的内容</p>
<input slot="footer" type="button" />
</modal>
</div>
<template id="temp">
<div class="modal">
<h2>这是标题</2>
//订制 对应 slot="content"
<slot name="content">
<div class="content">
<p>内容</p>
</div>
</slot>
//对这边订制 slot="footer"
<slot name="footer">
<div class="footer">
<button>确定</button>
</div>
</slot>
</div>
<template>
<script type="text/javascript">
//对组件进行内容的订制 slot
Vue.component('modal',{
template:'#temp'
})
new Vue({
el:'#app'
})
</script>
</body>
双向数据绑定
1:.sync
<body>
<div id="#app">
<p>父组件:{{title}}</p>
<hr/>
//双向数据绑定
<custom :title.sync='title'></custom>
// 内部实现如下,此时要改变title需要发布事件
<custom @update:title='title'></custom>
</div>
<script>
Vue.component('custom',{
props:['title']
template:`
<div>
<p>{{title}}</p>
<button @click='changeTitle'>改变title</button>
</div>
`,
methods:{
changeTitle(){
//任然要发布一个是事件 此时是 update事件
this.$emit('update:title','子组件修改了值')
}
}
})
new Vue({
el:'#app',
data:{
title:'这是父组件的标题'
}
})
</script>
</body>
2: v-model
<body>
<div id="#app">
<input type='text' v-model='title' />
{{title}}
//本质上实现 v-model语法糖
//<input type='text' :vlue='title' @input='title=$event.target.value'/>
//v-model 在组件上的应用
<custom v-model='title'></custom>
// 本质上的实现
<custom :vlue='title' @input='title=$event.target.value'>
</custom>
</div>
<script>
Vue.component('custom',{
props:['value'] //此时传递的参数是value 因为父组件绑定 的是value
template:`
<div>
<p>{{value}}</p>//使用是也是 value
<button @click='changeTitle'>改变title</button>
</div>
`,
methods:{
changeTitle(){
//任然要发布一个是事件 此时是 input 事件
this.$emit('input','子组件修改了值')
}
}
})
new Vue({
el:'#app',
data:{
title:'这是父组件的标题'
}
})
</script>
</body>