Vue.js学习笔记 02、Vue组件篇笔记(上)
@[toc]
前言
本篇博客是在学习技术胖-Vue3.x从零开始学-第一季 基础语法篇过程中记录整理的笔记,若文章中出现相关问题,请指出!
- 当前该链接失效了,有需要的小伙伴可以去b站或者技术胖官网去找相应的视频与笔记。
所有博客文件目录索引:博客目录索引(持续更新)
一、全局组件
子组件应用
<body>
<div id="app"></div>
</body>
<script>
//根组件(全局组件)
const app = Vue.createApp({
//直接应用两个自组件
template: `
<website />
<describe />
`
});
//子组件
app.component('website', {
template: ` <h2>JSPang.com</h2>`
})
app.component('describe', {
template: ` <h2>技术胖的博客</h2>`
})
app.mount("#app");
</script>
组件优点:组件的可复用性
优点:组件与组件之间互不干扰,相互独立。
<body>
<div id="app"></div>
</body>
<script>
//根组件
const app = Vue.createApp({
//复用多个组件
template: `
<m-count />
<m-count />
<m-count />
`
});
//子组件(全局组件)
app.component('m-count', {
data() {
return {
count: 0
}
},
methods: {
addFun() {
this.count++;
}
},
template: `
<sapn>{{count}}</sapn>
<button @click="addFun()">增加</button>
<br/>
`
})
app.mount("#app");
</script>
全局组件缺点描述
一旦定义了,就会占用系统资源,它是一直存在的,你在任何地方都可以使用这个全局组件,对性能产生影响。
全局组件(通过vue实例调用component()
)的概括:只要定义了,处处可以使用,性能不高,但是使用起来简单。
二、局部组件
创建与注册局部组件(认识components属性)
创建局部组件:直接使用一个对象{}来表示。
注册局部组件:需要配合传入到components对象属性中。
示例:
<body>
<div id="app"></div>
</body>
<script>
//1、创建局部组件:直接在一个对象中设置参数
const counter = {
data() {
return {
count: 0
}
},
template: `<div>{{count}}<button @click="count++">增加1</button></div>`
};
const app = Vue.createApp({
//2、注册局部组件,其完整写法:components: { counter:counter },前面一个是设置的别名,后一个是实际局部组件名称
//下面我演示别名的写法,若是不使用别名使用components: { counter }即可!!!
components: { changlu: counter },
template: `
<h2>JSPang.com</h2>
<changlu />
`
});
const vm = app.mount("#app")
</script>
局部组件的默认规定(组件名称首字母全都大写)
对于组件的名称采用全部首字母大写(驼峰命名法),示例如下:
const XieDaJiao = {
template: `<h2>谢大脚</h2>`
}
三、父子组件的传值(静态、动态)
父子组件的传值,包括静态传值和动态传值。
3.1、静态传值(name=“技小胖”)
静态传值
核心:直接在标签中使用name="技小胖"
,该种方式vue会进行自动解析并传入到props数组中。
<body>
<div id="app"></div>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.0.2/vue.global.js"></script>
<script>
const app = Vue.createApp({
//1、通过属性name传入到子组件中
template: `
<h2>JSPang.com</h2>
<Son name="技小胖" />
`
});
app.component('Son', {
//2、通过使用props数组形式根将值接收到name属性里
props: ['name'],
template: `<div>{{name}} div </div>`
})
const vm = app.mount("#app");
</script>
效果:动态传值使用props
属性接收后,对应的标签中不会有该键值了!
3.2、动态传值(v-bind:xx="xx"配合子组件中的props数组接收)
动态传递值
动态传值
将这个可改变的动态值放置在data
对象里,之后使用v-bind动态从data对象中找到属性值并赋值给指定属性:
<body>
<div id="app"></div>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.0.2/vue.global.js"></script>
<script>
const app = Vue.createApp({
data() {
return {
//在data对象中包含一个可修改的属性值(动态的)
name: "cl"
}
},
//1、绑定data对象中的name值也就是cl赋值到name参数并传递到全局组件中
template: `
<h2>JSPang.com</h2>
<Son v-bind:name="name" />
`
})
app.component('Son', {
//2、同样使用name属性来进行接收这个属性值
props: ['name'],
template: `
<h2>JSPang.com</h2>
<div>{{name}}</div>
`
})
const vm = app.mount("#app");
</script>
注意点:静态传值一定传的是字符串string,而动态传值是根据data对象中的属性来决定!!!
动态传递函数
动态传递函数:本质与上面传递值相同,都是传递的data对象里的值。
示例:
<body>
<div id="app"></div>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.0.2/vue.global.js"></script>
<script>
const app = Vue.createApp({
data() {
return {
appFun: () => alert("我是根组件的appFun()方法")
}
},
//1、还是老样子,编写v-bind:appFun = "appFun"来绑定对应data对象中的属性进行动态传函数
template: `
<h2>JSPang.com</h2>
<Son :appFun="appFun" />
`
})
app.component('Son', {
//2、接收该函数
props: ['appFun'],
methods: {
divClick() {
//3、调用传入进行的函数
this.appFun();
}
},
//为标签添加点击事件来间接调用动态传入的父组件的函数
template: `
<h2>JSPang.com</h2>
<div @click="divClick()">点我试试</div>
`
})
const vm = app.mount("#app");
</script>
3.3、三种校验方式
①类型校验(props需要写成{}形式)
此时props需要写成{}形式,key为得到的数据,value表示需要校验的值:这种方式只是会在console中报出黄色警告信息,依旧还是将值传递过来的!
- Vue支持的校验类型包括:String、Boolean、Array、Object、Function和Symbol。
效果:仅仅有警告信息,传递依旧会执行。
app.component('Son', {
//校验name是否为string类型
props: {
name: String
},
template: `<div>{{name}} div </div>`
})
②必填校验与默认值设置(required与default)
required
required
(布尔值true,false):必须传递参数,若是设置了类型参数就必须要校验指定传递的类型。
效果:会报黄色警告信息,传递空值也就是阻止传递,程序也会依旧运行!
注意:与default同时存在时,default失效!
示例:
const app = Vue.createApp({
data() {
return {
name: 123
}
},
//进行传递值,只是传递的是number类型
template: `
<h2>JSPang.com</h2>
<Son :name="name"/>
`
})
app.component('Son', {
//包含requred属性进行校验是否为String类型,不是就会阻止传递进来
props: {
name: {
type: String,
// required: false
default: 'i am changlu'
}
},
template: `<div>{{name}} div </div>`
})
default
default
(默认值):没有传递指定参数会设置默认值给指定参数。
效果:当没有传递过来指定值时,就会使用默认参数(没有required情况下)。
示例:
const app = Vue.createApp({
data() {
return {
name: 123
}
},
//没有进行传递值
template: `
<h2>JSPang.com</h2>
<Son />
`
})
app.component('Son', {
//由于name没有接受到传递值并且没有required,就会使用default默认值
props: {
name: {
type: String,
default: 'i am changlu'
}
},
template: `<div>{{name}} div </div>`
})
③精准校验(validator)
validator
:精准校验是一个函数:通过布尔类型返回值来表示校验失败还是通过。
- true:表示通过校验。
- false:表示没有通过校验,仅仅在console上报警告信息,传值同样成功!
示例:
<body>
<div id="app"></div>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.0.2/vue.global.js"></script>
<script>
const app = Vue.createApp({
data() {
return {
name: 'xxxSPan'
}
},
template: `
<h2>JSPang.com</h2>
<Son :name="name"/>
`
})
app.component('Son', {
props: {
name: {
type: String,
//validator属性是一个函数用于进行简单校验,根据返回值来表示是否通过
//与default不会有任何联系,记住default只是没有传递值的时候进行设置默认值的
validator: function (value) {
console.log(value.search("JSPang"))
return value.search("JSPang") != -1
},
default: 'JSPang.com'
}
},
template: `<div>{{name}} div </div>`
})
const vm = app.mount("#app")
</script>
四、单项数据流
4.1、父子组件传递属性补充
①以对象形式传递多个参数
之前仅仅学习了单个值单个值传递,若是参数有多个在父组件标签中需要写大量的绑定传值,造成冗余。
效果:将要传递的多个参数封装到一个对象中传递即可!
示例:
<body>
<div id="app">
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.0.2/vue.global.js"></script>
<script>
const app = Vue.createApp({
data() {
return {
//1、将多个参数绑定至一个对象
params: {
content: 'xxx内容',
a: 'a',
b: 'b'
}
}
},
//2、使用v-bind='xx',来绑定某个对象进行传值
template: `
<exerTab v-bind="params" />
`
});
app.component('exerTab', {
//3、可直接使用对象内部的属性名来接收
props: ['content', 'a', 'b'],
template: `
<span>{{ content }}-{{ a }}-{{ b }}</span>
`
});
app.mount("#app");
</script>
</body>
②xx-xx=’'传递,props中xxXx接收
静态传递带有-号的属性:content-aa='xxx内容'
,需要使用props: ['contentAa']
接收。
content-aa
=>contentAa
,去掉-,并且之后字母大写拼接来接收!
示例:
<body>
<div id="app">
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.0.2/vue.global.js"></script>
<script>
const app = Vue.createApp({
//1、传递带有-的参数:content-aa
template: `
<exerTab content-aa='xxx内容' />
`
});
app.component('exerTab', {
//2、对应该类参数props接收,需要去掉-以及其后大写:contentAa
props: ['contentAa'],
template: `
<span>{{ contentAa }}</span>
`
});
app.mount("#app");
</script>
</body>
4.2、认识单项数据流
单项数据流
:子组件可以使用父组件传递过来的数据,但是决定不能修改传递过来的数据!(可以想成调用函数时传递过来的是基本类型,而非地址引用传递)
效果:若是在子组件中修改父组件传递过来的值时就会报出warning提示并且会阻止修改该值!
<body>
<div id="app"></div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.0.2/vue.global.js"></script>
<script>
const app = Vue.createApp({
data() {
return {
content: '父组件中的content'
}
},
template: `
<exerTab :content='content' />
`
});
app.component('exerTab', {
props: ['content'],
methods: {
modifyContent() {
this.content = '子组件修改了content';
}
},
//绑定单击事件来尝试修改
template: `
<span @click="modifyContent()">{{ content }}</span>
`
});
app.mount("#app");
</script>
</body>
4.3、解决方案:实现在子组件中修改父组件传递过来的参数
方案:通过在data对象中设置一个新属性来接收传递来的参数,之后对该新属性进行赋值修改也能够达成目的!
示例:
<body>
<div id="app"></div>
</body>
<script>
const app = Vue.createApp({
data() {
return {
count: 0
}
},
template: `
<div>
<changlu :count="count"/>
</div>
`
});
app.component('changlu', {
props: ['count'],
data() {
return {
//1、创建一个属性来进行代替count
mycount: this.count
}
},
methods: {
//2、对新创建的属性进行赋值操作
handlerClick() {
this.mycount++;
}
},
template: `
<span @click="handlerClick()">{{mycount}}</span>
`
});
app.mount("#app");
</script>
4.4、设计单向数据流原因
核心:通过父组件传递到子组件中的data对象里的值不能够随意更改否则就会影响到其他复用的组件了!!!
五、No-Props属性
5.1、不使用props传递时效果(默认会继承到子组件中,仅仅是单标签情况)
简而言之:就是不使用props属性来接收的属性!
<body>
<div id="app"></div>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.0.2/vue.global.js"></script>
<script>
const app = Vue.createApp({
data() {
return {
count: 0
}
},
template: `
<div>
<changlu msg="hello,cl!"/>
</div>
`
});
app.component('changlu', {
//若是不使用props接收默认就会放置在template的标签中
template: `
<span>changlu组件</span>
`
});
app.mount("#app");
</script>
效果:可以看到对应的键值对继承到了子组件标签中。若是不想让键值对继承到子组件上,可以在组件对象中添加如下属性:
inheritAttrs: false
5.2、认识$attrs
若是不使用props属性接收且template模板有多个标签:不会生效
若此时有个需求就是让某个标签具有对应的属性:此时就使用到了$attrs
对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5AmAOaDB-1652144855684)(C:\Users\93997\AppData\Roaming\Typora\typora-user-images\image-20210708223102983.png)]
实际应用$attrs
this.$attrs
:一个代理对象,其中包含了所有父组件传递子组件时的键值对中,可以从这里获取!
示例:
<body>
<div id="app"></div>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.0.2/vue.global.js"></script>
<script>
const app = Vue.createApp({
data() {
return {
count: 0
}
},
template: `
<div>
<changlu msg="hello,cl!" msg1="changlugege"/>
</div>
`
});
app.component('changlu', {
methods: {
//this.$attrs:是一个代理对象,该对象中包含父组件传值过来的所有属性
handleClick() {
console.log(this.$attrs);
}
},
//v-bind:msg="$attrs.msg1" => 绑定单个值
//v-bind="$attrs" => 绑定所有父组件传递过来的值
template: `
<span @click="handleClick()">changlu组件</span>
<span v-bind:msg="$attrs.msg1">changlu组件</span>
<span v-bind="$attrs">changlu组件</span>
`
});
app.mount("#app");
</script>
- 点赞
- 收藏
- 关注作者
评论(0)