传统前端编程(有Vue之前)存在的问题:
依赖混乱,不易维护、代码复用率不高

组件化:
提高服用率、依赖关系清晰

所有组件归一个vm管,组件可以嵌套。

组件的定义:实现应用中局部功能代码和资源的集合
一个文件中包含有n个组件。
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>组件基本使用title>
<script src="../js/vue.js">script>
head>
<body>
<div id="root">
<h2>学校名称: {{schoolName}}h2>
<h2>学校地址:{{address}}h2>
<hr>
<h2>学生姓名: {{studentName}}h2>
<h2>学生年龄:{{age}}h2>
div>
body>
<script>
Vue.config.productionTip = false
// 创建school组件
const school = Vue.extend({
el:'#root',
data:{
schoolName:'尚硅谷',
address:'北京昌平',
studentName:'张三',
age:18,
},
})
script>
html>

组件不指定为谁服务
组件定义时,一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器。
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>组件基本使用title>
<script src="../js/vue.js">script>
head>
<body>
<div id="root">
<h2>{{ msg }}h2>
<hr>
<xuexiao>xuexiao>
<hr>
<xuesheng>xuesheng>
div>
body>
<script>
Vue.config.productionTip = false
// 第一步:创建school组件
const school = Vue.extend({
// 根只能有一个标签
template:`
学校名称: {{schoolName}}
学校地址:{{address}}
`,
// el:'#root', // 组件定义时,一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器。
data(){
return {
schoolName:'尚硅谷',
address:'北京昌平'
}
}
})
// 第一步:创建student组件
const student = Vue.extend({
template:`
学生姓名: {{studentName}}
学生年龄:{{age}}
`,
data(){
return {
studentName:'张三',
age:12
}
}
})
// 创建vm
new Vue({
el:'#root',
data:{
msg:'你好啊!',
},
// 第二步:注册组件(局部注册)
components:{
xuexiao:school,
xuesheng:student
}
})
script>
html>


学生同理了。
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>组件基本使用title>
<script src="../js/vue.js">script>
head>
<body>
<div id="root">
<hello>hello>
<h2>{{ msg }}h2>
<hr>
<school>school>
<hr>
<student>student>
<student>student>
div>
<div id="root2">
<hello>hello>
<student>student>
div>
body>
<script>
Vue.config.productionTip = false
// 第一步:创建school组件
const school = Vue.extend({
// 根只能有一个标签
template:`
学校名称: {{schoolName}}
学校地址:{{address}}
`,
// el:'#root', // 组件定义时,一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器。
data(){
return {
schoolName:'尚硅谷',
address:'北京昌平'
}
}
})
// 第一步:创建student组件
const student = Vue.extend({
template:`
学生姓名: {{studentName}}
学生年龄:{{age}}
`,
data(){
return {
studentName:'张三',
age:12
}
}
})
// 第一步:创建hello组件
const hello = Vue.extend({
template:`
你好啊:{{ name }}
`,
data(){
return {
name:'Tom',
}
},
})
//第二步:全局注册组件
Vue.component('hello',hello)
// 创建vm
new Vue({
el:'#root',
data:{
msg:'你好啊!',
},
// 第二步:注册组件(局部注册)
components:{
school, //简写
student
}
})
new Vue({
el:'#root2',
components:{
student,
}
})
script>
html>
总结:
Vue中使用组件的三大步骤:
定义组件(创建组件)
注册组件
使用组件(写组件标签)
如何定义一个组件?
Vue.extend(options)创建,其中options和new Vue(options)时传入那个options几乎一样,但也有点区别:
template可以配置组件结构。如何注册组件?
new Vue的时候传入components选项Vue.component(‘组件名’,组件)编写组件标签:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>几个注意点title>
<script src="../js/vue.js">script>
head>
<body>
<div id="root">
<h1>{{msg}}h1>
<school>school>
div>
body>
<script>
Vue.config.productionTip = false
// 定义组件(简写形式)
const s = {
// name:'atguigu',
template:`
学校名称: {{name}}
学校地址:{{address}}
`,
data(){
return {
name:'尚硅谷',
address:'北京',
}
},
}
// 定义组件(正常形式)
// const s = Vue.extend({
// // name:'atguigu',
// template:`
//
// 学校名称: {{name}}
// 学校地址:{{address}}
//
// `,
// data(){
// return {
// name:'尚硅谷',
// address:'北京',
// }
// },
// })
new Vue({
el:'#root',
data:{
msg:'欢迎学习vue'
},
components:{
school:s,
}
})
script>
html>
一般项目的Root下只管理一个app组件,由App组件管理多个其它子组件。
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>组件嵌套title>
<script src="../js/vue.js">script>
head>
<body>
<div id="root">
div>
body>
<script>
Vue.config.productionTip = false
// 定义student组件
const student = {
template:`
学生姓名: {{name}}
年龄:{{age}}
`,
data(){
return {
name:'尚硅谷',
age:18,
}
},
}
// 定义school组件
const school = {
// name:'atguigu',
template:`
学校名称: {{name}}
学校地址:{{address}}
`,
data(){
return {
name:'尚硅谷',
address:'北京',
}
},
// 注册组件(局部)
components:{
student
}
}
// 定义hello组件
const hello = {
template:`
欢迎来到你屋里
`,
}
// 定义app组件
const app = Vue.extend({
template:`
`,
components:{
school,
hello
}
})
//创建vm
new Vue({
template:` `,
el:'#root',
//注册组件(局部)
components:{app}
})
script>
html>
一、school的本质到底是什么?
数据类型??
输出一下school看看是什么

