vue组件基础知识

323 阅读4分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第22天,点击查看活动详情

非单文件组件

非单文件组件就是一个文件里面有n个组件 n>1

Vue中使用组件的三大步骤:

一、定义组件(创建组件)

使用Vue.extend(options)创建,其中options和new Vue(options)时传入的那个options几乎一样,但也有点区别;

区别如下:

  • el不要写,为什么? ——— 最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器。
  • data必须写成函数,为什么? ———— 避免组件被复用时,数据存在引用关系。

备注:使用template可以配置组件结构。

//第一步:创建school组件
		const school = Vue.extend({
			template:`
				<div class="demo">
					<h2>学校名称:{{schoolName}}</h2>
					<h2>学校地址:{{address}}</h2>
					<button @click="showName">点我提示学校名</button>	
				</div>
			`,
// el:'#root', //组件定义时,一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器。
			data(){
				return {
					schoolName:'gcshi',
					address:'陕西西安'
				}
			},
			methods: {
				showName(){
					alert(this.schoolName)
				}
			},
		})

二、注册组件

局部注册

靠new Vue的时候传入components选项

new Vue({
		el:'#root',
		data:{
			msg:'你好啊!'
		},
		//第二步:注册组件(局部注册)
		components:{
			school,
		}
})

全局注册

靠Vue.component('组件名',组件)

//第一步:创建hello组件
		const hello = Vue.extend({
			template:`
				<div>	
					<h2>你好啊!{{name}}</h2>
				</div>
			`,
			data(){
				return {
					name:'Tom'
				}
			}
		})
		
//第二步:全局注册组件
  Vue.component('hello',hello)

三、使用组件(写组件标签)

vue.js为源码文件,以下文件直接进行了本地引入

链接:pan.baidu.com/s/1D8p8Ywxf…

提取码:lhgv

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>基本使用</title>
		<script type="text/javascript" src="../js/vue.js"></script>
	</head>
	<body>
		<!-- 准备好一个容器-->
		<div id="root">
      <!-- 第三步:编写组件标签 -->
			<hello></hello>
			<hr>
			<h1>{{msg}}</h1>
			<hr>
			<!-- 第三步:编写组件标签 -->
			<school></school>
			<hr>
			<!-- 第三步:编写组件标签 -->
			<student></student>
		</div>

		<div id="root2">
			<hello></hello>
		</div>
	</body>

	<script type="text/javascript">
		Vue.config.productionTip = false

		//第一步:创建school组件
		const school = Vue.extend({
			template:`
				<div class="demo">
					<h2>学校名称:{{schoolName}}</h2>
					<h2>学校地址:{{address}}</h2>
					<button @click="showName">点我提示学校名</button>	
				</div>
			`,
			data(){
				return {
					schoolName:'尚硅谷',
					address:'北京昌平'
				}
			},
			methods: {
				showName(){
					alert(this.schoolName)
				}
			},
		})

		//第一步:创建student组件
		const student = Vue.extend({
			template:`
				<div>
					<h2>学生姓名:{{studentName}}</h2>
					<h2>学生年龄:{{age}}</h2>
				</div>
			`,
			data(){
				return {
					studentName:'张三',
					age:18
				}
			}
		})
		
		//第一步:创建hello组件
		const hello = Vue.extend({
			template:`
				<div>	
					<h2>你好啊!{{name}}</h2>
				</div>
			`,
			data(){
				return {
					name:'Tom'
				}
			}
		})
		
		//第二步:全局注册组件
		Vue.component('hello',hello)

		//创建vm
		new Vue({
			el:'#root',
			data:{
				msg:'你好啊!'
			},
			//第二步:注册组件(局部注册)
			components:{
				school,
				student
			}
		})

		new Vue({
			el:'#root2',
		})
	</script>
</html>

组件使用注意点

关于组件名:

一个单词组成:

第一种写法(首字母小写):school

第二种写法(首字母大写):School

