VUE学习(十一)、组件——非单文件组件、单文件组件

VUE学习(十一)、组件——非单文件组件、单文件组件

一、非单文件组件

一个文件包含有n个组件

1、基本使用

<body>
	<!-- 
		Vue中使用组件的三大步骤:
			一、定义组件(创建组件)
			二、注册组件
			三、使用组件(写组件标签)

		一、如何定义一个组件?
				使用Vue.extend(options)创建,其中options和new Vue(options)时传入的那个options几乎一样,但也有点区别;
				区别如下:
					1.el不要写,为什么? ——— 最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器。
					2.data必须写成函数,为什么? ———— 避免组件被复用时,数据存在引用关系。
				备注:使用template可以配置组件结构。

		二、如何注册组件?
			1.局部注册:靠new Vue的时候传入components选项
			2.全局注册:靠Vue.component('组件名',组件)

		三、编写组件标签:
			<school></school>
	-->
	<!-- 准备好一个容器-->
	<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>
		`,
		// el:'#root', //组件定义时,一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器。
		data() {
			return {
				schoolName: "xxx大学",
				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': school,
			student //简写
		}
	});

	new Vue({
		el: "#root2"
	});
</script>

2、注意点

<body>
	<!-- 
		几个注意点:
			1.关于组件名:
				一个单词组成:
					第一种写法(首字母小写):school
					第二种写法(首字母大写):School
				多个单词组成:
					第一种写法(kebab-case命名):my-school
					第二种写法(CamelCase命名):MySchool (需要Vue脚手架支持)
				备注:
					(1).组件名尽可能回避HTML中已有的元素名称,例如:h2、H2都不行。
					(2).可以使用name配置项指定组件在开发者工具中呈现的名字。

			2.关于组件标签:
				第一种写法:<school></school>
				第二种写法:<school/>
				备注:不用使用脚手架时,<school/>会导致后续组件不能渲染。(多次使用只能渲染第一次的)

			3.一个简写方式:
				const school = Vue.extend(options) 可简写为:const school = options
	-->
	<!-- 准备好一个容器-->
	<div id="root">
		<h1>{{msg}}</h1>
		<school></school>
	</div>
</body>

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

	//定义组件
	const s = Vue.extend({
		name: "myname", //使用name配置项指定组件在开发者工具中呈现的名字
		template: `
			<div>
				<h2>学校名称:{{name}}</h2>	
				<h2>学校地址:{{address}}</h2>	
			</div>
		`,
		data() {
			return {
				name: "xx大学",
				address: "云南"
			};
		}
	});

	new Vue({
		el: "#root",
		data: {
			msg: "欢迎学习Vue!"
		},
		components: {
			school: s
		}
	});
</script>

3、组件的嵌套

<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:'xxx大学',
				age:18
			}
		}
	})
	
	//定义school组件
	const school = Vue.extend({
		name:'school',
		template:`
			<div>
				<h2>学校名称:{{name}}</h2>	
				<h2>学校地址:{{address}}</h2>	
				<student></student>
			</div>
		`,
		data(){
			return {
				name:'xxx大学',
				address:'北京'
			}
		},
		//注册组件(局部)
		components:{
			student
		}
	})

	//定义hello组件
	const hello = Vue.extend({
		template:`<h1>{{msg}}</h1>`,
		data(){
			return {
				msg:'欢迎来到xxx大学学习!'
			}
		}
	})
	
	//定义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>

4、VueComponent

<body>
	<!-- 
		关于VueComponent:
			1.school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的。

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

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

			4.关于this指向:
				(1).组件配置中:
					data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【VueComponent实例对象】。
				(2).new Vue(options)配置中:
					data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【Vue实例对象】。

			5.VueComponent的实例对象,以后简称vc(也可称之为:组件实例对象)。
				Vue的实例对象,以后简称vm。
	-->
	<!-- 准备好一个容器-->
	<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:`
			<div>
				<h2>学校名称:{{name}}</h2>	
				<h2>学校地址:{{address}}</h2>	
				<button @click="showName">点我提示学校名</button>
			</div>
		`,
		data(){
			return {
				name:'xxx大学',
				address:'北京'
			}
		},
		methods: {
			showName(){
				console.log('showName',this)
			}
		},
	})

	const test = Vue.extend({
		template:`<span>atguigu</span>`
	})

	//定义hello组件
	const hello = Vue.extend({
		template:`
			<div>
				<h2>{{msg}}</h2>
				<test></test>	
			</div>
		`,
		data(){
			return {
				msg:'你好啊!'
			}
		},
		components:{test}
	})


	// console.log('@',school)
	// console.log('#',hello)

	//创建vm
	const vm = new Vue({
		el:'#root',
		components:{school,hello}
	})
</script>

5、 一个重要的内置关系

<body>
	<!-- 
			1.一个重要的内置关系:VueComponent.prototype.__proto__ === Vue.prototype
			2.为什么要有这个关系:让组件实例对象(vc)可以访问到 Vue原型上的属性、方法。
	-->
	<!-- 准备好一个容器-->
	<div id="root">
		<school></school>
	</div>
</body>

<script type="text/javascript">
	Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
	Vue.prototype.x = 99

	//定义school组件
	const school = Vue.extend({
		name:'school',
		template:`
			<div>
				<h2>学校名称:{{name}}</h2>	
				<h2>学校地址:{{address}}</h2>	
				<button @click="showX">点我输出x</button>
			</div>
		`,
		data(){
			return {
				name:'xxx大学',
				address:'北京'
			}
		},
		methods: {
			showX(){
				console.log(this.x)
			}
		},
	})

	//创建一个vm
	const vm = new Vue({
		el:'#root',
		data:{
			msg:'你好'
		},
		components:{school}
	})

	
	//定义一个构造函数
	/* function Demo(){
		this.a = 1
		this.b = 2
	}
	//创建一个Demo的实例对象
	const d = new Demo()

	console.log(Demo.prototype) //显示原型属性

	console.log(d.__proto__) //隐式原型属性

	console.log(Demo.prototype === d.__proto__)

	//程序员通过显示原型属性操作原型对象,追加一个x属性,值为99
	Demo.prototype.x = 99

	console.log('@',d) */

</script>

二、单文件组件

一个文件中只包含1个组件

1、School.vue

<template>
    <!-- template组件的结构 -->
    <div class="demo">
        <h2>学校名称:{{ name }}</h2>
        <h2>学校地址:{{ address }}</h2>
        <button @click="showName">点我提示学校名</button>
    </div>
</template>

<script>
//组件交互相关的代码
// 暴露相关知识 ES6模块化
// 第一种暴露方式(分别暴露)引入:import {xxx} from xxx
export const school = Vue.extend({
    data() {
        return {
            name: "xxx大学",
            address: "北京昌平"
        };
    },
    methods: {
        showName() {
            alert(this.name);
        }
    }
});

/*
// 第二种暴露方式(统一暴露)引入:import {xxx} from xxx
export { school };
// 第三种暴露方式(默认暴露)(一般用这个)引入:import xxx from xxx
export default school
// 默认暴露简写
export default Vue.extend({
    name: "School",
    data() {
        return {
            name: "xxx大学",
            address: "北京昌平"
        };
    },
    methods: {
        showName() {
            alert(this.name);
        }
    }
})
// 或者
export default{
	name: "School",
    data() {
        return {
            name: "xxx大学",
            address: "北京昌平"
        };
    },
    methods: {
        showName() {
            alert(this.name);
        }
    }
}

*/
</script>

<style>
/* 组件的样式 */
.demo {
    background-color: orange;
}
</style>

2、Student.vue

<template>
	<div>
		<h2>学生姓名:{{name}}</h2>
		<h2>学生年龄:{{age}}</h2>
	</div>
</template>

<script>
	 export default {
		name:'Student',
		data(){
			return {
				name:'张三',
				age:18
			}
		}
	}
</script>

3、main.js

// 浏览器不支持模块化语法,需要脚手架才能运行
import App from "./App.vue";

new Vue({
    el: "#root",
    template: `<App></App>`,
    components: { App }
});

4、index.html

<!DOCTYPE html>
<html>
    <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>
	<script src="../js/vue.js"></script>
	<script src="./main.js"></script>
</html>

推荐阅读

VUE笔记文章列表

1、VUE学习(一)、基于简单js引入的Vue快速入门——简单实例使用_醉瑾_的博客-CSDN博客

2、VUE学习(二)、计算属性vs侦听属性——基于案例的对比_醉瑾_的博客-CSDN博客

3、VUE学习(三)、绑定样式——class和style_醉瑾_的博客-CSDN博客

4、VUE学习(四)、条件渲染——v-if与v-show_醉瑾_的博客-CSDN博客

5、VUE学习(五)、列表渲染之:key原理、列表过滤、列表排序_醉瑾_的博客-CSDN博客

6、VUE学习(六)、vue 监测数据改变原理_醉瑾_的博客-CSDN博客

7、VUE学习(七)、收集表单数据_醉瑾_的博客-CSDN博客

8、VUE学习(八)、过滤器_醉瑾_的博客-CSDN博客

9、VUE学习(九)、内置指令、自定义指令_醉瑾_的博客-CSDN博客

10、VUE学习(十)、生命周期_醉瑾_的博客-CSDN博客

11、VUE学习(十一)、组件——非单文件组件、单文件组件_醉瑾_的博客-CSDN博客

12、VUE学习(十二)、vue脚手架的使用_醉瑾_的博客-CSDN博客

13、VUE学习(十三)、ref属性、props配置项、minix混入、自定义插件、scoped样式_醉瑾_的博客-CSDN博客

14、VUE学习(十四)、TodoList案例(基于props实现组件间通信通)_醉瑾_的博客-CSDN博客

15、VUE学习(十五)、组件自定义事件及todoList案例自定义事件完成_醉瑾_的博客-CSDN博客

16、VUE学习(十六)、全局事件总线及TodoList案例事件总线实现_醉瑾_的博客-CSDN博客

17、VUE学习(十七)、Vue封装的过度与动画_醉瑾_的博客-CSDN博客

18、VUE学习(十八)、VUE脚手架配置代理_醉瑾_的博客-CSDN博客

19、VUE学习(十九)、Github用户搜索案例_醉瑾_的博客-CSDN博客

20、VUE学习(二十)、插槽_醉瑾_的博客-CSDN博客

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

心醉瑶瑾前

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值