Loading

Vue2 组件

非单文件组件(过渡)

非单文件组件就是指并非一个组件占用一个文件,而是一个人间中有多个组件。我们只将其作为学习的过度,实际开发中不适用这种方式。

demo:

<body>
	<div id="app">
		<h1>大哥</h1>
		<hr>
		<!-- 3. 使用组件 -->
		<xuexiao></xuexiao>
		<hr>
		<student></student>
	</div>
</body>
<script src="https://cdn.jsdelivr.net/gh/brokyz/brokyzCDN/vue/2.7.10/vue.js"></script>
<script>
	// 1. 创建组件
	// 组件中不用指定el,因为组件不用绑定死为谁服务,追随vm实例。
	// 组件中的数据必须以函数的形式赋值。
	const school = Vue.extend({
		// 书写组件的html
		template: `
		<div>
			<h2>school:{{name}}</h2>
		</div>
	`,
		data() {
			return {
				name: "首经贸"
			}
		}
	})
	// 创建组件的简写形式,直接用对象。
	const student = {
		template: `
		<div>
			<h2>student:{{name}}</h2>
		</div>
	`,
		data() {
			return {
				name: "brokyz"
			}
		}
	}

	const vm = new Vue({
		// 2. 注册组件
		components: {
			xuexiao: school, // 可以注册名和组件名相同直接简写成 school
			student,
		},
	}).$mount("#app")
</script>

使用组件一般分为三步:

  1. 创建组件:此时组件已经创建,但是还没有被 vm 实例注册使用。
  2. 注册组件:此时组件被 vm 实例注册,但是并没有被 vm 实例使用。
  3. 编写组件标签(使用组件):此时组件被 vm 实例使用。

组件中不能指定 el 或者 mount:

​ 由于组件是灵活的可复用的,所以并不需要绑定一个元素只为其服务。而是由注册该组件的 vm 实例来决定一起为谁服务。

​ 可以将 vm 实例理解成大哥,组件是加入大哥麾下的小弟。大哥说打哪小弟也跟着打哪。

​ 所有的组件都得有大哥才可以展现出来。

组件中必须以函数的形式来指定数据:

​ 因为在同一个文件下,如果以对象的形式来指定数据的话,那么多个组件指向的是同一个对象。这样组件之间的数据就比较混乱。

​ demo:

let data = {
	name: "brokyz"
}
let a = data
let b = data
// 此时 a 和 b 指向了同一个 data,a 和 b 将操作同一个对象。

data(){
	return {
		name: "brokyz"
    }
}
let a = data()
let b = data()
// 此时 a 和 b 之前指向的是不同的对象。

组件的结构将以 template 的形式赋予组件。

组件的命名

在组件中指定 name 配置项,那么不管注册的时候是什么名字,在 Vue 开发者工具中都会显示组件指定的 name。

const school = Vue.extend({
	// 指定组件的名字
	name: "myschool",
    // 书写组件的html
	template: `
		<div>
			<h2>school:{{name}}</h2>
		</div>
	`,
	data() {
		return {
			name: "首经贸"
		}
	}
})

组件注册时的命名规范:

  1. 单个单词全小写school: school:在 Vue 开发者工具中首字母会自动大写显示。School
  2. 单个单词首字母大写School: school:与 Vue 开发者工具风格一致。School
  3. 多个单词用 - 隔开'my-school': school:注册时要用引号包裹,在开发者工具中以大驼峰的形式显示。MySchool
  4. 多个单词首字母大写MySchool: school:只有在使用脚手架的时候才能这样命名,否则组件无效。MySchool

组件嵌套

可以在组件上使用另一个组件,但是在非单个文件时注意书写顺序,需要用的组件要先创建。

<body>
	<div id="app">
		<h1>大哥</h1>
		<hr>
		<!-- 3. 使用组件 -->
		<xuexiao></xuexiao>
		<hr>
		<student></student>
	</div>
