<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="../JS/vue.js"></script>
<title>组件</title>
</head>
<body>
<!--
1.组件也分为全局组件和局部组件:
1.1.全局组件是使用Vue.component()方法来注册,该方法接受两个参数,第一个参数是组件的ID(名字),第二个参数
是一个函数对象(使用Vue.extend()方法创建的组件构造器),也可以是一个选项对象。语法如下:
Vue.component(id,[definition])
1.2.局部组件:是在Vue实例的选项对象中使用components选项来注册
2.注册组件是,data选项是一个函数(也必须是一个函数)。这是因为组件是可复用的Vue实例,
如果还是允许使用先前根实例的数据定义方式,那么所有复用的组件实例都将共享同一份数据,显然,这很容易导致混乱。采用
函数定义方式,那么每个组件实例都将拥有自己的一份返回对象的独立拷贝,每复用一次组件,data函数就执行一次,
从而返回一个新的数据对象。
3.组件的内容通过template选项来定义,当使用组件时,组件所在的位置将被template选项的内容所替换。
此外,组件的内容必须用一个根元素来包裹,且只能有一个根元素
4.因为HTML并不区分元素和属性的大小写,所以浏览器会把所有大写字符解释为小写字符,如下的ButtonCounter,这就会
导致找不到组件而爆错了,解决办法是在DOM模板中采用kebab-case命名来引用组件。
5.由于HTML并不支持自闭合的自定义元素,所以在DOM模板中就不用把ButtonCounter的组件当做自闭合元素来使用
6.调用Vue.component()方法注册全局组件时,第二个参数除了传入选项对象外,还可以传入Vue.extend()方法创建的组件构造器。
Vue.extend()方法使用基础Vue构造器创建一个"子类",该方法只有一个参数,接收一个包含组件选项的对象。
-->
<div id="app">
<button-counter></button-counter>
</div>
<script>
Vue.component('ButtonCounter',{
data: function () {
return {
count:0
}
},
template: '<button v-on:click="count++">You clicked me {{count}} times.</button>'
})
var vm = new Vue({
el: '#app',
data: {
count:0
}
});
</script>
</body>
</html>
通过extend:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="../JS/vue.js"></script>
<title>组件(extend)</title>
</head>
<body>
<!--
1..调用Vue.component()方法注册全局组件时,第二个参数除了传入选项对象外,还可以传入Vue.extend()方法创建的组件构造器。
Vue.extend()方法使用基础Vue构造器创建一个"子类",该方法只有一个参数,接收一个包含组件选项的对象。
-->
<div id="app">
<button-counter></button-counter>
</div>
<script>
let MyComponent = Vue.extend({
template: '<button @click="count++">You clicked me {{count}} times</button>',
data: function () {
return {
count: 0
}
}
})
Vue.component('ButtonCounter',MyComponent)
var vm = new Vue({
el: '#app'
});
</script>
</body>
</html>
局部组件的形式:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="../JS/vue.js"></script>
<title>组件(局部)</title>
</head>
<body>
<!--
1.对于components选项对象来说,它的每个属性的名字就是自定义元素的名字,其属性值就是这个组件的选项对象。
2.局部注册组件也可以使用Vue.extend()方法创建的组件也是可以使用Vue.extend()方法创建的组件构造器。
3.全局注册的组件可以在任何Vue实例中使用,而局部注册的组件只能在父组件的模板中使用。
-->
<div id="app">
<button-counter></button-counter>
</div>
<script>
var vm = new Vue({
el: '#app',
components:{
ButtonCounter:{
data:function () {
return{
count:0
}
},
template: '<button @click="count++">You clicked me {{count}} times</button>'
}
}
});
</script>
</body>
</html>
父传子(prop):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="../JS/vue.js"></script>
<title>组件-父传子(prop)</title>
</head>
<body>
<!--
1.组件是当做自定义元素来使用的,而元素一般是有属性的,同样,组件也可以有属性。在使用组件时,给组件元素设置属性,组件内部接受是通过组件内部是注册一些自定义的属性,
称为prop,这些prop是放在组件的props选项中定义的;之后在使用组件时,就可以把这些prop的名字作为元素的属性名来使用,通过属性向组件传递数据,这些数据
将作为组件实例的属性被使用。
2.在props选项中定义的prop,可以当成该组件实例的数据属性来使用。
3.props选项中声明的每一个prop,在使用组件时,作为元素的自定义属性来使用,属性值会被传递给组件内部的prop。
4.因为HTML中的属性名是不区分大小写的,所以要采用驼峰命名法,采用驼峰命名法的prop名要使用等价的(短横线分隔命名)名字来使用,如果在字符串模板中或单文件组件内使用
则没有这个限制,在字符串模板中,除了各种命名可以直接使用之外,组件还可以当做自闭合元素来使用。
-->
<div id="app">
<post-item post-title="Vue.js无难事"></post-item>
<post-list></post-list>
</div>
<script>
Vue.component('PostItem',{
props:['postTitle'],
//postTitle就像data中定义的数据属性
//在该组件中可以如"this.postTitle"这样使用
template: '<h3>{{postTitle}}</h3>'
})
//字符串模板(4)
Vue.component('PostList',{
//在字符串模板中可以使用PascalCase命名组的组件名
//和camelCase命名的prop名
template: '<div> <PostItem post-title="Vue.js无难事"></PostItem></div>'
})
var vm = new Vue({
el: '#app',
data: {
count:0
}
});
</script>
</body>
</html>
多个prop传值:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="../JS/vue.js"></script>
<title>组件-父传子(多个prop传递)</title>
</head>
<body>
<!--
1.在组件中和普通的HTML元素传值一样,要接受动态值,必须要使用 v-bind指令,否则,接收的值都是静态的字符串值。
-->
<div id="app">
<post-list></post-list>
</div>
<script>
Vue.component('PostItem',{
props:['author','title','content'],
template: `
<div>
<h3>{{title}}</h3>
<p>作者:{{author}}</p>
<p>{{content}}</p>
</div>
`
})
Vue.component('PostList',{
data(){
return{
author:'孙鑫',
title:'Vue.js无难事',
content:'这本书不错'
}
},
template: `
<div>
<PostItem
:author="author"
:title="title"
:content="content"
>
</PostItem>
</div>
`
})
var vm = new Vue({
el: '#app',
data: {
count:0
}
});
</script>
</body>
</html>
对象形式传值(1):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="../JS/vue.js"></script>
<title>组件-父传子(prop对象形式)</title>
</head>
<body>
<!--
1.如果子组件定义的prop较多,调用时就需要写较多的属性,然后一一赋值,这很麻烦,为此我们可以使用不带参数的v-bind来传入一个对象,你只需要将该对象的属性和
组件的prop一一对应即可。
2.我们在data中定义了一个post对象,它的属性值和PostItem的prop一一对应,在<PostItem>元素上使用了不带参数的v-bind指令,传入post对象,该对象的所有属性将
作为prop传入。虽然直接传入一个对象,将其所有属性值作为prop传入可以简化代码的编写,但也容易造成一些混乱,而在实际业务中开发时,子组件通常是以对象来接收数据,
父组件以对象的方式来传值
-->
<div id="app">
<post-list></post-list>
</div>
<script>
Vue.component('PostItem',{
props:['author','title','content'],
template: `
<div>
<h3>{{title}}</h3>
<p>作者:{{author}}</p>
<p>{{content}}</p>
</div>
`
})
Vue.component('PostList',{
data(){
return{
post:{
author:'孙鑫',
title:'Vue.js无难事',
content:'这本书不错'
}
}
},
template: `
<div>
<PostItem
v-bind="post"
>
</PostItem>
</div>
`
})
var vm = new Vue({
el: '#app'
});
</script>
</body>
</html>
对象形式(最常用写法):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="../JS/vue.js"></script>
<title>组件-父传子(prop对象形式)</title>
</head>
<body>
<!--
1.如果子组件定义的prop较多,调用时就需要写较多的属性,然后一一赋值,这很麻烦,为此我们可以使用不带参数的v-bind来传入一个对象,你只需要将该对象的属性和
组件的prop一一对应即可。
2.我们在data中定义了一个post对象,它的属性值和PostItem的prop一一对应,在<PostItem>元素上使用了不带参数的v-bind指令,传入post对象,该对象的所有属性将
作为prop传入。虽然直接传入一个对象,将其所有属性值作为prop传入可以简化代码的编写,但也容易造成一些混乱,而在实际业务中开发时,子组件通常是以对象来接收数据,
父组件以对象的方式来传值
-->
<div id="app">
<post-list></post-list>
</div>
<script>
Vue.component('PostItem',{
props:['post'],
template: `
<div>
<h3>{{post.title}}</h3>
<p>作者:{{post.author}}</p>
<p>{{post.content}}</p>
</div>
`
})
Vue.component('PostList',{
data(){
return{
post:{
author:'孙鑫',
title:'Vue.js无难事',
content:'这本书不错'
}
}
},
template: `
<div>
<PostItem
:post="post"
>
</PostItem>
</div>
`
})
var vm = new Vue({
el: '#app'
});
</script>
</body>
</html>
单向数据流:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="../JS/vue.js"></script>
<title>组件-单向数据流</title>
</head>
<body>
<!--
1.通过prop传递的数据是单向的,父组件的属性变化会向下传递给子组件,但是反过来不行。这可以防止子组件意外改变父组件的状态,从而导致应用程序的数据流难以理解。
2.每次父组件更新时,子组件中所有的prop都会刷新为最新的值。这意味着我们不应该在一个子组件内部去改变prop,如果这样做了,vue会站在浏览器的控制台中给出警告。
3.在两种情况下可能需要改变组件的prop。一种是定义一个prop,以方便父组件传递初始值,在子组件内将这个prop作为一个本地的prop数据来使用,遇到这种情况,解决
办法是定义一个本地的data属性,然后将prop的值作为其初始值,后续操作只访问这个data属性。第二种情况是prop接受数据后需要转换后使用,这种情况是可以使用计算
属性来解决的。(具体原因是,如果无论子组件怎么变,当父组件变换时,子组件的值会被父组件变换掉)
https://blog.youkuaiyun.com/weixin_44584442/article/details/111938708
-->
<div id="app">
father:
<button @click="count++">{{ count }}</button>
<son-cmp :count='count'></son-cmp>
</div>
<script>
Vue.component('son-cmp', {
props: ['count'],
template: `
<div>
son:
<button @click="count++">{{ count }}</button>
</div>
`
})
const vm = new Vue({
el: '#app',
data: {
count: 0
}
})
</script>
</body>
</html>
prop的验证:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="../JS/vue.js"></script>
<title>组件-prop验证</title>
</head>
<body>
<!--
1.当开发一个通用组件时,我们希望父组件通过prop传递的数据类型是符合要求的。为此Vue.js还提供了prop验证机制,在定义props选项时,使用一个带验证需求的对象
来代替之前一直使用的字符串数组
2.prop验证发生在组件实例创建之前,因此实例的属性(如data、计算属性等)在default或validator函数中不可用
3.验证的type可以是下列原生构造函数中的一个:
3.1.String
3.2.Number
3.3.Boolean
3.4.Array
3.5.Object
3.6.Date
3.7.Function
3.8.Symbol
3.9.自定义构造器
-->
<div id="app">
<my-component :username="test"></my-component>
</div>
<script>
function Person(firstName,lastName){
this.firstName = firstName
this.lastName = lastName
}
Vue.component('my-component',{
data:function () {
return{
count :0
}
},
props:{
//基本类型检查('null'和'undefined'会通过任何类型验证)
age:Number,
//多个可能的类型
tel:[String,Number],
//必填的字符串
username:{
type: String,
required:true
},
//带有默认值的数字
sizeOfPage:{
type: Number,
default: 10
},
//带有默认值的对象
greeting:{
type:Object,
default: function () {
return {
message: 'hello'
}
}
},
//自定义验证函数
info:{
validator:function (value) {
return ['success','waring','danger'].indexOf(value) !==-1
}
},
//验证author的值是否是通过 new Person创建的
author: Person
},
template: '<button v-on:click="count++">You clicked me {{count}} times.</button>'
})
var vm = new Vue({
el: '#app',
data: {
count:0,
test:"测试"
}
});
</script>
</body>
</html>
非prop属性:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="../JS/vue.js"></script>
<title>组件-非prop属性</title>
<style>
.child{
background-color: red;
}
.parent{
opacity: 0.5;
}
</style>
</head>
<body>
<!--
1.在使用组件时,组件的使用者可能会向组件传入未定义的prop的属性。在Vue.js中,这也是许可的,组件可以接受任意的属性,而这些外部设置的属性会被添加到这个组件的
根元素上。
2.MyInput组件没有定义任何的prop,根元素是<input>,在DOM模板中使用<my-input>元素时设置了type属性,这个属性将被添加到MyInput组件的根元素<input>上,
渲染结果为<input type="text">。此外,在MyInput组件的模板中还使用了class属性,同时在DOM模板中也设置了class属性,在这种情况下,两个class属性的值会被
合并,最终渲染为<input type="text" class="child parent">。要注意的是,只有class和style属性的值会合并,对其他属性而言,从外部提供给组件的值会替换
掉组件内部设置好的值。假设MyInput组件的模板是<input type="text">,如果父组件传入 type="checkbox",就会替换掉 type="text",最后渲染结果就变成了
<input type="checkbox">
3.如果不希望组件的根元素基础外部设置的属性,可以在组件的选项中设置 inheritAttrs:true,
-->
<div id="app">
<my-input type="text" class="parent" ></my-input>
</div>
<script>
Vue.component('MyInput',{
// inheritAttrs:true,
template: '<input type="text" class="child">'
})
var vm = new Vue({
el: '#app'
});
</script>
</body>
</html>
不想更了 太多了 就一个组件还有十几个 其余加起来最起码还有几百个,有需要的私聊我吧。。。。。