<div id&#61;"app"><hello-vue>hello-vue><hello-vue>hello-vue><hello-vue>hello-vue><hello-vue>hello-vue>div><script src&#61;"../js/vue.js">script><script>const cpnC &#61; Vue.extend({template:&#96;
hello vue
&#96;})Vue.component(&#39;hello-vue&#39;,cpnC)const app &#61; new Vue({el: &#39;#app&#39;,data: {msg: &#39;hello vue!&#39;}})script>
上述方式是全局组件&#xff0c;可以在多个vue实例中使用。&#xff08;实际开发一般从头到尾就一个vue实例&#xff09;
局部组件注册&#xff1a;
const app &#61; new Vue({el: &#39;#app&#39;,data: {msg: &#39;hello vue!&#39;},components:{//cpn使用组件时的标签名cpn:cpnC}
})
<div id&#61;"app"><cpn1>cpn1>div><script src&#61;"../js/vue.js">script><script>//子组件const cpnC2 &#61; Vue.extend({template: &#96;
hello vue2
&#96;})//父组件const cpnC1 &#61; Vue.extend({template: &#96;hello vue
省去extend
//全局组件
Vue.component(&#39;hello-vue&#39;,{template:&#96;hello vue
&#96;
})
//局部组件
const app &#61; new Vue({el: &#39;#app&#39;,data: {msg: &#39;hello vue!&#39;},components:{//cpn使用组件时的标签名cpn:{template:&#96;hello vue
&#96;}}
})
在标签中写&#xff0c;两种方式&#xff1a;
中写
标签中写然后使用id选择器放到模板后面
当我们封装好一个组件之后&#xff0c;在html使用组件实例&#xff0c;例如封装计数器组件&#xff0c;我们创建三个组件实例&#xff0c;每个组件实例都有数值的改变&#xff0c;如果组件中的data是对象或者数组形式&#xff0c;其中一个组件实例的数字改变&#xff0c;其他组件的数值也会跟着改变&#xff0c;因为组件在使用data中的数据时&#xff0c;三个组件的内存地址都会指向同一个data中的内存地址。而使用函数进行返回值&#xff0c;函数每次返回数据都会开辟一个新的内存地址&#xff0c;这就使得每一个组件指向的data中的数据都是不同的内存地址&#xff0c;这样其中一个计数器数值增加&#xff0c;其他计数器数值才不会跟着增加
<body><div id&#61;"app"><cpn :cmovies&#61;"movies">cpn>div><script type&#61;"text/x-template" id&#61;"cpn"><ul><li v-for&#61;"item in cmovies">{{item}}</li></ul>script><script src&#61;"../js/vue.js">script><script>const cpn &#61; {template: &#39;#cpn&#39;,data() {return {}},props: [&#39;cmovies&#39;]}const app &#61; new Vue({el: &#39;#app&#39;,data: {msg: &#39;hello vue!&#39;,movies: [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;]},components: {cpn}})script>
上面的数组写法&#xff0c;一般不用
对象写法
对象写法可验证的数据类型
props: {//基础的类型检查&#xff08;null匹配任何类型&#xff09;propA: Number,//多个可能的类型propB: [String, Number],//必填的字符串propC: {type: String,required: true},// 带有默认值的数字prorD: {type: Number,default: 100},// 带有默认值的对象propE: {type: Object,// 对象或数组默认值必须从一个工厂函数获取default() {return {msg: &#39;hello&#39;}},},// 自定义验证函数propF: {validator(value) {// 这个值必须匹配下列字符串中的一个return [&#39;success&#39;, &#39;warning&#39;, &#39;danger&#39;].indexOf(value) !&#61;&#61; -1}}}
在子组件中我们习惯使用驼峰命名&#xff0c;但是在html中绑定时&#xff0c;html无法识别驼峰命名&#xff0c;因此会报错&#xff0c;此时我们要么不使用驼峰命名&#xff0c;要么在html使用该名字时将驼峰命名改为用-
连接&#xff0c;即cMovies
---->c-movies
<div id&#61;"app"><cpn &#64;itemclick&#61;"nameclick">cpn>
div>
<template id&#61;"cpn"><div><button &#64;click&#61;"cnameClick(name)" v-for&#61;"name in names">{{name.name}}button>div>
template>
<script src&#61;"../js/vue.js">script>
<script>const cpn &#61; {template: &#39;#cpn&#39;,data() {return {names: [{id: 1, name: &#39;老子&#39;},{id: 2, name: &#39;孟子&#39;},{id: 3, name: &#39;孔子&#39;},{id: 4, name: &#39;荀子&#39;},]}},methods: {cnameClick(name){console.log(name,&#39;c&#39;)this.$emit(&#39;itemclick&#39;,name)},}}const app &#61; new Vue({el: &#39;#app&#39;,data: {msg: &#39;hello vue!&#39;},components: {cpn},methods: {nameclick(name){console.log(name)}}})
script>
监听子组件中发生的事件
<template id&#61;"cpn"><div><button &#64;click&#61;"cnameClick(name)" v-for&#61;"name in names">{{name.name}}button>div>
template>
在子组件中写调用的方法
methods: {cnameClick(name){console.log(name,&#39;c&#39;)this.$emit(&#39;itemclick&#39;,name)},}
并将该方法事件发送给父组件&#xff0c;参数为&#xff1a;自定义事件名&#xff0c;要传的参数
this.$emit(&#39;itemclick&#39;,name)
在html中使用该组件&#xff0c;并使用自定义事件监听
<div id&#61;"app"><cpn &#64;itemclick&#61;"nameclick">cpn>
div>
调用的方法未写参数默认传发射过来的第一个参数
在父组件中写自定义事件的回调方法
methods: {nameclick(name){console.log(name)}}
方法带的参数与$emit
发射的参数相同
<body><div id&#61;"app"><cpn :number1&#61;"num1" :number2&#61;"num2" &#64;num1change&#61;"num1change" &#64;num2change&#61;"num2change">cpn>div><template id&#61;"cpn"><div>props:{{number1}}data:{{dnumber1}}<input type&#61;"text" :value&#61;"dnumber1" &#64;input&#61;"num1input">props:{{number2}}data:{{dnumber2}}<input type&#61;"text" :value&#61;"dnumber2" &#64;input&#61;"num2input">div>template><script src&#61;"../js/vue.js">script><script>const app &#61; new Vue({el: &#39;#app&#39;,data: {num1: 1,num2: 0},components: {cpn: {template: &#39;#cpn&#39;,props: {number1: Number,number2: Number,},data(){return {dnumber1 : this.number1,dnumber2 : this.number2,}},methods:{num1input(event){this.dnumber1 &#61; event.target.valuethis.$emit(&#39;num1change&#39;,this.dnumber1)this.dnumber2 &#61; this.dnumber1 * 100this.$emit(&#39;num2change&#39;,this.dnumber2)},num2input(event){this.dnumber2 &#61; event.target.valuethis.$emit(&#39;num2change&#39;,this.dnumber2)this.dnumber1 &#61; this.dnumber2 / 100this.$emit(&#39;num1change&#39;,this.dnumber1)}}}},methods: {num1change(num){this.num1 &#61; parseInt(num)},num2change(num){this.num2 &#61; parseInt(num)}}})script>
body>
需求&#xff1a; 子组件的输入框中显示父组件中定义的num1
&#xff0c;num2
&#xff0c;更改子组件输入框中的内容&#xff0c;父组件的num1
&#xff0c;num2
跟着改变
思路&#xff1a;
props
把数据传给子组件&#xff0c;然后在输入框中使用v-model
双向绑定父传过来的数据 props
把数据传给子组件&#xff0c;子组件在data
中将传过来的数据用另一个变量number1
&#xff0c;number2
保存&#xff0c;在子组件输入框中更改时&#xff0c;将数据保存到number1
&#xff0c;number2
中&#xff0c;然后使用自定义事件&#xff0c;将更改后的数据传入给父组件&#xff0c;父组件在自己内部将子组件传过来的数据给原来的num1
,num2
当父组件要访问子组件中的方法或者属性时&#xff0c;可以使用以下两种方法
this.$children
this.$refs.xxxx
,在子组件实例中要加上ref&#61;"xxxx"
属性使用很少&#xff0c;且不建议使用&#xff0c;耦合度高
写法与父访子类似&#xff0c;两个的区别&#xff0c;字面意思可看出
生活中插槽目的是让我们原来的设备进行扩展性
vue中组件的插槽也是为了让封装的组件更加有扩展性&#xff0c;让使用者可以决定组件内部一些内容到底展示什么
封装&#xff1a;
标签即可使用&#xff1a;
标签上述方法只能将组件实例标签中的所有内容替换给所有的
标签
假设我们定义了3个插槽&#xff0c;而我们只想替换中间那个插槽那我们就要给中间那个插槽命名
写法&#xff1a;
一句话总结&#xff1a;父组件替换插槽的标签&#xff0c;但是内容由子组件来提供。
个人理解&#xff1a;子组件定义数据&#xff0c;父组件决定表现形式
需求&#xff1a;
写法&#xff1a;
子组件插槽中定义一个名字并绑定一个数据&#xff0c;这里定义data绑定pLanguages
在父组件中使用该插槽时&#xff0c;使用包裹需要使用的子组件的数据即可引用
<cpn><template slot-scope&#61;"slot">{{slot.data}}template>
cpn>
表现形式
需求&#xff1a;
写法&#xff1a;
子组件插槽中定义一个名字并绑定一个数据&#xff0c;这里定义data绑定pLanguages
在父组件中使用该插槽时&#xff0c;使用包裹需要使用的子组件的数据即可引用
<cpn><template slot-scope&#61;"slot">{{slot.data}}template>
cpn>
参考&#xff1a;vue从入门到精通