</body>
<script src="https://cdn.jsdelivr.net/gh/brokyz/brokyzCDN/vue/2.7.10/vue.js"></script>
<script>
	// 1. 创建组件
	// 组件中不用指定el,因为组件不用绑定死为谁服务,追随vm实例。
	// 组件中的数据必须以函数的形式赋值。

	const student = Vue.extend({
		template: `
		<div>
			<h2>student:{{name}}</h2>
		</div>
	`,
		data() {
			return {
				name: "brokyz"
			}
		}
	})

	const school = Vue.extend({
		// 书写组件的html
		name: "myschool",
		template: `
		<div>
			<h2>school:{{name}}</h2>
			<student></student>
		</div>
	`,
		data() {
			return {
				name: "首经贸"
			}
		},
		components: {
			student
		}
	})

	const vm = new Vue({
		// 2. 注册组件
		components: {
			xuexiao: school, // 可以注册名和组件名相同直接简写成 school
			student,
		},
	}).$mount("#app")
</script>

app 组件

在开发中,会定义一个 app 组件,用于管理应用中的所有组件。可以将 app 理解为一人之下(root),万人之上(其他组件)。

<body>
	<div id="root">
		<app></app>
	</div>
</body>
<script src="https://cdn.jsdelivr.net/gh/brokyz/brokyzCDN/vue/2.7.10/vue.js"></script>
<script>
	// 1. 创建组件
	// 组件中不用指定el,因为组件不用绑定死为谁服务,追随vm实例。
	// 组件中的数据必须以函数的形式赋值。

	const student = Vue.extend({
		template: `
	<div>
		<h2>student:{{name}}</h2>
	</div>
`,
		data() {
			return {
				name: "brokyz"
			}
		}
	})

	const school = Vue.extend({
		// 书写组件的html
		name: "myschool",
		template: `
	<div>
		<h2>school:{{name}}</h2>
		<student></student>
	</div>
`,
		data() {
			return {
				name: "首经贸"
			}
		},
		components: {
			student
		}
	})

	const app = Vue.extend({
		template: `
			<div>
				<school></school>
			</div>
		`,
		components: {
			school
		}
	})

	const vm = new Vue({
		// 2. 注册组件
		components: {
			app
		},
	}).$mount("#root")
</script>

VueComponent 构造函数

  1. 创建组件的本质就是创建一个名为 VueComponent 的构造函数,这不是程序员自己定义的,而是由 Vue.extend帮我们生成的。

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

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

  4. 关于 this 的指向:

    1. 组件配置中:

      data函数、methos中的函数、watch中的函数、computed中的函数,它们的 this 全指向【VueComponent 实例对象】。

    2. new Vue(options) 中:

      data函数、methos中的函数、watch中的函数、computed中的函数,它们的 this 全指向【Vue 实例对象】。

  5. VueComponent 的实例对象,也称为 vc 或 组件实例对象,Vue 实例对象,简称 vm。

  6. vm.$childrenvc.$children都存储了它们里面的组件。

vm 与 vc 的内置关系

首先从表面上说,vm 需要 el,而且 data 可以是对象可以是函数。而 vc 没有 el,必须是函数 data。

然后观察其二者的原型关系:

注意:实例对象的__proto__是隐式原型属性,构造函数的prototype式显示原型属性,二者都同时指向原型对象。一般我们用显示进行操作,隐式进行使用。

单文件组件

推荐 vscode 插件:vetur

组件 school.vue

<template>
	<div class="demo">
		<h2>学校名称:{{ name }}</h2>
		<h2>学校地址:{{ address }}</h2>
	</div>
</template>

<script>
	export default {
		data() {
			return {
				name: '首经贸',
				address: '北京市丰台区'
			};
		}
	};
</script>

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

向外暴露组件:

我们这里的单文件的组件是需要被其他人导入并且注册的,所以我们这里要向外暴露我们的 vc。

// Vue 推荐的简写写法
export default {
	data() {
		return {
			name: '首经贸',
			address: '北京市丰台区'
		};
	}
};
// 上一种写完整
const school = Vue.extend({
    data() {
		return {
			name: '首经贸',
			address: '北京市丰台区'
		};
	}
})
export default school

app.vue

<template>
	<div>
		<School></School>
		<student></student>
	</div>