多个单词组成:

第一种写法(kebab-case命名):my-school

第二种写法(CamelCase命名):MySchool (需要Vue脚手架支持)

备注:

(1).组件名尽可能回避HTML中已有的元素名称,例如:h2、H2都不行。

(2).可以使用name配置项指定组件在开发者工具中呈现的名字。

关于组件标签:

第一种写法:

第二种写法: (需要使用脚手架,不用使用脚手架时,会导致后续组件不能渲染。)

一个简写方式

const school = Vue.extend(options) 可简写为:const school = options

组件的嵌套

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>组件的嵌套</title>
		<!-- 引入Vue -->
		<script type="text/javascript" src="../js/vue.js"></script>
	</head>
	<body>
		<!-- 准备好一个容器-->
		<div id="root"></div>
	</body>

	<script type="text/javascript">
		Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
		//定义student组件
		const student = Vue.extend({
			name:'student',
			template:`
				<div>
					<h2>学生姓名:{{name}}</h2>	
					<h2>学生年龄:{{age}}</h2>	
				</div>
			`,
			data(){
				return {
					name:'尚硅谷',
					age:18
				}
			}
		})
		//定义school组件
		const school = Vue.extend({
			name:'school',
			template:`
				<div>
					<h2>学校名称:{{name}}</h2>	
					<h2>学校地址:{{address}}</h2>	
					<student></student>
				</div>
			`,
			data(){
				return {
					name:'尚硅谷',
					address:'北京'
				}
			},
			//注册组件(局部)
			components:{
				student
			}
		})

		//定义hello组件
		const hello = Vue.extend({
			template:`<h1>{{msg}}</h1>`,
			data(){
				return {
					msg:'欢迎来到尚硅谷学习!'
				}
			}
		})
		
		//定义app组件
		const app = Vue.extend({
			template:`
				<div>	
					<hello></hello>
					<school></school>
				</div>
			`,
			components:{
				school,
				hello
			}
		})

		//创建vm
		new Vue({
			template:'<app></app>',
			el:'#root',
			//注册组件(局部)
			components:{app}
		})
	</script>
</html>

VueComponent

  • 组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的。
//定义school组件
		const school = Vue.extend({
			name:'school',
			template:`
				<div>
				  哈哈哈哈
				</div>
			`,
		})
console.log(school)   
//    ƒ VueComponent (options) {
//         this._init(options);
//    }

从打印结果可以看出,shool组件实际是由VueComponent构造函数所实例化出来的对象。

打断点,进入vue.js源码中,可以发现在使用 Vue.extend创建组件时,实际还在内部调用了VueComponent构造函数生成了sub实例化对象,最终将实例化对象return了出来。

  • 我们只需要写或,Vue解析时会帮我们创建school组件的实例对象,即Vue帮我们执行的:new VueComponent(options)。

  • 特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent!!!!


  • 关于this指向:
    1. 组件配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【VueComponent实例对象】。
    2. new Vue(options)配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【Vue实例对象】。
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>VueComponent</title>
		<script type="text/javascript" src="../js/vue.js"></script>
	</head>
	<body>
		<div id="root">
			<school></school>
			<hello></hello>
		</div>
	</body>

	<script type="text/javascript">
		Vue.config.productionTip = false
		
		//定义school组件
		const school = Vue.extend({
			name:'school',
			template:`
				<h1 @click="showThis">
					点击school组件
				</h1>
			`,
			methods: {
				showThis(){
					console.log('school组件',this)
				}
			},
		})
		
		const test = Vue.extend({
			template:`<h4>test子组件</h4>`
		})

		//定义hello组件
		const hello = Vue.extend({
			template:`
				<h2>
					<h4>hello组件</h4>
					<test></test>	
				</h2>
			`,
			components:{test}
		})

		//创建vm
		const vm = new Vue({
			el:'#root',
			created(){
				console.log("Vue根组件",this)
			},
			components:{school,hello}
		})
	</script>