是构造函数,代码里没有显式调用new VueComponent(),但是在源码中调用了这个构造函数。
1.school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的。
2.我们只需写 或 ,Vue解析时会帮我们创建school组件的实例对象(组件是构造函数,构造函数可以有实例对象),即Vue帮我们执行了:new VueComponent(options)。
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>VueComponenttitle>
<script src="../js/vue.js">script>
head>
<body>
<div id="root">
<school>school>
div>
body>
<script>
Vue.config.productionTip = false
// 定义school组件
const school = Vue.extend({
name:'school',//组件想要显示在开发者工具里边的名字
template:`
学校名称: {{name}}
学校地址:{{address}}
`,
data(){
return {
name:'尚硅谷',
address:'北京',
}
},
})
console.log('@',school)
//创建vm
new Vue({
el:'#root',
components:{school},
})
script>
html>
3.特别注意:每次调用 Vue.extend,返回的都是一个全新的 VueComponent。

DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>VueComponenttitle>
<script src="../js/vue.js">script>
head>
<body>
<div id="root">
<school>school>
<hello>hello>
div>
body>
<script>
Vue.config.productionTip = false
// 定义school组件
const school = Vue.extend({
name:'school',//组件想要显示在开发者工具里边的名字
template:`
学校名称: {{name}}
学校地址:{{address}}
`,
data(){
return {
name:'尚硅谷',
address:'北京',
}
},
})
// 定义hello组件
const hello = Vue.extend({
template:`{{msg}}
`,
data(){
return {
msg:'你好啊!'
}
}
})
console.log('@',school)
console.log('#',school)
//创建vm
const vm = new Vue({
el:'#root',
components:{school,hello},
})
script>
html>
判断school和hello是不是相同的?不同!
console.log('@',school===hello)
4.关于this指向:
(1)组件配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【VueComponent实例对象】。
(2)new Vue(options)配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【Vue实例对象】。
5.VueComponent的实例对象,以后简称vc(也可以称之为:组件实例对象)。
Vue的实例对象,以后简称vm。
问:如何能体现vm在管理着vc呢?看 vm中的children属性。

DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>VueComponenttitle>
<script src="../js/vue.js">script>
head>
<body>
<div id="root">
<school>school>
<hello>hello>
div>
body>
<script>
Vue.config.productionTip = false
const school = Vue.extend({
name:'school',
template:`
学校名称: {{name}}
学校地址:{{address}}
`,
data(){
return {
name:'尚硅谷',
address:'北京',
}
},
})
const hello = Vue.extend({
template:`{{msg}}
`,
data(){
return {
msg:'你好啊!'
}
}
})
new Vue({
el:'#root',
components:{school,hello},
})
script>
html>
子组件中的子组件:


DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>VueComponenttitle>
<script src="../js/vue.js">script>
head>
<body>
<div id="root">
<school>school>
<hello>hello>
div>
body>
<script>
Vue.config.productionTip = false
const school = Vue.extend({
name:'school',
template:`
学校名称: {{name}}
学校地址:{{address}}
`,
data(){
return {
name:'尚硅谷',
address:'北京',
}
},
})
const test = Vue.extend({
template:`test子组件`
})
const hello = Vue.extend({
template:`
{{msg}}
`,
data(){
return {
msg:'你好啊!'
}
},
components:{test}
})
new Vue({
el:'#root',
components:{school,hello},
})
script>
html>
vm可以指定el,为哪个容器服务。vm不能指定el(报错),vc只能跟着大哥vm混。另外data配置项,vc只能写成函数式,vm都可以。
函数身上的prototype(显式原型属性)和对象身上的__proto__(隐式原型属性)都指向了一个对象(原型对象)。

DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>一个重要的内置关系title>
<script src="../js/vue.js">script>
head>
<body>
<div id="root">
div>
body>
<script>
Vue.config.productionTip = false
// 定义一个构造函数
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.__proto__.x)
script>
html>
修改上述,输出d,是Demo的实例对象。带着Demo,表示对象d是由Demo缔造出来的(好区分)。

console.log('@', d)
Vue构造函数身上有很多属性,其中一个是prototype,prototype的值是一个对象,对象是Vue的原型对象。
Vue实例对象vm的__proto__的值也指向了Vue的原型对象。
Vue的原型对象是一个普普通通Object对象,Vue的原型对象的__proto__的值指向的是Object的原型对象。
一句话:实例的隐式原型属性永远指向自己缔造者的原型对象。


VueComponent构造函数同理,身上有很多属性(且与Vue的相同)。
VueComponent原型对象的原型对象是Vue原型对象。

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