三、组件化开发

注册组件

三个步骤
①创建组件构造器Vue.extend()
传入template
②注册组件Vue.component()
需要传递两个参数:1.注册组件的标签名 2.组件构造器
③使用组件<my-cpn></my-cpn>

<div id="app">
 <my-cpn></my-cpn>
 <my-cpn></my-cpn>
 <my-cpn></my-cpn>
</div>
<script src="js/vue.js"></script>
<script>
const cpnContent = Vue.extend({
 template:`
  <div>
   <h2>我是标题</h2>
   <p>我是内容,哈哈哈哈</p>
   <p>我是内容,呵呵呵呵</p>
  </div>`
})
Vue.component('my-cpn',cpnContent) //参数:标签名,组件构造器

var app = new Vue({
 el:'#app',
 data:{
 }
})
</script>

全局组件和局部组件

<div id="app">
 <cpn></cpn>
 <cpn></cpn>
 <cpn></cpn>
</div>
<div id="app1">
 <cpn></cpn>
</div>
<script src="js/vue.js"></script>
<script>
const cpnContent = Vue.extend({
 template:`
  <div>
  <h2 class="tit">我是标题</h2>
  <p>我是内容,哈哈哈哈</p>
  <p>我是内容,呵呵呵呵</p>
 </div>`
})
//Vue.component('cpn', cpnContent) 全局组件

const app = new Vue({
 el:'#app',
 components:{//局部组件
  cpn: cpnContent //在全局组件时候用的标签名字my-con有-,局部的标签有-就会报错
 }
})
const app1 = new Vue({
 el:'#app1'
})
</script>

父组件和子组件

<div id="app">
 <cpn2></cpn2>
 <!-- <cpn1></cpn1> 如果要显示这个需要在全局组件中注册,在父组件中注册是局部组件,他的作用域只能在父组件中显示-->
</div>
<script src="js/vue.js"></script>
<script>
//创建第一个组件构造器(子组件)
const cpnCon1 = Vue.extend({
 template: `
 <div>
  <h2>我是标题1</h2>
  <p>我是内容,哈哈哈</p>
 </div>
 `
})
//创建第二个组件构造器(父组件)
const cpnCon2 = Vue.extend({
template: `
 <div>
  <h2>我是标题2</h2>
  <p>我是内容,呵呵呵</p>
  <cpn1></cpn1>
 </div>
`,
 components: { //注册组件1,组件2里面嵌套了组件1
  cpn1: cpnCon1
 }
})
//root 根组件
var app = new Vue({
 el:'#app',
 data:{
  message:'hello'
 },
 components:{ //注册局部组件
  // cpn1: cpnCon1,
  cpn2: cpnCon2 //注册组件2
 }
})
</script>

注册组件语法糖

<div id="app">
 <cpn1></cpn1>
 <cpn2></cpn2>
</div>
<script src="js/vue.js"></script>
<script>
//创建组件构造器
//const cpnCon = Vue.extend()

//2.注册全局组件(可省略第一步,直接注册组件) component不用加s
Vue.component('cpn1',{
 template: `
 <div>
  <h2>我是标题全局组件</h2>
  <p>我是内容,哈哈哈</p>
 </div>`
})

var app = new Vue({
 el:'#app',
 data:{
 message:'hello'
},
components:{//component要加s 这里是注册局部组件
 'cpn2':{
 template: `
 <div>
  <h2>我是标题局部组件</h2>
  <p>我是内容,哈哈哈</p>
 </div>`
 }
}
})
</script>

模板的分离写法

使用标签,添加id

Vue.component('cpn',{
 template: `#cpn`
})

组件数据的存放

组件对象也有一个data属性,只是这个data属性必须是一个函数,为什么必须是函数呢?
原因是在于Vue让每个组件对象都返回一个新的对象,因为如果是同一个对象的,组件在多次使用后会相互影响

<div id="app">
 <cpn></cpn>
</div>
<template id="cpn">
 <div>
  <h2>{{title}}</h2>
  <p>我是内容</p>
 </div>
</template>
<script src="js/vue.js"></script>
<script>
Vue.component('cpn',{
 template: `#cpn`,
  data(){ //data属性必须是函数
   return { //函数必须返回一个对象
    title:'我是标题哦'
   }
  }
})
var app = new Vue({
 el:'#app',
 data:{}
})
</script>

