vue -> 组件

创建全局组件----

方法一:(初始阶段)

1.//使用vue.extend来创建组件模板
const vr = vue.extend({
	//
	template: `<div>
				<h1></h1>
				<p></p>
			</div>
	`
})
//使用component来创建组件模板对象
	vue.component('MyCont(实例化的组件名)',vr(组件模板名))
//调用:
<body>
	<my-cont></my-cont>//使用的组件直接以html标签的样式引用
	//组件名格式,在注册的时候最好用双驼峰命名,引用的时候用‘-’链接双驼峰
</body>

方法二:(进阶)

	vue.component('MyCont(实例化的组件名)',vue.extend({
	//第一个参数为组件名,二参为将要创建的组件模板
		template: `<div>
					<h1></h1>
					<p></p>
				</div>
		`
	}))
//调用:
<body>
	<my-cont></my-cont>//使用的组件直接以html标签的样式引用
	//组件名格式,在注册的时候最好用双驼峰命名,引用的时候用‘-’链接双驼峰
</body>

方法二简化:

vue.component('MyCont(实例化的组件名)',{
	//对象的字面量形式
		template: `<div>
					<h1></h1>
					<p></p>
				</div>
		`
	})
//调用:
<body>
	<my-cont></my-cont>//使用的组件直接以html标签的样式引用
	//组件名格式,在注册的时候最好用双驼峰命名,引用的时候用‘-’链接双驼峰
</body>

方法三:(组件的模板写在外部)

<div id="app">
	<my-cont></my-con>
</div>

<template id="one">
	<div>
		<h3></h3>
		...
	</div>
</template>


<script>
	//实例化vue对象
	const v = new vue({
		el: "#app",
		data: {},
	})
	//创建组件
	vue.component('MyCont(实例化的组件名)',{
		//第一个参数为组件名,二参为将要创建的组件模板
			template: "#one"//组件模板绑定在外部的template上,类似vue实例化中的el
		})
</script>

总结:不管是那种方法,template模板中只能有一个根标签

	正确写法:**<template>**				错误写法:**<template>**	
				<div>//被div包裹						<div>不只有一对根标签
					<p></p>							</div>
					...								  ...
				</div>								<p></p>
			**</template>**						**</template>**
				

-----------------------------------------------------------------------------

创建私有组件----

方法一:

<div id="app">
	<ones></ones>//在app范围内使用
<div>
```javascript
	const v = new vue({
		el: "#app",
		components: {
			ones: {
				template: `<div>
							<p></p>
							<h1></h1>
							...
						</div>`
			}
		}
	})

**方法二:**
```html
	<div id="app">
		<ones></ones>//在app范围内使用
	<div>
	<template id="one">
		<div>
			<p></p>
			....
		</div>
	</template>
		const v = new vue({
			el: "#app",
			components: {	定义私有组件的函数(内部函数)
				ones: {
					template: "#one"
				}
			}
		})

----------------------------------------------------------

组件的data数据----

<body>
  <div id="app">
    <my-cont></my-cont>
  </div>
  <!-- <my-cont>{{ mag }}</my-cont> -->
</body>
<script>


  Vue.component("MyCont", {
    template: `<h1>全局组件----{{ mag }}</h1>`,
    //组件可以有自己的data数据
    //组件中的data和实例上的data不同,必须是一个函数,并且返回一个对象,
    //组件中的data使用和实例的data一样
    data() {
      return {
        mag: 'xxx',
      }
    },
  })

  const v = new Vue({
    el: "#app",
    data: {
      msg: "xxx"
    },
    methods: {

    },
  });
</script>
总结:**data为函数返回对象而不是直接是一个对象的原因,
	因为当data为一个全局组件的时候,目的是为了能够复用,但是如果data为对象的话
	就会造成引用类型传递现象(引用类型地址指向相同),操作一个,全部跟着改变
	所以data为函数返回对象,可以避免这一现象的发生,组件多次使用不会干扰**

