17 Vue组件化编程

104 阅读6分钟

模块与组件、模块化与组件化

image.png

image.png

模块

a理解:向外提供特定功能的 js 程序,一般就是一个 js 文件  
b为什么:js 文件很多很复杂  
c作用:复用、简化 js 的编写,提高 js 运行效率

组件

a定义:用来实现局部功能的代码和资源的集合(html/css/js/image…)  
b为什么:一个界面的功能很复杂  
c作用:复用编码,简化项目编码,提高运行效率

模块化

当应用中的 js 都以模块来编写的,那这个应用就是一个模块化的应用

组件化

当应用中的功能都是多组件的方式来编写的,那这个应用就是一个组件化的应用

组件形式

非单文件组件:一个文件中包含有 n 个组件

单文件组件:一个文件中只包含有 1 个组件

单文件组件

基本使用

1.定义组件 使用Vue.extend(options)创建,其中options和new Vue(options)时传入的options几乎一样,但也有点区别

a:el不要写,因为最终所有的组件都要经过一个vm的管理,由vm中的el才决定服务哪个容器  
b:data必须写成函数,避免组件被复用时,数据存在引用关系,data返回的事新创建的对象,data:{}返回的事一个对象,修改会有问题。

2.注册组件

a.局部注册:new Vue()的时候options传入components选项.

	new Vue({
		el: '#root',
		// 2.1注册组件school,但是没有注册student(局部注册组件)
		components: {
			school
		}
	})

b.全局注册:Vue.component('组件名',组件),注册之后全局都可以使用全局注册后的组件。

	Vue.component('student',student)‘
    ’

3.局部注册:new Vue()的时候options传入components选项.

	new Vue({
		el: '#root',
		// 2.1注册组件school,但是没有注册student(局部注册组件)
		components: {
			school
		}
	})

b.全局注册:Vue.component('组件名',组件),注册之后全局都可以使用全局注册后的组件。

	Vue.component('student',student)

3.使用组件

编写组件标签如 <school></school>
<!DOCTYPE html>
<html>

<head>
	<meta charset="UTF-8" />
	<title>非单文件组件</title>
</head>
<script type="text/javascript" src="../js/vue.js"></script>

<body>
	<div id="root">
		<h2>{{msg}}</h2>
		<!-- 组件标签 -->
		<school></school>
		<student></student>
		<hello></hello>
	</div>
</body>
<script type="text/javascript">
	Vue.config.productionTip = false


	//创建shcool组件
	const school = Vue.extend({
		//el:'#root,//组件定义时一定不要写el配置项。
		//应为最终所以的组件都要被一个vm管理,由vm决定那个容器
		template: `
				<div class="demo">
					<h3>学校名称:{{schoolName}}</h3>
					<h3>学校地址:{{address}}</h3>
					<button @click="showName">点我提示学校名</button>	
  			</div>`,
		data() {
			return {
				schoolName: '尚硅谷',
				address: '北京昌平'
			}
		},
		methods: {
			showName() {
				alert(this.schoolName)
			}
		}
	})

	//创建shcool组件
	const student = Vue.extend({
		//el:'#root,//组件定义时一定不要写el配置项。
		//应为最终所以的组件都要被一个vm管理,由vm决定那个容器
		template: `
		<div>
					<h3>学生姓名:{{studentName}}</h3>
					<h3>学生年龄:{{age}}</h3>
  			</div>`,
		data() {
			return {
				studentName: '张三',
				age: 18
			}
		},
		methods: {
			showName() {
				alert(this.schoolName)
			}
		}
	})

	//创建hello组件
	const hello = Vue.extend({
		//el:'#root,//组件定义时一定不要写el配置项。
		//应为最终所以的组件都要被一个vm管理,由vm决定那个容器
		template: `
				<div>	
					<h3>你好啊!{{name}}</h3>
  			</div>
			`,
		data() {
			return {
				name: 'cess',
			}
		}
	})


	//创建vm
	new Vue({
		el: '#root',
		data: {
			msg: '你好啊'
		},
		components: {
			school,
			student
			// 
		}
	})

</script>

</html>

image.png

组件注意事项

关于组件名

●一个单词组成
○第一种写法(首字母小写):school
○第二种写法(首字母大写):School
●多个单词组成
○kebab-case:横杆分隔。vue展示的组件名称会 大写字母 my-school Vue:展示 My-School ○CamelCase:大驼峰(需要Vue脚手架支持),不用脚手架会回报错,无法识别组件名称。 MySchool

●备注
1、组件名尽可能回避HTML中已有的元素名称,例如:h2、H2都不行
2、可以使用name配置项指定组件在开发者工具中呈现的名字

关于组件标签

●第一种写法:
●第二种写法:(需要Vue脚手架支持)
●备注:不使用脚手架时,会导致后续组件不能渲染
一个简写方式:const school = Vue.extend(options)可简写为const school = options,因为父组件components引入的时候会自动创建

组件的嵌套

image.png

<!DOCTYPE html>
<html>

<head>
	<meta charset="UTF-8" />
	<title>几个注意点</title>
</head>
<script type="text/javascript" src="../js/vue.js"></script>

<body>
	<div id="root">
		<app></app>
	</div>