父子组件的通信

  1. 通过props向子组件传递数据
    注意一:驼峰命名会报错,可以在组件上面把大写I改成-i(:cInfo写成:c-info)
    注意二:子组件中的模板中必须要在最外层写上根元素,就是大的div
    props的值有两种方式
    方式一:字符串数组,数组中的字符串就是传递时的名称
    方式二:对象,对象可以设置传递时的类型,也可以设置默认值等
    步骤
    步骤一:在父组件中写好数据movies: ['我是父组件的数据1','我是父组件的数据2']
    步骤二:(已知)组件上可以写自定义属性,在子组件中定义props(可以是数组也可以是对象)属性(可以传多个属性)接收即可,props里面写变量名称props: ['childmovies']
    步骤三:在引用的子组件<cpn/>上面通过v-bind绑定把父组件的值传递给子组件的变量名<cpn :childmovies='movies'/>
<div id="app">
 <!--父组件movies的数据赋值给子组件props的childmovies-->
 <cpn :childmovies="movies" :childmessage="message"></cpn>
</div>
<template id="cpn">
  <ul>
      <li v-for="item in childmovies" :key="item">{{ item }}</li>
  </ul>
  <!--<h3>{{ childmovies }}</h3>-->
  <p>{{childmessage}} </p>

</template>
<script src="js/vue.js"></script>
<script>
//相当于子组件
const cpn = {
 template:`#cpn`,
 props:['childmovies','childmessage'] //childmovies相当于变量
}
//相当于父组件
const app = new Vue({
 el:'#app',
 data:{
   movies: ['海王','海贼王','海尔兄弟'],
   message: 'hello'
 },
 components: {
  cpn //对象增强写法,原来的写法是'cpn': cpn(标签名,组件构造器)
 }
})
</script>
//除了数组之外,我们也可以使用对象,当需要对props进行类型等验证时,就需要对象写法了。
props: {
  //1.类型限制
  //childmovies: Number

  //2.提供一些默认值
  /*childmessage: {
    type: String,
    default: 'aaa', //写了默认值之后,子组件的标签上可以不写v-bind绑定自定义属性传值了
    required: true //必须加上childmovies这个属性
  }, */

  //3.类型是对象或者数组时,默认值必须是一个函数
  childmovies: {
    type: String,
    default() {
      return {}
    }
  }
}
  1. 通过事件向父组件发送消息$.emit
<!--父组件模板-->
<div id="app">
 <!-- 通过v-on接收子组件的事件监听发送, itemclick不能写驼峰 -->
 <cpn @itemclick="cpnCilck"></cpn>
</div>
<!--子组件模板-->
<template id="cpn">
 <div>
  <button v-for="item in cate" @click="btnClick(item)">{{item.name}}</button>
 </div>
</template>
<script src="js/vue.js"></script>
<script>
//子组件
const cpn = {
 template:`#cpn`,
 data(){
  return {
   cate:[
    {id:'aaa', name:'热门推荐'},
    {id:'bbb', name:'手机数码'},
    {id:'ccc', name:'家用家电'},
    {id:'ddd', name:'电脑办公'}
   ]
  }
 },
 methods:{
  btnClick(item){
  //通过emit把子组件的item传给父组件,itemClick是事件名字,自定义事件
   this.$emit('itemclick', item)
  }
 }
}
//父组件
const app = new Vue({
 el:'#app',
 data:{
  message:'hello'
 },
 components:{
  cpn
 },
 methods:{
  cpnCilck(item){
   console.log('cpnCilck',item);
  }
 }
})
</script>

父子组件的访问方式

父组件访问子组件: $children 或 $refs
子组件访问父组件: $parent

插槽

  1. 插槽的基本使用
    在template中添加<solt></solt>
  2. 插槽的默认值
<solt><button></button></solt>
  1. 具名插槽
<cpn><span name='center'>标题</span></cpn>
<solt name='center'><span>中间</span>/solt>
  1. 编译作用域
    父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在子级作用域内编译。
    isShow使用的是Vue实例中的属性
  2. 作用域插槽
    v-slot
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值