</html>

此外。也可以看出,vue根组件管理者其他所有组件

  • VueComponent的实例对象,以后简称vc(也可称之为:组件实例对象)。Vue的实例对象,以后简称vm。

一个重要的内置关系

如图,正常情况下,VueComponent的隐式原型属性__proto__应该指向Object的原型对象,但是vue做了强制更改,使

VueComponent.prototype.proto === Vue.prototype

为什么要有这个关系:让组件实例对象(vc)可以访问到 Vue原型上的属性、方法。

vue2中


原生html中组件的使用

不使用Cli脚手架的项目中


全局使用组件(全局注册)

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>我的练习</title>
	</head>
	<body>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
		
		<div id="app">
		    <my-Button></my-Button>
 				<my-Button></my-Button>
		</div>
		
		<script type="text/javascript">
		// 定义一个名为 button-counter 的新组件
		Vue.component('MyButton', {
		  data: function () {
		    return {
		      count: 0
		    }
		  },
		  template: '<button v-on:click="count++">我被点击了{{ count }}次</button>'
		})
		 const vm = new Vue({
			el: '#app',
			data: {}
		})
		</script>
	</body>
</html>

组件名的两种命名方式

连字符:如 "my-Button",使用

驼峰式:如"MyButton",或均可。

  • 直接在 DOM (即非字符串的模板) 中使用时只有连字符是有效的,如上述例子使用会报错
  • 组件中的data必须是函数

局部使用组件(局部注册)

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>我的练习</title>
	</head>
	<body>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
		
		<div id="app">
			<b>{{hello}}</b>
		    <my-Button1></my-Button1>
		</div>
		<script type="text/javascript">
		
		const Bcomponent = {
		  data: function() {return {title: "嘿嘿!"}},
		  template: '<button>{{ title }}</button>'
		};
		
		const Pcomponent = {
		  data: function() {return {count: 9}},
		  components:{
		  	MyButton2:Bcomponent,
		  },
		  template: '<div><button>{{ count }}次数</button><my-Button2></my-Button2></div>'
		};
		
		const vm = new Vue({
			el: '#app',
			data: {hello:"你好"},
			components:{
				MyButton1:Pcomponent,
			}
		})
		</script>
	</body>
</html>

cli中组件的使用

通过cli创建的项目

全局使用组件(全局注册)

import Thecomponent from './Thecomponent.vue'
Vue.component('MyButton',Thecomponent )
const vm = new Vue({
	render:h => h(App)
}).$mount("#app")

局部使用组件(局部注册)

某一vue文件中

<template>
  <div class="app">
    <Child></Child>
  </div>
</template>
<script>
    import Child from './components/Child.vue'//静态引入
    export default {
        name:'App',
        components:{ Child:Child },
    }
</script>

Vue3中

原生html中组件的使用

不使用Cli脚手架的项目中

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>我的练习</title>
	</head>
	<body>
		<script src="https://unpkg.com/vue@next"></script>
		
		<div id="app">
			<button-counter></button-counter>
		</div>
		<script type="text/javascript">
		
		// 创建一个Vue 应用
		const app = Vue.createApp({
			data() {
			    return {
			      counter: 0
			    }
			  }
		})
	
		// 定义一个名为 button-counter 的新全局组件
		app.component('button-counter', {
		  data() {
		    return {
		      count: 0
		    }
		  },
		  template: `
		    <button @click="count++">
		      我被点击了 {{ count }} 次
		    </button>`
		})
		app.mount('#app')
	
		</script>
	</body>
</html>

vite中

全局使用组件(全局注册)

const app = Vue.createApp({...})

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

app.mount('#app')

局部使用组件(局部注册)

<template>
	<div class="app">
		<Child ></Child>
	</div>
</template>
<script>
	import Child from './components/Child.vue'//静态引入
	export default {
		name:'App',
		components:{Child},  //组件写法不变
	}
</script>

方法同vue2,不变