• Vue.js的组件化思想--上


    Vue.js的组件化思想--上

     

    一、Vue中的组件

    Vue视图层的灵魂 —  组件化

    组件(Component)是 Vue.js 最强大的功能之一;

    组件可以扩展 HTML 元素,封装可重用的代码;

    在较高层面上,组件是自定义元素, Vue.js 的编译器为它添加特殊功能。在有些情况下,组件也可以是原生 HTML 元素的形式,以 is 特性扩展。

    二、全局组件的创建和注册

     全局组件-步骤:1.创建组件Vue.extend(),指定组件的名称--2.注册组件Vue.component()--3.挂载作用域下实例化

    案例代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>全局组件</title>
    </head>
    <body>
    <div id="app">
        <my-date></my-date>    
        <my-date></my-date>    
    </div>
    <hr>
    <div id="app1">
        <my-date></my-date>    
        <my-date></my-date>    
    </div>
    
    <script_top src="js/vue.js"></script_top>
    <script_top>
    // 全局组件-步骤:1.创建组件Vue.extend(),指定组件的名称--2.注册组件Vue.component()--3.挂载作用域下实例化
        // 1.创建组件
        let Profile = Vue.extend({
            template:`
                <div>
                    <input    type='date'>
                    <p>今天已经是夏天了</p>
                </div>`
        });
    
        // 2.注册组件,指定组件的名称
        Vue.component('my-date',Profile);
        // 3.挂载作用域下实例化
    
    
    
        new Vue({
            el:'#app',
            data:{
            }
        });
        new Vue({
            el:'#app1',
            data:{
            }
        })
    </script_top>
    </body>
    </html>

    运行结果:

    调用Vue.extend()创建的是一个组件构造器,构造器有一个选项对象,选项对象的template属性用于定义组件要渲染的HTML;

      

    调用Vue.component()注册组件时,需要提供2个参数:组件的标签名 和 组件构造器;注册的组件要挂载到某个Vue实例下,否则它不会生效;

      

    Vue.extend() 和 Vue.component():由于 Vue 本身是一个构造函数,Vue.extend() 是一个类继承方法,它用来创建一个 Vue 的子类并返回其构造函数;

      

    而Vue.component() 的作用在于:建立指定的构造函数与 ID 字符串间的关系,从而让 Vue.js 能在模板中使用它;直接向 Vue.component() 传递 options 时,它会在内部调用 Vue.extend()。

    三、局部组件的创建和注册

    案例代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
    	<meta charset="UTF-8">
    	<title>Document</title>
    </head>
    <body>
    <div id="app">
        <my_date></my_date>
        <my_color></my_color>
    </div>
    <script_top src="js/vue.js"></script_top>
    <script_top>
    	// 1.创建组件
    	let Profile = Vue.extend({
    		template:`
    			<div>
    				<input	type='date'>
    				<p>今天已经是夏天了</p>
    			</div>`
    	});
    
    	// 可以拥有多个局部组件
    	let Profile2 = Vue.extend({
    		template:`
    			<div>
    				<input	type='color'>
    				<p我是一个色板</p>
    			</div>`
    	});
    
    	new Vue({
    		el:'#app',
    		// 2.注册组件,指定组件的名称.
    		// 注意:局部组件一定要加s
    		components:{
    			'my_date':Profile,
    			'my_color':Profile2
    		}
    	})
    </script_top>
    </body>
    </html>
    

      

    运行结果:

     局部组件只能在局部作用域调用:否则会报错!

    <!DOCTYPE html>
    <html lang="en">
    <head>
    	<meta charset="UTF-8">
    	<title>局部组件只能在局部作用域调用</title>
    </head>
    <body>
    <div id="app">
        <my_date></my_date>
        <my_color></my_color>
    </div>
    <hr>
    <div id="app1">
        <my_date></my_date>
        <my_color></my_color>
    </div>
    <script_top src="js/vue.js"></script_top>
    <script_top>
    	// 1.创建组件
    	let Profile = Vue.extend({
    		template:`
    			<div>
    				<input	type='date'>
    				<p>今天已经是夏天了</p>
    			</div>`
    	});
    
    	// 可以拥有多个局部组件
    	let Profile2 = Vue.extend({
    		template:`
    			<div>
    				<input	type='color'>
    				<p我是一个色板</p>
    			</div>`
    	});
    
    	new Vue({
    		el:'#app',
    		// 2.注册组件,指定组件的名称.
    		// 注意:局部组件一定要加s
    		components:{
    			'my_date':Profile,
    			'my_color':Profile2
    		}
    	})
    	// 局部组件只能在局部作用域调用
    	new Vue({
    		el:'#app1'
    	})
    </script_top>
    </body>
    </html>
    

      

    运行结果:

    四、另一种组件创建和注册方式

     

    直接通过Vue.component注册或获取全局组件,主要体现在以下几种方式:

    // 注册组件,传入一个扩展过的构造器

    Vue.component('my-component', Vue.extend({ /* ... */ }))

    // 注册组件,传入一个选项对象(自动调用 Vue.extend)

    Vue.component('my-component', { /* ... */ })

    // 获取注册的组件(始终返回构造器)

    var MyComponent = Vue.component('my-component') 

    4.1  自定义全局组件

    第二种写法。(第一步、第二步写在一起。)

    <!DOCTYPE html>
    <html lang="en">
    <head>
    	<meta charset="UTF-8">
    	<title>全局组件</title>
    </head>
    <body>
    <div id="app">
        <my-date></my-date>	
        <my-date></my-date>	
    </div>
    <hr>
    <div id="app1">
        <my-date></my-date>	
        <my-date></my-date>	
    </div>
    
    <script_top src="js/vue.js"></script_top>
    <script_top>
    // 全局组件-步骤:1.创建组件Vue.extend(),指定组件的名称--2.注册组件Vue.component()--3.挂载作用域下实例化
    	// 1.创建组件
    	// 2.注册组件,指定组件的名称
    	Vue.component('my-date',{
    		// 模板选项
    		template:`
    			<div>
    				<input	type='date'>
    				<p>今天已经是夏天了</p>
    			</div>`
    	});
    	
    
    
    
    	new Vue({
    		el:'#app',
    		data:{
    		}
    	});
    	new Vue({
    		el:'#app1',
    		data:{
    		}
    	})
    </script_top>
    </body>
    </html>
    

    4.2  自定义局部组件

    <!DOCTYPE html>
    <html lang="en">
    <head>
    	<meta charset="UTF-8">
    	<title>局部组件写法2</title>
    </head>
    <body>
    <div id="app">
        <my_date></my_date>
        <my_color></my_color>
    </div>
    <hr>
    <div id="app1">
        <my_date></my_date>
        <my_color></my_color>
    </div>
    <script_top src="js/vue.js"></script_top>
    <script_top>
    	new Vue({
    		el:'#app',
    		// 2.注册组件,指定组件的名称.
    		// 注意:局部组件一定要加s
    		components:{
    			'my_date':{
    				template:`
    					<div>
    						<input	type='date'>
    						<p>今天已经是夏天了</p>
    					</div>`
    			},
    			'my_color':{
    				template:`
    					<div>
    						<input	type='color'>
    						<p我是一个色板</p>
    					</div>`
    			}
    		}
    	})
    </script_top>
    </body>
    </html>
    

      

    五、父子组件

          组件意味着协同工作,通常父子组件会是这样的关系:组件 A 在它的模版中使用了组件 B 。

    最简单的父子组件:

    <!DOCTYPE html>
    <html lang="en">
    <head>
    	<meta charset="UTF-8">
    	<title>Document</title>
    </head>
    <body>
    <div id="app">
        <parent></parent>
    
        <child></child>	
    </div>
    <script_top src="js/vue.js"></script_top>
    <script_top>
    	// 1.子组件构造器
    	let Child1 = Vue.extend({
    		template:`<img src="./img/1.jpg" width="200" />`,
    	});
    
    	let Child2 = Vue.extend({
    		template:`<p>我是美女哦!</p>`,
    	});
    	// 全局组件component
    	Vue.component('child',Child1);
    	// 2.父组件构造器  
    	Vue.component('parent',{
    		//局部组件components
    		components:{
    			'my_child1':Child1,
    			'my_child2':Child2
    		},
    		template:`
    			<div>
    				<my_child1></my_child1>
    				<my_child2></my_child2>		
    			</div>
    		`
    	});
    
    
    	new Vue({
    		el:'#app',
    	})
    </script_top>
    </body>
    </html>
    

      运行结果:

    在父子组件组合使用中要注意以下一些问题:
    1.没有实例化的子组件不能拿出来单独使用!
    2.在父标签内部嵌套子标签!
    因为在父标签一旦生成真实的DOM,其内部的子标签就会被解析成为普通的HTML标签来执行,而且<child-component>不是标准的HTML标签,会被浏览器过滤掉。

    六、在组件上绑定Class和Style

           数据绑定一个常见需求是操作元素的 class 列表和它的内联样式。因为它们都是属性 ,我们可以用v-bind 处理它们:只需要计算出表达式最终的字符串。

            而且,把 v-bind 用于 class 和 style 时,表达式的结果类型除了字符串之外,还可以是对象或数组。

    案例代码:

     

    七、template和script_top标签

           尽管在上面组件的组件注册的方式已经很简单,但是在template选项中拼接HTML的标签还是不符合常规的编程习惯,而且HTML元素和js代码混杂在一起造成了很大的耦合性。

     

           那么,template和script_top标签可以帮助我们将定义在JS中的HTML模板分离出来。

     

    注意: 两种注册方式效果一样,官方建议用第一种。

    (1)使用template标签注册组件:

    <!DOCTYPE html>
    <html lang="en">
    <head>
    	<meta charset="UTF-8">
    	<title>Document</title>
    </head>
    <body>
    <div id="app">
        <my-div></my-div>
    </div>
    
    <hr> 
    
    <template id="my_div">
    		<div>我是贝贝</div>
    </template>
    
    <script_top src="js/vue.js"></script_top>
    <script_top>
    
    	// 1.实例化组件  全局组件component
    	Vue.component('my-div',{
    		template:'#my_div'
    	})
    
    	new Vue({
    		el:'#app',
    	})
    </script_top>
    </body>
    </html>
    

      

    运行结果:

    注意:必须只有一个出口文件,否则会报错!

    (2)使用script_top标签注册组件:

    <!DOCTYPE html>
    <html lang="en">
    <head>
    	<meta charset="UTF-8">
    	<title>Document</title>
    </head>
    <body>
    <div id="app">
        <my-div></my-div>
    </div>
    <script_top type="text/template" id="my_div">
    	<!-- 注意必须只有一个出口文件,否则会报错 -->
    	<div>
    		<img src="./img/1.jpg" width="200">
    		<div>我是美女哦!</div>
    	</div>
    </script_top>
    
    <script_top src="js/vue.js"></script_top>
    <script_top>
    	// 1.实例化组件  全局组件component
    	Vue.component('my-div',{
    		template:'#my_div'
    	});
    	new Vue({
    		el:'#app',
    	})
    </script_top>
    </body>
    </html>
    

     
    注意:使用<script_top>标签时,type指定为text/x-template,意在告诉浏览器这不是一段js脚本,浏览器在解析HTML文档时会忽略<script_top>标签内定义的内容。

    八、挂载选项data必须是函数

            使用组件时,大多数可以传入到 Vue 构造器中的选项可以在 Vue.extend() 或Vue.component()中注册组件时使用,但有一个重要前提: data 必须是函数

    下面代码会出现的问题:

    <!DOCTYPE html>
    <html lang="en">
    <head>
    	<meta charset="UTF-8">
    	<title>Document</title>
    </head>
    <body>
    <div id="app">
        <my-div></my-div>
    </div>
    <script_top type="text/template" id="my_div">
    	<!-- 注意必须只有一个出口文件,否则会报错 -->
    	<div>
    		<img src="./img/1.jpg" width="200">
    		<p>我是美女哦!</p>
    		<p>{{message}}</p>
    	</div>
    </script_top>
    
    <script_top src="js/vue.js"></script_top>
    <script_top>
    	// 1.实例化组件  全局组件component
    	Vue.component('my-div',{
    		template:'#my_div',
    		data:{
    			message:'我的贝贝'
    		}
    	});
    	new Vue({
    		el:'#app',
    	})
    </script_top>
    </body>
    </html>
    

      

    正确的写法:

    <!DOCTYPE html>
    <html lang="en">
    <head>
    	<meta charset="UTF-8">
    	<title>Document</title>
    </head>
    <body>
    <div id="app">
        <my-div></my-div>
    </div>
    <script_top type="text/template" id="my_div">
    	<!-- 注意必须只有一个出口文件,否则会报错 -->
    	<div>
    		<img src="./img/1.jpg" width="200">
    		<p>我是美女哦!</p>
    		<p>{{message}}</p>
    	</div>
    </script_top>
    
    <script_top src="js/vue.js"></script_top>
    <script_top>
    	// 1.实例化组件  全局组件component
    	Vue.component('my-div',{
    		template:'#my_div',
    		/*data:{
    			message:'我的贝贝'
    		}*/
    		// 挂载组件data必须是个函数。
    		data(){
    			return {message:'我的贝贝'}
    		}
    	});
    	new Vue({
    		el:'#app',
    	})
    </script_top>
    </body>
    </html>
    

      

     运行结果:

    注意:如果data选项指向某个对象,这意味着所有的组件实例共用一个data。

    我们应当使用一个函数作为 data 选项,让这个函数返回一个新对象。

     

    运行结果:这三个组件共享了同一个 data , 因此增加一个 counter 会影响所有组件!

    解决办法:为每个组件返回新的 data 对象来解决这个问题!

    data: function () {

                return {

                    counter: 0

                }

            }

    <!DOCTYPE html>
    <html lang="en">
    <head>
    	<meta charset="UTF-8">
    	<title>验证data必须是函数</title>
    </head>
    <body>
    <div id="app">
    	<!-- data必须是函数:内容不会共享,每次都是独立的。 -->
        <my-btn></my-btn>
        <my-btn></my-btn>
        <my-btn></my-btn>
        <my-btn></my-btn>
    </div>
    
    <template id="my_btn">
    	<!-- v-on @ -->
    	<button @click="counter+=1">点击次数:{{counter}}</button>
    </template>
    
    <script_top src="js/vue.js"></script_top>
    <script_top>
    	// 1.实例化组件
    	Vue.component('my-btn',{
    		template:'#my_btn',
    		data(){
    			return {counter:0}
    		}
    	});
    
    	new Vue({
    		el:'#app'
    	})
    </script_top>
    </body>
    </html>
    

      

    运行结果:

     
     
  • 相关阅读:
    USACO2018 DEC(Platinum) (树上乱搞,期望+凸包)
    USACO2018 DEC (Gold) (dp,容斥+哈希,最短路)
    《信息学奥赛一本通》题库 1034 计算三角形面积——基础
    UNR#3 Day1——[ 堆+ST表+复杂度分析 ][ 结论 ][ 线段树合并 ]
    bzoj 4298 [ONTAK2015]Bajtocja——哈希+启发式合并
    玲珑杯#20 C 漆黑的太阳——莫队
    链表写法
    传址函数写法
    bzoj 4650 & 洛谷 P1117 优秀的拆分 —— 枚举关键点+后缀数组
    bzoj 2119 股市的预测 —— 枚举关键点+后缀数组
  • 原文地址:https://www.cnblogs.com/yimiflh/p/9280618.html
Copyright © 2020-2023  润新知