<body>
<div id="app">
<hello></hello>
<world></world>
</div>
<div id="root">
<hello></hello>
<world></world>//局部注册的组件world显示不出来
</div>
<script src="/vue.js"></script>
<script>
//全局注册组件(创建组件,要在new Vue之前)
Vue.component('hello', {
//组件的模板(组件要显示的标签)
template: `
Hello
`
});
//局部注册组件
new Vue({
el: '#app',
components: {
'world': {
template: `world
`
}
}
})
new Vue({
el: '#root'
})
</script>
</body>
<body>
<div id="app">
<my-component></my-component>
</div>
<script src="/vue.js"></script>
<script>
//创建全局组件:
Vue.component('my-component',{
template:`
{{msg}}
{{newMsg}}
`,
//和之前一样data,computed等都能用
data(){
return{
msg:'你好呀'
}
},
computed:{
newMsg(){
return '我不好'
}
}
});
//为什么组件中data()只能用函数返回的形式:
//因为组件要多次使用,以保证每个组件用的data独立
//使得每个实例可以维护一份被返回对象的独立的拷贝(官方的话)
// const a = data();
// const b = data();
new Vue({
el:'#app',
})
</script>
</body>
Vue中为组件提供了一个props 的属性,在组件上注册的一些自定义属性,通过props,使得父组件向子组件传值。
注意:当父组件向子组件传递数据时,除了字符串,其他所有数据类型都需要通过v-bind 来进行传递。
<body>
<div id="app">
<father></father>
</div>
<script src="/vue.js"></script>
//父子组件的前提是有嵌套关系。 注意:局部组件不能嵌套到全局组件中。
//1.父组件传值:父组件中,给子组件设置属性,进行传值。
<script>
Vue.component('father', {
template: `
`
})
//2.子组件接收值:通过props属性,在数组或对象中设置对应的属性名,来接收父组件传递的数据。
Vue.component('child', {
props:['name','age'],
template: `
{{name}} {{age}}
`
})
new Vue({
el: '#app'
})
</script>
</body>
props 可以通过设置成对象的形式,来进行props的验证。
<body>
<div id="app">
<father></father>
<hr>
<hr>
<child></child>
</div>
<script src="/vue.js"></script>
<script>
Vue.component('father', {
template: `
father
{{msg}}
`,
data() {
return {
msg:'father msg'
}
}
})
Vue.component('child', {
props:{
name:String, //name接收的数据类型为String
age:[Number,String], //age接收的数据类型为Number或String
gender:{
type:String, //gender接收的数据类型为String
default:'男' //当没有接收到gender属性值时,采用default的默认值'男'
},
friends:{
type:Object,
default:()=>({}) //当默认值为数组或对象时,要以函数返回值的形式来设置默认值
}
},
template: `
child
{{name}} {{age}} {{gender}}
`
})
new Vue({
el: '#app'
})
</script>
</body>
@自定义名称=方法名
,来向子组件传递自定义事件。@事件类型="$emit('自定义事件名称')”
来触发父组件传递的自定义事件。<body>
<div id="app">
<father></father>
</div>
<script src="/vue.js"></script>
<script>
Vue.component('father',{
template:`
`,
methods: {
sayHello(){
console.log('hello')
}
}
})
Vue.component('child',{
template:`
child
`
})
new Vue({
el:'#app'
})
</script>
</body>
在父组件中定义一个修改父组件数据的方法,然后通过自定义事件将该方法传递给子组件,让子组件来触发该方法。
<body>
<div id="app">
<father></father>
</div>
<script src="/vue.js"></script>
<script>
Vue.component('father',{
template:`
{{num}}
`,
data() {
return {
num:100
}
},
methods: {
add(){
this.num++
}
}
})
Vue.component('child',{
template:`
`
})
new Vue({
el:'#app'
})
</script>
</body>
当子组件想要将数据传递给父组件时,通过调用父组件的方法,来进行数据的传递。
<body>
<div id="app">
<father></father>
</div>
<script src="/vue.js"></script>
<script>
Vue.component('father',{
template:`
{{num}}
`,
data() {
return {
num:100
}
},
//函数可以接收参数
methods: {
add(newNum1,newNum2){
this.num += newNum1+newNum2;
}
}
})
//$emit()的第二个参数,用来向父组件传递数据
Vue.component('child',{
template:`
`
})
new Vue({
el:'#app'
})
</script>
</body>
<body>
<div id="app">
//父组件counter中包含了两个子组件
<counter></counter>
</div>
<script src="/vue.js"></script>
<script>
//注意:组件名需要加引号
Vue.component('counter', {
template: `
//自定义属性
//自定义事件
`,
//show和set都要用数据,因此数据放在父组件身上
data() {
return {
count: ''
}
},
methods: {
// 子组件修改父组件的数据
increment() {
this.count++;
},
decrement() {
this.count--;
},
//子组件传值给父组件
inputCount(newCount) {
this.count = newCount
}
}
})
//父传子
Vue.component('show-count', {
props: {
count: {
type: [Number, String],
default: 0
}
},
template: `
计数器:{{count}}
`
})
//子传父
//@blur是当元素失去焦点时所触发的事件
Vue.component('set-count', {
template: `
//给input加了ref属性
`,
methods: {
inputCount() {
const value = this.$refs.newCount.value;
this.$emit('inputCount', value);
this.$refs.newCount.value = '';
}
},
})
new Vue({
el: '#app',
})
</script>
</body>
假设:在vue 中,需要操作DOM了,需要拿到页面上某个DOM元素的引用,此时怎么办?
答:ref引用,ref用来辅助开发者在不依赖于jQuery的情况下,获取DOM元素或组件的引用。
注意:每个vue的组件实例上,都包含一个 $refs对象,里面存储着对应的DOM元素或组件的引用。默认情况下,组件的 $refs指向一个空对象。
<style>
.done {
color: red;
text-decoration: line-through;
}
.btnsName>*{
margin-right: 10px;
}
</style>
<body>
<div id="app">
<todolist></todolist>
</div>
<script src="/vue.js"></script>
<script>
//父组件:
Vue.component('todolist', {
template: `
`,
data() {
return {
listData: [
{ text: 'HTML', done: false },
{ text: 'CSS', done: true },
{ text: 'JS', done: false },
],
current:'ALL'
}
},
computed:{
filterListData(){
switch(this.current){
case'DONE':return this.listData.filter(item=>item.done);
case'ACTIVE':return this.listData.filter(item=>!item.done);
default:return this.listData;
}
},
doneTotal(){
return this.listData.filter(item=>item.done).length;
}
},
methods: {
addTodo(text) {
this.listData.push({
text,
done: false
});
},
//单向数据流,不能修改props,不能在子组件list中用@click="item.done=!item.done"切换样式。
//因此在父组件中根据子组件传过来的下标index修改。
doneToggle(index) {
this.listData[index].done = !this.listData[index].done
},
currentToggle(current){
this.current = current;
}
}
})
Vue.component('addTo', {
data() {
return {
text: ''
}
},
template: `
`,
methods: {
addTodo() {
this.$emit('addTodo', this.text),
this.text = ''
}
}
})
Vue.component('list', {
props: {
listData: {
type: Array,
default: () => []
}
},
template: `
-
{{item.text}}
`,
})
Vue.component('btns', {
props:['current','total','doneTotal'],
data(){
return{
btnsName:['ALL','DONE','ACTIVE'],
}
},
template: `
`
})
new Vue({
el: '#app'
})
</script>
</body>
<body>
<div id="app">
<h1>{{msg}}</h1>
<button @click="msg='我不好'">按钮</button>
<button @click="$destroy()">销毁</button>
</div>
<script src="/vue.js"></script>
//created,mounted:页面初始化时向服务端发起请求。
<script>
new Vue({
el: "#app",
data() {
return {
msg: "你好"
}
},
beforeCreate() {
console.log('创建前');
},
created() {
console.log('创建完成');
},
beforeMount() {
console.log('挂载前');
},
mounted() {
console.log('挂载完成');
},
beforeUpdate() {
console.log('数据更新前');
},
updated() {
console.log('数据更新完成');
},
beforeDestroy() {
console.log('销毁前');
},
destroyed() {
console.log('销毁完成');
}
})
</script>
</body>
//知识点:
1.插槽的内容:从组件外部向组件内部的插槽添加内容。
2.插槽的默认值:当没有给插槽传递数据时,默认插槽内容为空,给插槽手动设置默认值,页面就显示插槽的默认值。
3.具名插槽:一个组件中,有多个插槽时,可以通过name属性给插槽设置名字。
<body>
<div id="app">
<cpn>
//具名插槽的v-slot只能写在template中
<template v-slot:header>
<h3>插槽的内容</h3>
</template>
<template v-slot:footer>
//没有给插槽传递内容,显示插槽的默认值
</template>
</cpn>
</div>
<script src="/vue.js"></script>
<script>
Vue.component('cpn', {
template:`
文章一
文章二
文章三
插槽的默认值
`
})
new Vue({
el: '#app'
})
</script>
</body>
当插槽中渲染的数据由插槽所在的子组件提供,而插槽显示的标签由父组件提供,这种情况下就需要用到作用域插槽。
//用无序列表和有序列表渲染学生列表students
<body>
<div id="app">
<father></father>
</div>
<script src="/vue.js"></script>
<script>
Vue.component('father', {
template:`
- {{item}}
- {{item}}
`
});
Vue.component('child', {
data(){
return{
students:['张三','李四','王五']
}
},
template:`
学生列表
`
})
new Vue({
el: '#app'
})
</script>
</body>
案例:
<body>
<div id="app">
<tabs></tabs>
</div>
<script src="/vue.js"></script>
<script>
Vue.component('tabs',{
data() {
return {
current:'Home'
}
},
//标签:切换组件不会重新渲染
template:`
`
})
Vue.component('Home',{
template:`
Home的组件内容
`
})
Vue.component('About',{
template:`
About的组件内容
`
})
Vue.component('Posts',{
template:`
Posts的组件内容
`
})
new Vue({
el:'#app'
})
</script>
</body>