-------------------------------------------------------------

组件切换登录/注册小demo-----

<body>
  <div id="app">
    <a href="#"><button @click="log">登录</button></a>
    <a href="#"><button @click="sig">注册</button></a>
    <login v-if="flag"></login>
    <sign v-else="flag"></sign>
  </div>
  <!-- <my-cont>{{ mag }}</my-cont> -->
</body>
<script>

  //登录组件
  Vue.component("login", {
    template: `<h1>登录板块</h1>`,
    data() {
      return {
      }
    },
  })
  //注册组键
  Vue.component("sign", {
    template: `<h1>注册板块</h1>`,
    data() {
      return {
      }
    },
  })

  const v = new Vue({
    el: "#app",
    data: {
      msg: "xxx",
      flag: true,
    },
    methods: {
      log(){
        this.flag = true//登录按钮控制,配和v-if
      },
      sig(){
        this.flag = false//注册按钮控制,配和v-else
      }
    },
  })
</script>
---缺点,只能在俩中状态中切换

component 标签:

  <style>
    .v-enter, .v-leave{
      opacity: 1;
    }
    .v-enter-avtive,.v-leave-active{
      transform: translateX(150px);
      color: rgb(209, 62, 4);
      opacity: 0;
      transition: all 1.2s ease
    }
  </style>
<body>
  <div id="app">
    <a href="" @click.prevent="name='login'"><button>登录</button></a>
    <a href="" @click.prevent="name='sign'"><button>注册</button></a>
    <a href="" @click.prevent="name='way'"><button>路人</button></a>
    <!-- vue 提供的component标签用于切换组件 :is="xxx" xxx就是要切换的组件名 -->
    <!-- 这个组件名定义成实例data数据的一个变量 -->
    <transition>
    	<component :is="name"></component>
    </transition>
  </div>
</body>
<script src="./vue.js"></script>
<script>
  //登录组件
  Vue.component("login", {0
    template: `<h1>登录板块</h1>`,
    data() {
      return {
      }
    },
  })
  //注册组键
  Vue.component("sign", {
    template: `<h1>注册板块</h1>`,
    data() {
      return {
      }
    },
  })
   //路人a组键
   Vue.component("way", {
    template: `<h1>路人板块</h1>`,
    data() {
      return {
      }
    },
  })

  const v = new Vue({
    el: "#app",
    data: {
      name: ""
    },
    methods: {

    },
  })
</script>
vue 提供的一些标签(元素)
	<component></component>/<template><template>/<transition></transition>/<transitionGroup></transitionGroup>

----------------------------------------------------------------

组件间的传值----

父向子传递普通属性数据:

<body>
  <div id="app" v-cloak>
    <!-- 传递父组件的msg 使用自定义属性传递 -->
    <login :fuzi="msg"></login><!-- ① -->
  </div>
</body>
<script src="./vue.js"></script>
<script>
  const c = new Vue({
    el: '#app',
    data: {
      msg: "fufu",
    },
    methods: {
      change(){
        console.log("fu")
      }
    },
    components: {
      login:{
        //子组件可以使用父组件传递的值,为了后期冲突,在父组件传递属性的时候
        //属性名最好不要和子组件的data里的属性名相同,不然后警告
        template: `<h1>子组件{{ fuzi + msg }}</h1>`,
        //props是数组 里面的值都是父组件传递过来的,数组的值就是上面父组件传递的属性
        //props接受到的值可以改,但是千万别动一旦更改 修改的这个值的源头就会不再指向唯一
        //违背单流体原则,当一个父组件中有多个子组件时,子组件的数据 应该由 父组件统一管理(不应该在子组件的data中管理)
    	//好处:增加组件的复用性 以及可维护性
        props: [
          "fuzi"/* ① */
        ],
        data(){
          return {
            msg: "zizi"
          }
        }
      }
    }
  })
