Vue学习 组件

Vue组件学习

什么是组件: 组件的出现,就是为了拆分Vue实例的代码量的,能够让我们以不同的组件,来划分不同的功能模块,将来我们需要什么样的功能,就可以去调用对应的组件即可;
组件化和模块化的不同:

  • 模块化: 是从代码逻辑的角度进行划分的;方便代码分层开发,保证每个功能模块的职能单一;
  • 组件化: 是从UI界面的角度进行划分的;前端的组件化,方便UI组件的重用;
定义全局组件的三种方法

1.使用 Vue.extend 配合 Vue.component 方法:

 //1.1 使用Vue.extend来创建全局的Vue组件
        var com1 = Vue.extend({
            template: '<h3>this is a h3</h3>' //通过template属性,指定组件要展示的HTML结构
            
        })

2.直接使用 Vue.component 方法:

Vue.component('register', {
      template: '<h1>注册</h1>'
    });

3.将模板字符串,定义到script标签种:

<script id="tmpl" type="x-template">
      <div><a href="#">登录</a> | <a href="#">注册</a></div>
    </script>

同时,需要使用 Vue.component 来定义组件:

Vue.component('account', {
      template: '#tmpl'
    });

组件中展示数据和响应事件

1.在组件中,data需要被定义为一个方法,例如:

Vue.component('account', {
      template: '#tmpl',
      data() {
        return {
          msg: '大家好!'
        }
      },
      methods:{
        login(){
          alert('点击了登录按钮');
        }
      }
    });

2.在子组件中,如果将模板字符串,定义到了script标签中,那么,要访问子组件身上的data属性中的值,需要使用this来访问;

组件切换

1.使用flag标识符结合v-if和v-else切换组件

<body>
		<div id="app">
			<a href="" @click.prevent="flag=true">登录</a>
			<a href="" @click.prevent="flag=false">注册</a>
			
			<login v-if="flag"></login>
			<register v-else="flag"></register>
			
		</div>
		<script>
			
			Vue.component('login',{
				template:'<h3>登录组件</h3>'
			})
			Vue.component('register',{
				template: '<h3>注册组件</h3>'
			})
			
			var vm=new Vue({
				el:'#app',
				data:{
					flag:true
				},
				methods:{
					
				}
			})
		</script>
	</body>

2.使用:is属性来切换不同的子组件,并添加切换动画

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
	</head>
	<body>
		<div id="app">
			<a href="" @click.prevent="comName='login'">登陆</a>
	        <a href="" @click.prevent="comName='register'">注册</a>
	        <!--Vue提供的元素来展示对应名称的组件 -->
	        <!--conponent是一个占位符, :is属性可以用来指定要展示的组件的名称 -->
			<component :is="comName"></component>
			
			<!--总结:当前学习了几个Vue提供的标签-->
    		<!--component, template, transition, transitionGroup-->
			
		</div>
		<script>
			Vue.component('login',{
				template:'<h3>登录组件</h3>'
			})
			Vue.component('register',{
				template: '<h3>注册组件</h3>'
			})
			
			
			var vm=new Vue({
				el:'#app',
				data:{
					comName: 'login' //当前component 中绑定的组件的名称
				},
				methods:{
					
				}
			})
		</script>
	</body>
</html>

【重点】为什么组件中的data属性必须定义为一个方法并返回一个对象

通过计数器案例:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
	</head>
	<body>
		<div id="app">
			<counter></counter>
			<hr />
			<counter></counter>
		</div>
		
		<template id="tmp1">
			<div>
				<input type="button" value="+1" @click="increment" />
				<h3>{{ count }}</h3>	
			</div>
		</template>
		<script>
			
			var dataObj = { count: 0 }
			
			Vue.component('counter',{
				template:'#tmp1',
				data:function(){
//					return dataObj
					return { count: 0 }
				},
				methods:{
					increment(){
						this.count++
					}
				}
			})
			
			var vm=new Vue({
				el:'#app',
				data:{
					
				},
				methods:{
					
				}
			})
		</script>
	</body>
</html>

使用components属性定义局部子组件

1.组件实例定义方式

<script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {},
      components: { // 定义子组件
        account: { // account 组件
          template: '<div><h1>这是Account组件{{name}}</h1><login></login></div>', // 在这里使用定义的子组件
          components: { // 定义子组件的子组件
            login: { // login 组件
              template: "<h3>这是登录组件</h3>"
            }
          }
        }
      }
    });
  </script>

2.引用组件:

<div id="app">
    <account></account>
  </div>

父组件向子组件传值

1.组件实例定义方式,注意:一定要使用props属性来定义父组件传递过来的数据

