组件
组件相当于一个小的Vue对象,也有Vue的生命周期。
父组件往子组件传值
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0,minimal-ui:ios">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" href="">
<script src="./Vue/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 将父组件的值传给子组件 v-bind:product="item" 将遍历出来的值 传给 子组件props中的product -->
<product-com v-for="item,index in proList" v-bind:product="item"></product-com>
</div>
</body>
<script>
Vue.component("product-com", {
template: `<li>
<h3>{{product.title}}</h3>
<h4>{{product.price}}</h4>
<p>{{product.brief}}</p>
</li>`,
props: ['product'] //相当于属性列表
})
//根组件
let app = new Vue({
el: "#app",
data: {
proList: [{
title: "产品1",
price: "10",
brief: "产品描述1"
}, {
title: "产品2",
price: "10",
brief: "产品描述2"
}, {
title: "产品3",
price: "10",
brief: "产品描述3"
}, {
title: "产品4",
price: "10",
brief: "产品描述4"
}]
}
})
</script>
</html>
子组件给父组件传值
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0,minimal-ui:ios">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" href="">
<script src="./Vue/vue.js"></script>
</head>
<body>
<div id="app">
<product-com v-for="item,index in schools" v-bind:school="item" @getschoolname="getname"></product-com>
<h2>选中的学校是:{{schoolname}}</h2>
</div>
</body>
<script>
Vue.component("product-com", {
template: `<li>
<h3>{{school}}</h3>
<button @click="schoolname(school)">学校</button>
</li>`,
props: ['school'],
methods: {
schoolname: function(schoolname1) {
console.log(schoolname1)
console.log(this)//this 中有所有的属性和方法
//通过 $emit("事件名称",参数)
//调用 v-on:事件名称="父组件的函数" 然后参数会传入父组件的函数中,然后就可以给父组件的属性赋值了
//如 @getschoolname="getname"
this.$emit("getschoolname", schoolname1)
}
}
})
//根组件
let app = new Vue({
el: "#app",
data: {
schools: ["清华", "北大"],
schoolname: ""
},
methods: {
getname: function(schoolname) {
this.schoolname = schoolname
}
}
})
</script>
</html>
第二种子组件给父组件传值
可以通过父组件给子组件传递函数对象来使子组件调用父组件的函数对象(由于this指向是固定的!)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0,minimal-ui:ios">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" href="">
<script src="./Vue/vue.js"></script>
</head>
<body>
<div id="app">
<product-com v-for="item,index in schools" v-bind:school="item" :methodobject="getname"></product-com>
<h2>选中的学校是:{{schoolname}}</h2>
</div>
</body>
<script>
Vue.component("product-com", {
template: `<li>
<h3>{{school}}</h3>
<button @click="schoolname(school)">学校</button>
</li>`,
props: ['school', 'methodobject'],
methods: {
schoolname: function(schoolname1) {
console.log(schoolname1)
console.log(this) //这边的是Vuecomponent 子组件
this.methodobject(schoolname1) //这边的this绑定的是父组件
//通过 $emit("事件名称",参数)
//调用 v-on:事件名称="父组件的函数" 然后参数会传入父组件的函数中,然后就可以给父组件的属性赋值了
//this.$emit("getschoolname", schoolname1)
}
}
})
//根组件
let app = new Vue({
el: "#app",
data: {
schools: ["清华", "北大"],
schoolname: ""
},
methods: {
getname: function(schoolname) {
console.log(this)
this.schoolname = schoolname
// console.log(this.schoolname)
}
}
})
</script>
</html>
通过子组件通过$parent属性找到父组件的Vue对象
$parent 父组件 $root 根组件 $children 子组件
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0,minimal-ui:ios">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" href="">
<script src="./Vue/vue.js"></script>
</head>
<body>
<div id="app">
<product-com v-for="item,index in schools" v-bind:school="item"></product-com>
<h2>选中的学校是:{{schoolname}}</h2>
</div>
</body>
<script>
Vue.component("product-com", {
template: `<li>
<h3>{{school}}</h3>
<button @click="schoolname(school)">学校</button>
</li>`,
props: ['school', 'methodobject'],
methods: {
schoolname: function(schoolname1) {
console.log(schoolname1)
console.log(this) //这边的是Vuecomponent 子组件
//通过父组件
this.$parent.getname(schoolname1)
}
}
})
//根组件
let app = new Vue({
el: "#app",
data: {
schools: ["清华", "北大"],
schoolname: ""
},
methods: {
getname: function(schoolname) {
console.log(this)
this.schoolname = schoolname
// console.log(this.schoolname)
}
}
})
</script>
</html>
在组件上使用 v-model
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0,minimal-ui:ios">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" href="">
<script src="./Vue/vue.js"></script>
</head>
<body>
<div id="app">
<input-com v-model="username"></input-com>
<h1>{{username}}</h1>
</div>
</body>
<script>
Vue.component("input-com", {
template: `
<input type="text" v-bind:value="value" @input="$emit('input',$event.target.value)" >
`,
props: ['value']
})
var app = new Vue({
el: "#app",
data: {
username: ""
},
methods: {
}
})
</script>
</html>
下面是官方文档
当用在组件上时,v-model
则会这样:
<custom-input
v-bind:value="searchText"
v-on:input="searchText = $event"
></custom-input>
为了让它正常工作,这个组件内的 <input>
必须:
- 将其
value
attribute 绑定到一个名叫value
的 prop 上 - 在其
input
事件被触发时,将新的值通过自定义的input
事件抛出
写成代码之后是这样的:
Vue.component('custom-input', {
props: ['value'],
template: `
<input
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
`
})
现在 v-model
就应该可以在这个组件上完美地工作起来了:
<custom-input v-model="searchText"></custom-input>
插槽
和 HTML 元素一样,我们经常需要向一个组件传递内容
新版本已经弃用了<slot></slot>
! 新版本使用 v-slot
在template模板中加入<slot></slot>
,则会将在组件标签内部的html加入到<slot></slot>
中,<slot></slot>
中只能使用父元素的属性!
例如:
和 HTML 元素一样,我们经常需要向一个组件传递内容,像这样:
<alert-box>
Something bad happened.
</alert-box>
可能会渲染出这样的东西:
Error! Something bad happened.
幸好,Vue 自定义的 <slot>
元素让这变得非常简单:
Vue.component('alert-box', {
template: `
<div class="demo-alert-box">
<strong>Error!</strong>
<slot></slot>
</div>
`
})
如你所见,我们只要在需要的地方加入插槽就行了——就这么简单!
动态组件
可以使用 <component v-bind:is="组件名" ></component>
标签来指定组件
<!DOCTYPE html>
<html>
<head>
<title>Dynamic Components Example</title>
<script src="./Vue/vue.js"></script>
<style>
.tab-button {
padding: 6px 10px;
border-top-left-radius: 3px;
border-top-right-radius: 3px;
border: 1px solid #ccc;
cursor: pointer;
background: #f0f0f0;
margin-bottom: -1px;
margin-right: -1px;
}
.tab-button:hover {
background: #e0e0e0;
}
.tab-button.active {
background: #e0e0e0;
}
.tab {
border: 1px solid #ccc;
padding: 10px;
}
</style>
</head>
<body>
<div id="dynamic-component-demo" class="demo">
<button v-for="tab in tabs" v-bind:key="tab" v-bind:class="['tab-button', { active: currentTab === tab }]" v-on:click="currentTab = tab">
{{ tab }}
</button>
//:is=“组件名” 属性 动态指定组件
<component v-bind:is="currentTabComponent" class="tab"></component>
</div>
<script>
Vue.component("tab-home", {
template: "<div>Home component</div>"
});
Vue.component("tab-posts", {
template: "<div>Posts component</div>"
});
Vue.component("tab-archive", {
template: "<div>Archive component</div>"
});
new Vue({
el: "#dynamic-component-demo",
data: {
currentTab: "Home",
tabs: ["Home", "Posts", "Archive"]
},
computed: {
currentTabComponent: function() {
return "tab-" + this.currentTab.toLowerCase();
}
}
});
</script>
</body>
</html>