</script>

子向父传递(通过自定义事件)理解为父给子一个方法模型,子调用该方法后
父就可以拿到子调用方法时的参数并赋值给自己的数据上:

<body>
  <div id="app" v-cloak>
    <!-- 自定义的事件名,就是子组件要接受的属性 ①-->
    <!-- 如果change加个()就成了方法的调用,会把方法的结果传递给子组件 -->
    <login @aaa="change"></login>
  </div>
</body>
<script src="./vue.js"></script>
<script>
  const v = new Vue({
    el: "#app",
    data: {
     msg: "fu" ,
     setmsg: null,
    },
    methods: {
      change(a1,a2) {
        console.log("fufufufufu" + a1 + a2)
        this.setmsg = a2//收到子组件传过来的值,赋值给自己的data数据
      }
    },
    components: {
      login: {
        template: `
        <div>
          <h1>我是子</h1>
          <button @click="btn">子组件按钮,来调用父组件的方法</button>
        </div>
          `,
        data: {
        	msg: "xxx"
        },
        methods: {
          btn(){
            //使用this.$emit来接受父组件的传递的方法①
            //可以接受传参,参数和父组件中的change参数保持一致
            //父组件的参数时形参,子组件的是实参
            //因为这个子组件的aaa可以理解为指向父组件的change
            //这里的实参可以是子组件里的data数据,父组件里就可以收到该子组件传递回去的数据
            this.$emit("aaa",11,this.msg)
          }
        },
      }
    },
  })
</script>

兄弟之间的传递(事件总线)

原理和子向父传递一样,只不过兄弟之间不能只能在组件标签内写自定的事件,所以需要用一个第三方组件来链接
定义一个全局的总线(第三方)bus,谁向外传递值就给谁调用bus.$eimt("自定义事件名①",传递的值)
谁接收就给谁调用bus.$on("自定的事件名①",(形参->传递的值)=>{})
<body>
  <div id="app" v-cloak>
    <!-- 自定义的事件名,就是子组件要接受的属性 ①-->
    <!-- 如果change加个()就成了方法的调用,会把方法的结果传递给子组件 -->
    <login></login>
    <logins></logins>
  </div>
</body>
<script src="./vue.js"></script>
<script>
	//第三方中间过度
  const bus = new Vue()
  const v = new Vue({
    el: "#app",
    data: { 
      msg: "fu",
      setmsg: "",
    },
    methods: {
      change(a1) {
        console.log("fufufufufu" + a1)
        this.setmsg = a1
      }
    },
    components: {
      login: {//子组件1
        template: `
        <div>
          <h1>我是子1</h1>
          <button @click="btn">我是子1</button>
        </div>
          `,
        data(){
          return {
            setmsg: "xiongdi1"
          }
        },
        methods: {
          btn(){
            bus.$emit("aaa",this.setmsg)//传递给子组件2的值,自定义事件aaa
          }
        },
      },
      logins: {//子组件2
        template: `
        <div>
          <h1>我是子2</h1>
          <button>我是子2</button>
        </div>
          `,
        data(){
          return {
            setmsg: ""
          }
        },
        methods: {

        },
        mounted(){
          bus.$on("aaa",(setmsg)=>{//接受自定义事件aaa
            this.setmsg = setmsg//接收子组件1传过来的值,并赋值给自己的data数据上
          })
        }
      },
    },
  })
</script>

一下三种通信 不太常用

  • ref 父组件中直接获取子组件的实例 需要记住
    面试题:如何在父组件中 直接调用子组件的 方法

  • 实例 $parent属性和 $children属性
    $parent获取父组件实例(子组件中使用)
    $children 获取 所有的子组件 返回的是数组(父组件中使用)

  • provide/inject
    provide 父组件属性 提供给 子组件的数据
    inject 父组件通过provide提供的数据,子组件可以通过inject拿到

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值