Vue注册组件
注册组件,关键字:component()有两个参数
-
第一个参数:新组件的名称(字符串类型)组件名定义时可以使用驼峰命名,但是使用时必须是用“-”来连接
-
第二个参数:回调函数(写Vue的代码)
自定义组件是可以复用多个的,但是都是双标签,不建议使用单标签的形式
<div id="app"> <itme-li></itme-li> <itme-li></itme-li> <itme-li></itme-li> <itme-li></itme-li> <!-- </itme-li> 不建议使用,即使用了也是无效的--> </div> <script> Vue.component("itme-li",{ template:`<li>hello world</li>` }) </script>
-
如果要是在template里面写两个同级的元素,则第二个不会显示,而且会报错。要想实现两个或多个同级元素,则必须在前面加个根元素
<div id="app"> <itme-li></itme-li> </div> <script> //错误写法 Vue.component("itme-li",{ template:` <li>hello world</li> <li>你好</li>//这个则不会显示,切报错 ` }); //正确写法 Vue.component("itme-li",{ template:` <ul> <li>hello world</li> <li>你好</li> </ul> ` }); </script>
-
上面传的都是死值,那我们也可以动态传值,有个关键词:props();定义一个props接收父组件的值,这里面写的名称就是template语法糖里面的名称要保持一致,可以写多个值
<div id="app"> <!-- v-bind:show="msg"必须写在开始标签的后面 --> <!-- <v-bind:show="msg" itme-li></itme-li> 这个是错误写法--> <!-- 如果绑定的数据比较多的话,是可以分开写的,示例见如下代码 --> <!-- props传的什么值就只能用谁 --> <!-- v-for="itme in list"遍历的是父组件里面数组 --> <!-- 这里v-bind绑定的也是props里的值 --> <itme-li v-bind:show="msg" v-bind:shows="msgTwo" v-for="itme in list" v-bind:arr="itme" :key="itme.id" ></itme-li> </div> <script> Vue.component("itme-li",{ //定义一个props接收父组件的值,这里面写的名称就是template语法糖里面的名称要保持一致,可以写多个值 props:["show","shows","arr"], template:` <ul> <li>{{show}}</li> <li>{{shows}}</li> <li>{{arr.id}}--{{arr.name}}</li> </ul> ` }); let vm = new Vue({ el:"#app", data:{ msg:'今天天气真好啊', msgTwo:"心情也好很多了", list:[ {id:0,name:"旭陌"}, {id:1,name:"旭陌1"}, {id:2,name:"旭陌2"}, {id:3,name:"旭陌3"} ] } }); </script>
以上代码所渲染的示例!![@HXO[05N7PO)DIU@0DM`$J9](C:\Users\admin\Desktop\@HXO[05N7PO)DIU@0DM`$J9.png)
- $emit():从子组件传值给父组件:有两个参数,第一个为事件名称,第二个是提供的值(或者是实参)。这里的自定义事件名不能使用驼峰命名,必须全部使用小写或者短横线分割。
```html
<div id="app">
<itme-li
v-for="itme in list"
v-bind:arr="itme"
:key="itme.id"
:style="{fontSize:fontSize + 'em'}"
v-on:change="num"
></itme-li>
</div>
<script>
Vue.component("itme-li",{
props:["arr"],
template:`
<ul>
<li>{{arr.id}}--{{arr.name}}</li>
<button @click="$emit('change',0.1)">点击方法字体</button>
</ul>
`
});
let vm = new Vue({
el:"#app",
data:{
list:[
{id:0,name:"旭陌"},
{id:1,name:"旭陌1"},
{id:2,name:"旭陌2"},
{id:3,name:"旭陌3"}
],
fontSize:1
},
methods:{
num(n){
this.fontSize += n;
}
}
});
</script>
-
局部组件:
- 优点:局部组件只能在定义它的实例中使用,是不可以在别的实例中使用的,方便管理
- 缺点:代码冗余比较高
-
全局组件:
- 优点:可以在任何的vue实例中使用
- 缺点:如果说你的项目中已经没有使用这个组件了,它依然会包含在我们项目最终的构建结果中
<div id="app"> <itme-one></itme-one>//这个全局组件可以用 <ccc></ccc>//这个是可以用的 </div> <div id="app1"> <itme-one></itme-one>//这个全局组件可以用 <ccc></ccc>//这个会报错,组件为定义 </div> <script> //全局组件 Vue.component("itme-one",{ template:`<div>这是全局组件</div>` }); let vm = new Vue({ el:"#app", //components属性定义一个组件 components:{ //ccc是组件名 'ccc':{ template:`<h2>这是局部组件</h2>`//组件模板 } } }); let vm1 = new Vue({ el:"#app1", }); </script>
-
props的类型,前面也讲过了props是可以以数组的形式的,但是同时也是可以以对象的形式存在,而这个时候就可以选择props的接收数据名称的类型,如果类型以父组件里面的数据类型不一样虽然也可以渲染,但是也是会报错的,下面就来看一个例子吧
<div id="app"> <itme-one v-bind:change='msg' ></itme-one> </div> <script> Vue.component("itme-one",{ props:{ //这里就设置为数值类型 'change':Number//此刻改成string就可以了 }, template:`<div>{{change}}</div>` }); let vm = new Vue({ el:"#app", data:{ //而父组件的数据是string类型 msg:"你好啊,很高兴认识你" } }); </script>
-
:插槽
-
插槽的基本用法:使用注册组件时,直接在组件标签中写入内容是无效的,但是如果使用了slot标签的话,则能够将内容展示出来。当组件渲染的时候,将会被我们自己在模板写的内容替代。还有就是如果slot标签在某个元素的前面,则展现的内容也会在某个元素的内容前面
<div id="app"> <itme-one v-bind:url='url' ><h2>haha</h2></itme-one> </div> <script> Vue.component("itme-one",{ props:['url'], template:`<div> <slot></slot> <a href="url">点我</a> </div>` }); let vm = new Vue({ el:"#app", data:{ url:'/today' } }); </script>
-
插槽里的作用域编译:父级作用里的内容是在父级模板里编译的, 而子作用域里的内容是在子作用域里编译的
<div id="app"> <itme-one v-bind:url='url' > <!-- 这里是父级作用域的内容 --> <h2>{{msg}}</h2> </itme-one> </div> <script> Vue.component("itme-one",{ props:['url'], data:function(){ return { msg:"这里是子作用域的内容" } }, template:`<div> <slot></slot> <a href="url">{{msg}}}</a> </div>` }); let vm = new Vue({ el:"#app", data:{ url:'/today', msg:"这里是父作用域的内容" } }); </script>
-
插槽的后备内容,当注册组件里没有写内容的时候,slot插槽里的内容是默认的,要是注册组件里有内容,则显示注册组件里的内容为主。
<div id="app"> <itme-one v-bind:url='url' > <!-- <h2>{{url}}</h2>这里没写内容的时候就是slot的默认内容显示 --> </itme-one> </div> <script> Vue.component("itme-one",{ props:['url'], template:`<div> <slot>{{url}}<i>这里是默认的内容</i></slot> <a href="url">{{url}}</a> </div>` }); let vm = new Vue({ el:"#app", data:{ url:'/today' } }); </script>
-
具名插槽:如果有多个slot插槽的话,这个时候slot是有name属性的,在slot写上属性名就可以了
<div id="app"> <itme-one> <!-- v-slot:header可以缩写成#header --> <template v-slot:header> <h2>这里是头部区域</h2> </template> <p>这里是p1</p> <p>这里是p2</p> <p>这里是p3</p> <template #footer> <h2>这里是footer区域</h2> </template> </itme-one> </div> <script> Vue.component("itme-one",{ // props:['url'], template:`<div> <header> <slot name="header"></slot> </header> <main> <slot></slot> </main> <footer> <slot name="footer"></slot> </footer> </div>` }); let vm = new Vue({ el:"#app" }); </script>
-
作用域插槽:如果你想在父级用子级的内容,就需要用到作用域插槽
<!-- v-bind:user="user"v-bind:自定义属性名=传过去使用的值 v-slot={user,password:pwd}如果有多个对象的话,用,隔开直接写传过去的参数 password:pwd这里的password改成pwd,所以用第二个对象就是pwd了,要是不写的话就是默认的password,就跟es6的解构赋值是一样的 --> <div id="app"> <itme-one v-slot={user,password:pwd}> {{user.name}} {{pwd.val}} </itme-one> </div> <script> Vue.component("itme-one",{ data(){ return { user:{ name:"xumo" }, password:{ val:123 } } }, template:`<div><slot v-bind:user="user" v-bind:password="password" ></slot></div>` }); let vm = new Vue({ el:"#app" }); </script>
-
$refs:父组件获取子组件的属性和方法
<div id="app"> <!-- ref属性可以获取父组件的属性和方法 --> <itme-one ref="son"></itme-one> <button @click="getData">点击获取数据</button> <p>{{msg1}}--{{msg2}}</p> </div> <script> Vue.component("itme-one",{ data(){ return{ a:123, b:456 } }, template:`<ul><li style='list-style:none'></li></ul>` }); let vm = new Vue({ el:"#app", data:{ msg1:"", msg2:"" }, methods:{ getData(){ // console.log(this.$refs); return this.msg1 = this.$refs.son.a, this.msg2 = this.$refs.son.b } } }); </script>
-
-