vue组件及通信
1、vue组件
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>20181204组件</title> <script src="vue.js" type="text/javascript" charset="utf-8"></script> </head> <body> <div id="app"> <firstcomponent></firstcomponent> <secondcomponent></secondcomponent> </div> <script type="text/javascript"> //(1.1)注册全局组件,组件可以在任意模板里面使用 Vue.component("firstcomponent",{ //组件命名,可以用firstComponent或者first-component,但是调用的时候就必须为first-component; //如果都是小写,那么就可以直接用firstcomponent; //在自定义事件中,事件名也应该使用短横线分割方法命名,如果将事件用v-on:myEvent 命名, //就会变成v-on:myevent,导致监听不到事件,所以用v-on:my-event 。 template:"<div><p>我是全局组件</p></div>" //最外层必须有根元素包裹 }) var vm = new Vue({ el:"#app", data:{ msg:"hello" } }) //(1.2)注册局部组件,在组件实例中通过选项对象注册,只有在定义这个组件的Vue实例里面才可以使用 var vm2 = new Vue({ el:"#app2", data:{ }, components:{ //注意这里是components,后面加s,复数 secondcomponent:{ template:"<div><p>我是局部组件</p></div>" } } }) //(1.3)以上,都可以将组件模板定义到template标签中去 <template id="myComponent"> <div><p>全局组件</p></div> </template> <div id="app"> <firstcomponent></firstcomponent> </div> <script type="text/javascript"> //注册全局组件 Vue.component("firstcomponent",{ template:"#myComponent", //写上template标签的id值即可,和css选择器一样 data(){ return { myData:"a data" } } }) var vm = new Vue({ el:"#app", data:{ } }) </script> //(1.3)为组件添加data和methods //【注意】组件中的data,不再是对象,而是一个方法(否则报错); 而且这个方法内部,还必须返回一个对象才行,组件中的 data 数据使用方式,和实例中的 data 使用方式完全一样!!! <template id="myComponent"> <div> <p>全局组件</p> <p>{{myData}}</p> //调用组件中的data </div> </template> <div id="app"> <firstcomponent></firstcomponent> </div> <script type="text/javascript"> Vue.component("firstcomponent",{ template:"#myComponent", data(){ //组件中的data是一个函数,return一个对象,对象里面是组件的值 return { myData:"a data" } } }) var vm = new Vue({ el:"#app", data:{ } }) </script> </script> </body> </html>
2、父组件与子组件
Child组件是在Parent组件中注册的,它只能在Parent组件中使用,确切地说:子组件只能在父组件的template中使用。
<template id="myComponent"> <div> <p>全局组件</p> <p>{{myData}}</p> <child></child><!-- 调用子组件 --> </div> </template> <div id="app"> <firstcomponent></firstcomponent> </div> <script type="text/javascript"> //注册全局组件 Vue.component("firstcomponent",{ template:"#myComponent", data(){ return { myData:"a data" } }, components:{ "child":{ template:"<div>我是子组件</div>" } } }) var vm = new Vue({ el:"#app", data:{ } }) </script> 子组件也可以使用template <template id="myComponent"> <div> <p>全局组件</p> <p>{{myData}}</p> <child></child> </div> </template> <template id="childComponent"> <div>我是子组件111</div> </template> <div id="app"> <firstcomponent></firstcomponent> </div> <script type="text/javascript"> //注册全局组件 Vue.component("firstcomponent",{ template:"#myComponent", data(){ return { myData:"a data" } }, components:{ "child":{ template:"#childComponent" } } }) var vm = new Vue({ el:"#app", data:{ } }) </script>
3、vue-cli 父子组件传值
A组件使用在App.vue组件的模板中,那么A是子组件,App.vue是父组件
父组件可以多次重复使用子组件
父组件->子组件,传递数据用props,将父组件定义好的值通过props传递给子组件
(3.1)、创建子组件,在src/components/文件夹下,创建一个Child.vue
(3.2)、在Child.vue中创建组件,创建props属性,然后在props中定义一个名为message的属性
<template> <div> <h3>child子组件部分</h3> <p>{{message}}</p> </div></template><script> export default{ props:["message"] }</script>(3.3)、在App.vue中引入Child.vue组件,并在App.vue的components中注册组件<template> <div id="app"> <child message="hello"></child> </div></template><script> import child from './components/Child.vue'; ** //import不能放在export里面,需要放在顶层作用域** export default{ name:"app", components:{ child } }</script>
【注意】现在父组件向子组件传递的值是"hello",是基本数据类型,如果传递是引用数据类,那么就得使用v-bind
如:
<template> <div id="app"> <child :message="parentData"></child> </div></template><script> import child from './components/Child.vue'; export default{ name:"app", data:function(){ return { parentData:"hello,child" } } components:{ child } }</script>
总结一下:
子组件在props中创建一个属性,用以接收父组件传过来的值
父组件中注册子组件
在子组件标签中添加子组件props中创建的属性
把需要传给子组件的值赋给该属性
组件,本质上是一个函数或类,要定制它,就需要向它传参
因为子组件是在父组件里面使用的
所以传值都是在父组件里面操作,接收值、渲染值、过滤值,都是在子组件操作
【注意】单纯插值到页面直接是{{}},如果给按钮等赋值,则必须使用v-bindexport default{ name:"child", props:{ title:{ type:String, default:"我是标题" } }}
子组件->父组件传值,需要自定义事件
子组件内部不能写具体的业务逻辑,具体的点击之后做什么操作,在父组件中写。
子组件内部只需要发布一个自定义事件:this.$emit("custom-event"),
"custom-event"即是自定义事件的名称,这个名称在父子组件里面均是用得到的
通过this.$emit通知给父组件,我已经点击了按钮或者做了什么操作
父组件使用v-on监听子组件的自定义事件,然后自己定义一个事件,一旦监听到了子组件定义的事件触发了,那么就触发自己定义的事件了。
总结一下:
子组件中需要以某种方式例如点击事件的方法来触发一个自定义事件
将需要传的值作为$emit的第二个参数,该值将作为实参传给响应自定义事件的方法
在父组件中注册子组件并在子组件标签上绑定对自定义事件的监听
子组件:模板中标签上,如<template> <button @click="sendMsgToParent"></button>//在响应该点击事件的函数中使用$emit来触发一个自定义事件,并传递一个参数</template>methods:{ sendMsgToParent:function(){ this.$emit("listenChildEvent","this message is from child"); }}父组件:模板中调用子组件<template> <child @listenChildEvent="showMsgFromChild"></child> //在父组件中的子标签中监听该自定义事件并添加一个响应该事件的处理方法</template>methods:{ showMsgFromChild:function(data){ alert(data); }}
这种父子通信比较脆弱,只能在父子组件嵌套三层以内,多了就不行了。*
4、props:
是单向数据流,只允许父组件向子组件传递数据,子组件不允许修改这个数据
双向数据流.sync
父组件里:调用子组件时,使用.sync<modal :isshow.sync="show"></modal>在data里:data:function(){ return { isshow:false }}子组件里:在props里定义props:{ isshow:{ type:Boolean, default:false }}在子组件的自定义方法里改变isshow的值this.$emit("update:isshow",false) //sync和update配合使用
还可以使用v-model来实现父子组件双向数据流
在父组件调用子组件时,使用v-model<p :class="{blue:isBlue}">改变我的背景颜色</p><Modal title="我是父级传的标题" btn-value="我是父级传的按钮" @toParent="parentEvent" v-model="isBlue"></Modal> <!--现在这个isBlue是双向绑定-->data(){ return { isBlue:false }}在子组件props:{ value:{ type:Boolean, default:false }}methods:{ sendChildEvent(){ this.$emit("input",true) //即可改变p的背景颜色为蓝色 }}
v-model="isBlue",isBlue现在是双向绑定,v-model帮我们做两件事情,一是以value的形式把isBlue传给子组件,所以子组件需要定义value属性;二是需要在子组件里改变isBue的值,通过触发this.$emit("input",true)来触发input事件,开发者不需要手动监听input事件,v-model已经帮我们处理好了
5、Vuex
Vuex是所有组件共享的一个对象、仓库、容器,专门管理值,当需要拿值、改变值,都需要通过这个仓库里面的规则进行操作
//原生html监听事件写在行间
关心这个按钮是否被点击了,然后做一些处理,就需要监听一个元素的事件。当用户点击了这个按钮,浏览器内部会发布一个事件,接收到这个事件,执行对应的处理函数
<button onclick="alert(1)"></button>
app.vue也是组件,里面的data也得是一个函数,然后返回一个对象
props:{title:{ type:String, default:"我是标题"}
}
<Modal title="我是父组件给的值1" ></Modal>
如果要显示默认值,那么Modal里面就不能写title="我是父组件给的值1"了,直接删除
<Modal ></Modal>即可,不能是<Modal title="" ></Modal>这样的
行间一律使用烤串命名法,在使用的时候一律使用驼峰命名法
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。