</template>

<script>
    // 引入组件
	import School from './school'
	export default {
		name: 'App',
		components: {
			School
		}
	};
</script>

<style></style>

main.js

import App from './App.vue'

new Vue({
	el: '#root',
	template: '<app></app>',
	components: {
		App
	},
})

index.html

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<div id="root"></div>
		<script src="https://cdn.jsdelivr.net/gh/brokyz/brokyzCDN/vue/2.7.10/vue.js"></script>
		<script src="./main.js"></script>
	</body>
</html>
  • 引入 main.js 要在容器的下面才可以。
  • 需要在这里引入 vue.js。

注意:这里都配置完成后,页面中并不能显示出来,需要在脚手架中才可以运行。

VueCli 脚手架

脚手架可以为我们自动配置我们的前端工程化的开发环境,省去了我们使用 webpack 手动配置前端工程化开发环境的麻烦。

使用

安装 VueCli

npm install -g @vue/cli

切换到要创建项目的目录,然后使用命令创建项目

vue create projectNmae

如果下载慢需要配置淘宝镜像

npm config set registry https://registry.npm.taobao.org

开发时编译代码

npm run serve

分析脚手架结构

配置文件:

  1. .gitignore:git 的忽略文件。
  2. babel.config.js:babel 的配置文件,用于 es6 转 es5。
  3. package.json:nodejs的配置文件。
  4. package-lock.json:nodejs中的包的版本控制文件,里面存着报的版本信息。

主题文件:

  1. src/main.js:vue 项目中一切的开端,整个项目的入口文件。文件中导入了 vue 和 app,创建了 vm 实例。
  2. src/App.vue:项目中的一个汇总组件,所有的组件展示都汇总到这里,它是所有组件的父组件。然后再由 vm 实例调用 App 总组件进行页面展现。
  3. src/components:用于存放组件。
  4. src/assets:用于存放静态文件。
  5. public/index.html:vm 实例最终渲染的页面,其中有元素被 vm 实例绑定。

render 函数

我们认识脚手架之前的 vm 实例:

import Vue from 'vue'
import App from './App.vue'

new Vue({
	template: '<App></App>',
    components: {App}
}).$mount('#app')

上述这种 vm 实例的写法在脚手架中运行时会报错。因为在脚手架中导入的 vue 并不是完整路径,而是 vue 文件夹,其中包含了许多版本的 vue 文件,但是默认为我们导入的是 dist/vue.runtime.esm.js, 这是精简掉了模板解析器的 vue,并不是完成版的 vue.js。这个由于没有 模板解析器,所以无法解析 template 中的语法。

这时我们就可以使用 render 渲染函数:

import Vue from 'vue'
import App from './App.vue'

new Vue({
	render(createElement){
        return createElement('h1', '你好')
    }
}).$mount('#app')


// 简写
new Vue({
	render: h => h(App),
}).$mount('#app')

为什么 vue 会有精简版本?

​ vue 中有些东西是我们开发时用到的,这些东西上线时被 webpack 打包编译会生成 js。但是里面有些只有开发时会用的代码在上线时并不会被使用。所以 vue 为我们提供了一些精简版本的 vue。类似于 nodejs 中的 dependencies 和 devDependencies。

注意:

  1. 我们所说的模板解析器是服务于的是在 vue.js 中用于创建 vm 实例时配置项里面的 template。
  2. 而组件中的 tamplate 标签是我们 nodejs 中安装的 vue-template-compiler 包来进行解析的。

关于不同版本 vue 的区别:

  1. vue.js 于 vue.runtime.xxx.js 的区别:

    1. vue.js 是完整版,包含了:核心功能+模板解析器。
    2. vue.runtime.xxx.js 是运行版的 Vue,只包含:核心功能,不包含模板解析器。
  2. 因为 vue.runtime.xxx.js 没有模板解析器,所以不能使用 template 配置项,需要使用 render 函数接收到的 createElement 函数去指定具体内容。

posted @ 2022-10-03 13:22  brokyz  阅读(112)  评论(0编辑  收藏  举报