var vm = new Vue({
            el: '#app',
            data:{
                msg: '123父组件中的数据' 
            },
            methods: {
                
            },
            components:{
                'com1':{
                    //子组件中,默认无法访问到父组件中的data和methods
                    template: '<h1 @click="change"> 这是子组件 {{parentmsg}}</h1>',
                    //注意,组件中的所有props中的数据都是通过父组件传递给子组件的
                    //propes中的数据是只可读
                    props: ['parentmsg'] ,// 把父组件传递过来的parentmsg属性, 数组中,定义一下,这样才能用这个数据,
                    //注意子组件中的data数据,并不是通过父组件传递过来的,而是子组件字有的,比如:子组件通过Ajax请求回来的值,可以放到data中
                    //dat a中的数据可读可写
                    data(){
                        return {
                            title: '123',
                            content: 'qqq'
                        }
                    },

2.使用v-bind或简化指令,将数据传递到子组件中:

<div id="app">
    <son :finfo="msg"></son>
  </div>

子组件向父组件传值

1.原理:父组件将方法的引用,传递到子组件内部,子组件在内部调用父组件传递过来的方法,同时把要发送给父组件的数据,在调用方法的时候当作参数传递进去;

2.父组件将方法的引用传递给子组件,其中,getMsg是父组件中methods中定义的方法名称,func是子组件调用传递过来方法时候的方法名称

<com2 @func="show"></com2>

3.子组件内部通过this.$emit(‘方法名’, 要传递的数据)方式,来调用父组件中的方法,同时把数据传递给父组件使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="../vue.js"></script>
    
</head>
<body>
    <div id="app">
        <!--父组件想子组件传递方法使用的是事件绑定机制: v-on 当我们自定义了一个事件属性之后,
        子组件就能过通过某型方法,来调用传进去的这个方法了-->
        <com2 @func="show"></com2>
    </div>
    <template id='temp1'>
        <div>
            <h1>子组件</h1>
            <input type="button" @click="myclick" value="这个是子组件的按钮,点击它,触发父组件传过来的func方法 ">
        </div>
    </template>
    <script>
        //定义了一个字面类型的组件模板对象
        var com2 = {
            template: '#temp1' ,
            methods: {
                myclick(){
                    //当点击子组件方法的时候,如何拿到父组件传递过来的func方法
                    //emit是触发的意思
                    this.$emit('func', this.sonmsg)
                }
            },  
            data() {
                return {
                    sonmsg: {
                        name: 'aaa',
                        age: 6
                    }
                 }
            }
        }
        var vm = new Vue({
            el: '#app',
            data: {
                datamsgFromSon: null
            },
            methods: {
                show(data){
                   // console.log('调用了父组件身上的show方法'+data)
                   console.log(data)
                   this.datamsgFromSon = data
                },
            },
            components:{
                com2  
            },
        })
    </script>
</body>
</html>

组件评论列表案例

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<link rel="stylesheet" type="text/css" href="../../boot-strap.css"/>
		<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
	</head>
	<body>
		<div id="app">
			
			<cmt-box @func="loadComments"></cmt-box>  <!--把父组件的方法传到子组件调用-->
			
			<ul class="list-group">
				<li class="list-group-item" v-for="item in list" :key="item.id">
					<span class="badge">评论人: {{item.user}}</span>
					{{ item.content }}
				</li>
			</ul>
		</div>
		
		<template id="tmp1">
			<div>
				<div class="form-group">
					<label>评论人:</label>
					<input type="text" class="form-group" v-model="user"/>
				</div>
				
				<div class="form-group">
					<label>评论内容:</label>
					<textarea class="form-control" v-model="content"></textarea>
				</div>
				
				<div class="form-group">
	
					<input type="button" value="发表评论" 
					class="btn btn-primary" @click="postComnent"/>
				</div>
				
			</div>
		</template>
		
		<script>
			
			var comentBox = {
				data(){
					return {
						user:'',
						content:'',
					}
				},
				template: '#tmp1',
				methods: {
					postComnent(){
						  /* 
                        
                        1.评论数据村到哪里去??? 存放到了localStorage中
                        2.先组织出一个最新的评论数据对象
                        3.把第二步中得到的评论对象保存到localStorage中
                            3.1  localStorage中只支持存放字符串数据, 要先调用JSON.stringfy
                            3.2  在保存最新的评论数据之前,要从localStorage获取之前的评论数据。转化为一个数组对象。然后吧最新的数据push进去
                            3.3  如果获取到的localStorage中的评论字符串为空,则可以返回一个'[]'让JSON.parse去转换
                            3.4  把最新评论列表数组再次调用JSON.stringfy 转化为 数组字符串然后调用localStringfy。
                            
                    */
                   var comment = { id:Date.now(), user: this.user, content: this.content}
					var list = JSON.parse(localStorage.getItem('cmts')|| '[]')
					list.unshift(comment)
					localStorage.setItem('cmts',JSON.stringify(list))
					this.user = this.content = ''
					
					this.$emit('func')
					}
				}
			} 
			
			var vm=new Vue({
				el:'#app',
				data:{
					list:[
					{ id: Date.now(), user: '小白', content:'111'},
					{ id: Date.now(), user: '李xiao白', content:'222'},
					{ id: Date.now(), user: '李白', content:'333'},
					]
				},
				created(){
					this.loadComments()
				},
				methods:{
					loadComments(){//从本地的 localStorage中加载评论列表 
						var list = JSON.parse(localStorage.getItem('cmts')|| '[]')
						this.list = list
					}
				},
				components:{
					'cmt-box':comentBox
				}
			})
		</script>
	</body>
</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值