一.组件
1.定义组件
Vue自定义组件分为两种:全局注册和局部注册,全局组件可以在任何地方引用,局部组件只能在当前Vue实例使用。
1)全局注册
使用Vue.component(tagName, options)来定义:
2)局部注册
在Vue实例中使用components属性来定义:
注意:HTML 特性是不区分大小写的,所有在定义组件时尽量使用中划线“-”来指定组件名。
即使,使用了驼峰标示命名如:myComponent,在页面引用时仍然要使用<my-component>进行引用。
<body> <div id="app"> <my-hello></my-hello> </div> <div id="root"> <!--使用组件--> <my-hello></my-hello> <my-hello></my-hello> <my-hello></my-hello> <!-- <my-hello/>--> <!--不推荐使用--> <my-hello></my-hello> <inner-hello></inner-hello> </div> </body> <script type="text/javascript"> /*定义全局组件*/ Vue.component("my-hello",{ template:"<h3>Hello Vue</h3>" }); new Vue({ el:"#app" }); new Vue({ el:"#root", components:{ "inner-hello":{ template:"<h3>我是局部组件</h3>" } } }); </script>
2.is属性
在table标签中直接使用自定义组件,无法正常显示。DOM解析时会解析到<table>标签的外部:
原因是:table/ol/ul/select 这种html标签有特殊的结构要求,不能直接使用自定义标签。他们有自己的默认嵌套规则,比如:
table> tr> [th, td];
ol/ul > li;
select > option
<body> <table id="app"> <tr is="my-hello"></tr> </table> </body> <script type="text/javascript"> /*定义全局组件*/ Vue.component("my-hello",{ template:"<h3>Hello Vue</h3>" }); new Vue({ el:"#app" }); </script>
3.模板
<body> <!-- 模板 当模板的html结构比较复杂时,直接在template属性中定义就不现实了,效率也会很低,此时我们可以使用模板,定义模板的四种形式: 1)直接使用字符串定义 2)使用<script type="text/x-template"> 3)使用<template>标签 4)使用.vue组件,需要使用模块加载机制 在使用直接字符串模板时、x-template和.vue组件时,不需要is进行转义。 --> <div id="app"> <my-hello1></my-hello1> <my-hello2></my-hello2> <my-hello3></my-hello3> <my-hello4></my-hello4> </div> <!--2)使用<script type="text/x-template">--> <script type="text/x-template" id="tpl3"> <ul> <li>01</li> <li>02</li> </ul> </script> <!--3)使用<template>标签--> <template id="tpl4"> <ul> <li>011</li> <li>022</li> </ul> </template> </body> <script type="text/javascript"> /*1)直接使用字符串定义*/ var tpl = "<div><button>按钮</button><span>Hello</span></div>"; var tpl2 = ` <div> <button>按钮2</button> <span>Hello2</span> </div> `; console.log(tpl2); // 定义组件 Vue.component("my-hello1",{ template:tpl }); Vue.component("my-hello2",{ template:tpl2 }); Vue.component("my-hello3",{ template:"#tpl3" }); Vue.component("my-hello4",{ template:"#tpl4" }); new Vue({ el:"#app" }); </script>
4.data属性
通过data属性指定自定义组件的初始数据,要求data必须是一个函数,如果不是函数就会报错。
<body> <div id="app"> <!--使用组件--> <my-hello></my-hello> <my-hello></my-hello> <my-hello></my-hello> </div> </body> <script type="text/javascript"> /*定义组件需要在实例化vue之前*/ Vue.component("my-hello",{ template:"<button @click=‘count++‘>按钮{{count}}</button>", // 定义组件内部data: 必须通过函数定义 data:function(){ return {count:0}; } }); new Vue({ el:"#app", data:{ } }); </script>
5.props
组件可以嵌套使用,叫做父子组件。那么父组件经常要给子组件传递数据这叫做父子组件通信。
父子组件的关系可以总结为 props 向下传递,事件向上传递。
父组件通过 props 给子组件下发数据,子组件通过事件给父组件发送消息。
1、在父组件中定义数据
2、在使用组件时,绑定父组件中的数据
3、在子组件中通过props属性声明父组件中传递过来的参数
4、在template属性中使用父组件中的参数
<body> <div id="app"> <!--使用组件--> <my-hello :txt1="msg" :txt2="txt"></my-hello> </div> </body> <script type="text/javascript"> /*定义组件需要在实例化vue之前*/ Vue.component("my-hello",{ // 声明父组件传递过来的参数 props:["txt1","txt2"], template:"<div>{{txt1}}:{{txt2}}</div>" }); new Vue({ el:"#app", data:{ msg:"来自系统的消息", txt:"Hello Vue!" } }); </script>
6.props校验
子组件在接收父组件传入数据时, 可以进行props校验,来确保数据的格式和是否必传。可以指定一下属性:
1) type: 指定数据类型 String Number Object ...注意不能使用字符串数组,只能是对象大写形式
2) required: 指定是否必输
3) default: 给默认值或者自定义函数返回默认值
4) validator: 自定义函数校验
非props属性
引用子组件时,非定义的props属性,自动合并到子组件上,class和style也会自动合并。
<body> <div id="app"> <!--使用组件--> <my-hello class="item" style="font-size: 30px;color:pink;" ></my-hello> </div> </body> <script type="text/javascript"> /*定义组件需要在实例化vue之前*/ Vue.component("my-hello",{ template:"<span class=‘test‘ style=‘color:red‘>Vue</span>" }); new Vue({ el:"#app" }); </script>
7.自定义事件
父组件给子组件传值使用props属性, 那么需要子组件更新父组件时,要使用自定义事件$on和$emit:
?$on监听: 不能监听驼峰标示的自定义事件, 使用全部小写(abc)或者-(a-b-c)
?$emit主动触发: $emit(事件名,传入参数)
主动挂载
自定义事件不仅可以绑定在子组件,也可以直接挂载到父组件,使用$on绑定和$emit触发。
<body> <div id="app"> <my-hello v-on:update-count="changecount()"></my-hello> {{count}} </div> </body> <script type="text/javascript"> Vue.component("my-hello",{ template:"<button v-on:click=‘update‘>子组件Child</button>", methods:{ update:function(){ console.log("点击..."); this.$emit("update-count","自定义事件"); } } }); var app = new Vue({ el:"#app", data:{ count:0 }, methods:{ changecount:function(){ this.count++; } } }); // 主动挂载自定义事件 app.$on("update-count",function(value){ console.log(value); this.count++; }); // 触发自定义事件 app.$emit("update-count","这是自定义事件"); </script>
二.插槽分发
1.slot插槽
<body> <!-- --> <div id="app"> <my-hello></my-hello> <my-hello> <h3>你好</h3> <p>这是p元素</p> </my-hello> </div> <!--使用template标签--> <template id="tpl1"> <div> <h4>Hello Vue</h4> <!--插槽,占位--> <slot>如果没有传递数据,默认显示这段文本</slot> </div> </template> </body> <script type="text/javascript"> // 自定义组件 Vue.component("my-hello",{ template:"#tpl1", }); var app = new Vue({ el:"#app" }); </script>
2.具名插槽
具名插槽slot, 就是给插槽起个名字。
在子组件定时可以定定义多个<slot>插槽,同时通过name属性指定一个名字,如:<slot name=‘header‘>,父组件引用时使用< slot=‘header‘>进行插槽选择。
<body> <div id="app"> <!--<my-hello></my-hello>--> <my-hello> <h3 slot="header">你好</h3> <p slot="footer">这是p元素</p> </my-hello> </div> <!--使用template标签--> <template id="tpl1"> <div> <slot name="header">如果没有传递数据,默认显示这段文本</slot> <div>--------------------</div> <!--插槽,占位--> <slot name="footer">如果没有传递数据,默认显示这段文本</slot> </div> </template> </body> <script type="text/javascript"> // 自定义组件 Vue.component("my-hello",{ template:"#tpl1", }); var app = new Vue({ el:"#app" }); </script>
3.插槽作用域
作用域插槽slot-scope,
父组件通过<slot>插槽混入父组件的内容, 子组件也可以通过slot作用域向插槽slot内部传入数据,使用方式:<slot text=‘子组件数据‘>,
父组件通过<template slot-scope="props">进行引用。
<body> <div id="app"> <!--<my-hello></my-hello>--> <my-hello> <template slot-scope="props"> <h3>你好----{{props.msg}}----{{props.txt}}</h3> </template> </my-hello> </div> <!--使用template标签--> <template id="tpl1"> <div> <div>--------------------</div> <!--插槽,占位--> <slot msg="你好啊" txt="Hello">如果没有传递数据,默认显示这段文本</slot> </div> </template> </body> <script type="text/javascript"> // 自定义组件 Vue.component("my-hello",{ template:"#tpl1", }); var app = new Vue({ el:"#app" }); </script>
原文:https://www.cnblogs.com/xiaokeji/p/10776723.html