</body>
<script type="text/javascript">
	Vue.config.productionTip = false


	const student = Vue.extend({
		name: 'student',
		template: `
				<div class="demo">
					<h3>学校名称:{{schoolName}}</h3>
					<h3>学校地址:{{address}}</h3>
  			</div>`,
		data() {
			return {
				schoolName: '尚硅谷',
				address: '北京昌平'
			}
		}
	})

	const school = Vue.extend({
		name: 'school',
		template: `
				<div class="demo">
					<h3>学校名称:{{schoolName}}</h3>
					<h3>学校地址:{{address}}</h3>
					//加载子组件
					<student></student>
  			</div>`,
		data() {
			return {
				schoolName: '尚硅谷',
				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({
		el: '#root',
		data: {
			msg: '你好啊'
		},
		//注册组件
		components: {
			app
		}
	})

</script>

</html>

image.png

组件的嵌套:

创建组件
const school = Vue.extend({
  name'组件名称',
  template`模版`,
  data() {
    return {
      propertyName'propertyValue'
    }
  },
  //注册子组件
  components: {
     子组件    
  }
})

1、template 中包含子组件的标签的使用。 2、components:注册对应的子组件。

VueComponent

关于 VueComponent

a.school 组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,而是 Vue.extend() 生成的  

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

c每次调用Vue.extend,返回的都是一个全新的VueComponent,即不同组件是不同的对象  

d关于 this 指向  

   ⅰ:组件配置中data函数、methods中的函数、watch中的函数、computed中的函数 它们的 this 均是 VueComponent实例对象  
   ⅱ:new Vue(options)配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的 this 均是 Vue实例对象  

e:VueComponent的实例对象,以后简称vc(组件实例对象)Vue的实例对象,以后简称vm
<!DOCTYPE html>
<html>

<head>
	<meta charset="UTF-8" />
	<title>VueComponet</title>
</head>
<script type="text/javascript" src="../js/vue.js"></script>

<body>
	<div id="root">
		<!-- 不同的组件对应不同的VueComponet实例 -->
		<school></school>
		<hello></hello>
	</div>
</body>
<script type="text/javascript">
	Vue.config.productionTip = false
	//组件
	const school = Vue.extend({
		name: 'school',
		template: `
				<div class="demo">
					<h3>学校名称:{{schoolName}}</h3>
					<h3>学校地址:{{address}}</h3>
					<button @click="showName">点我提示学校名</button>
  			</div>`,
		data() {
			return {
				schoolName: '尚硅谷',
				address: '北京昌平'
			}
		},
		methods:{
			showName(){
				alert(this.schoolName,this )
			}
		}
	})
	//组件
	const hello = Vue.extend({
		template:'<h2>{{msg}}</h2>',
		data(){
			return {
				msg:'你好啊'
			}
		}
	})
	//查看组件类型,每一次 Vue.extend都会创建一个VueComponent实例
	console.log(school)
	//组件本质:函数VueComponent
	// VueComponent(options) {
    //           this._init(options);
    //       }
	
	//创建vm
	new Vue({
		el: '#root',
		//注册组件
		components: {
			school,hello
		}
	})
</script>
</html>

重要的内置关系

image.png

1一个重要的内置关系:VueComponent.prototype.proto === Vue.prototype
2为什么要有这个关系:让组件实例对象vc可以访问到 Vue原型上的属性、方法

<!DOCTYPE html>
<html>

<head>
	<meta charset="UTF-8" />
	<title>VueComponet</title>
</head>
<script type="text/javascript" src="../js/vue.js"></script>

<body>
	<div id="root">
		<!-- 1一个重要的内置关系VueComppnent.prototype.__proto__===Vue.prototype -->
		<school></school>
	</div>
</body>
<script type="text/javascript">
	Vue.config.productionTip = false
	// 添加内置属性
	Vue.prototype.x = 99
	//组件
	const school = Vue.extend({
		name: 'school',
		template: `
				<div class="demo">
					<h3>学校名称:{{schoolName}}</h3>
					<h3>学校地址:{{address}}</h3>
					<button @click='shows'>学校地址:{{address}}</button>
  			</div>`,
		data() {
			return {
				schoolName: '尚硅谷',
				address: '北京昌平'
			}
		},
		methods:{
			shows(){
				console.log(this.x)
			}
		}
	})
	//闯将一个vm
	new Vue({
		el:'#root',
		data:{
			msg:'你好'
		},
		components:{school}
	})
	//true
	console.log(school.prototype.__proto__===Vue.prototype);
</script>
</html>

单文件组件

School.vue

<template>
    <div class="demo">
					<h3>学校名称:{{schoolName}}</h3>
					<h3>学校地址:{{address}}</h3>
					<button @click="showName">点我提示学校名</button>	
  			</div>
</template>

<script>
   export default {
		name:'School',
		data() {
			return {
				schoolName: '尚硅谷',
				address: '北京昌平'
			}
		},
		methods: {
			showName() {
				alert(this.schoolName)
			}
		}
	}
</script>

<style>
	.demo{
		background-color:orange;
	}
</style>


Student.vue

<template>
    <div class="demo">
					<h3>学生名称:{{name}}</h3>
					<h3>学生年龄:{{age}}</h3>
  			</div>
</template>

<script>
   export default {
		name:'School',
		data() {
			return {
				name: 'sx',
				age: 18
			}
		}
	}
</script>

<style>
	.demo{
		background-color:orange;
	}
</style>


App.vue

<template>
	<div>
		<School>
		</School>
		<Student></Student>
	</div>
</template>

<script>
import School from './School'
import Student from './Student'
export default {
	name:'app',
	components:{
		School,
		Student
	}
}
</script>

main.js

import App from './App.vue'
new vue({
	el:'#root',
	template:'<App></App>',
	components:{
		app
	}
})

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>练习单文件组件语法</title>
</head>
<body>
    <div id = 'root'>
    </div>
    <script type="text/javascript" src="../js/vue.js"></script>
    <script type="text/javascript" src="./main.js"></script>
</body>
</html>