组件化编程
模块:
向外提供特定供的JS程序,一般就是一个js文件。
作用:复用js,简化js的编写,提高js运行效率
组件:
实现应用中局部功能代码和资源的集合。
作用:复用编码,简化项目编码,提高运行效率
模块化:当应用中的js都以模块来编写时,那这个应用就是一个模块化应用。
组件化:当应用中的功能都是多组件的方式来编写的,那这个应用就是一个组件化的应用。
函数式和对象式的区别
对象式定义的对象,在被复用时会因为存在引用关系,修改一个引用时另一个引用也被改变。函数式定义的对象没有这个问题。
let data = {a: 1,b: 2};const x1 = data;const x2 = data;console.log(x1);console.log(x2);// data为对象式时, x1和x2引用同一个data对象。x1改变a属性时,x2的a属性也会被改x1.a = 99;console.log(x1.a);console.log(x2.a);function data2() {return {a: 1,b: 2}}const y1 = data2();const y2 = data2();console.log(y1);console.log(y2);// data2为函数式,y1、y2不存在引用关系。y1改变a属性时,不会影响y2的a属性y1.a = 99;console.log(y1.a);console.log(y2.a);
非单文件组件
- 使用
Vue.extend定义组件 - 将定义的组件注册进
new Vue中 - 在页面中将组件名作为标签名配置到页面中
示例:
<body><div id="app"><!-- 此处直接使用组件名作为标签名 --><school-component></school-component><hr><student-component></student-component></div></body><script>Vue.config.productionTip = false;// 定义组件const school = Vue.extend({// 组件中的配置项和new Vue中的配置项几乎一样// 组件定义时不能写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器// 使用template编写组件的模板template: `<div><h2>学校名称:{{schoolName}}</h2><h2>学校地址:{{address}}</h2></div>`,// 组件中的data要使用函数式写法,不能使用对象式。使用函数式写法可以避免组件被附庸时存在引用关系data(){return {schoolName: '庞各庄学院',address: '庞各庄'}}});const student = Vue.extend({template:`<div><h2>学生姓名:{{studentName}}</h2><h2>学生年龄:{{age}}</h2></div>`,data() {return {studentName: '张三',age: 18}}});new Vue({el: '#app',components: {'school-component': school, // 此处的定义的属性名才是真正的组件名,上面定义组件时的变量名只是一个临时的中转变量名'student-component': student}});</script>
注册全局组件:
<body><div id="app"><hello></hello></div></body><script>const hello = Vue.extend({template:`<div><h2>{{msg}}</h2></div>`,data() {return {msg: 'hello'}}});// 将组件注册为全局组件// 参数1:组件名// 参数2:组件Vue.component('hello', hello);new Vue({el: '#app'}</script>
组件名注意点:
组件名为一个单词时:可以全小写,也可以首字母大写(推荐)
new Vue({el: '#app',components: {Student: student // 单个单词时,可以首字母大写,也可以全小写}});
组件名为多个单词组成时:使用短横连接
new Vue({el: '#app',components: {'my-student': student // 多个单词时,使用短横连接}});
如果是脚手架环境,可以使用所有单词首字母都大写的形式(推荐):
new Vue({el: '#app',components: {MyStudent: student // 多个单词时,所有单词首字母都大写。(需要是脚手架环境才可以,引用vue.js是不可以处理首字母大写的)}});
组件名尽可能回避html中已经有的元素名称,例如:h2、H2等都不可以。
可以使用name配置项指定组件在开发者工具中呈现的名字。例如:
<body><div id="app"><student-component></student-component><hr></div></body><script>Vue.config.productionTip = false;const student = Vue.extend({// 使用name属性配置该组件在Vue开发者工具中显示的名称。该名称不会影响组件在new Vue注册的名字。name:'test',template:`<div><h2>学生姓名:{{studentName}}</h2><h2>学生年龄:{{age}}</h2></div>`,data() {return {studentName: '张三',age: 18}}});new Vue({el: '#app',components: {'student-component': student}});</script>
组件标签的写法:
<!-- 第一种写法:正常的双标签 --><school></school><!-- 第二种写法:自闭合 --><school />
第二种写法需要在脚手架环境下使用。如果不是脚手架环境,<school/>会导致后续组件不能正确渲染。
组件配置的简写形式:
const school = Vue.extend(options);// 可以简写为:const school = options;
组件嵌套
组件可以嵌套使用,在父组件里嵌套子组件。
例如:
<body><div id="app"><school></school></div></body><script>Vue.config.productionTip = false;const student = {template:`<div><h2>{{studentName}}</h2></div>`,data() {return {studentName: 'tom'}}}// school内部嵌套student组件const school = {template:`<div><h2>{{schoolName}}</h2><student></student></div>`,data() {return {schoolName: '庞各庄小学'}},components: {student}}new Vue({el: '#app',components: {school}})</script>
实际开发中,一般在vm中只有一个叫app的组件,其他组件都嵌套进app组件内。
例如:
<body><div id="app"></div></body><script>Vue.config.productionTip = false;const student = {template:`<div><h2>{{studentName}}</h2></div>`,data() {return {studentName: 'tom'}}}const school = {template:`<div><h2>{{schoolName}}</h2><student></student></div>`,data() {return {schoolName: '庞各庄小学'}},components: {student}}const hello = {template:`<div><h2>{{msg}}</h2></div>`,data() {return {msg: 'hello'}}}// 其他组件位于app组件下const app = {template:`<div><hello></hello><school></school></div>`,components: {hello,school}}// vm中只管理app一个组件new Vue({el: '#app',template:`<app></app>`,components: {app}})</script>
VueComponent
定义的组件在本质上是一个名为VueComponent的构造函数,且不是开发人员定义的,是Vue.extend生成的。
在模板中配置<school></school>,Vue解析时会自动创建school组件的实例对象。即Vue自动执行了new VueComponent(options)。
每次调用Vue.extend,返回的都是一个全新的VueComponent。
Vue的this指向:
- 在组件配置中:data函数、methods中的函数、watch中的函数、computed中的函数,它们的
this均是VueComponent实例对象vc - 在
new Vue配置中,data函数、methods函数、watch中的函数、computed中的函数,它们的this均是Vue实例对象vm
js原型对象
js中定义一个函数后,函数对象会有一个prototype属性,称为显示原型属性。
如果该函数是一个构造函数,new 出来一个对象后,这个实例对象会有一个__proto__属性,该属性称为隐式原型属性。
显示原型属性、隐式原型属性都指向了同一个对象,叫做原型对象。
对象的隐式原型属性(原型对象)指向自己的缔造者。
// 定义一个构造函数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__); // true,这两个属性都指向了同一个对象,叫做原型对象
因为Demo.prototype和d.__proto__是同一个对象,所以操作Demo.prototype时实例对象也会变:
Demo.prototype.x = 99;console.log('d.__proto__.x:' + d.__proto__.x); // d.__proto__.x 也可以输出99
进一步的,如果程序中使用了d.x,而d对象本身没有x属性,就会顺着原型链查找到d.__proto__.x:
console.log('d.x:' + d.x); // d.x 也可以输出99。 d本身没有x属性,但是js会通过原型链d.__proto__找到d.__proto__.x
Vue组件中的内置关系
Vue组件中:Vue组件的原型对象的原型对象,就是Vue的原型对象
VueComponent.prototype.__proto__ === Vue.prototype
单文件组件
一个文件就是一个组件,组件的模板、样式、定义都在该文件中。
文件名后缀为.vue,里面可以编写3个标签:
<template><!-- 组件的结构,即配置的组件模板 --></template><script>// 组件交互相关的代码(数据、方法等)</script><style>/* 组件的样式 */</style>
推荐为VSCode安装 Vetur插件进行VUE代码的编写。
示例:
<template><!-- 组件模板 --><div class="demo"><h2>{{studentName}}</h2></div></template><script>// 定义组件const school = Vue.extend({name: 'School', // vue开发者工具中显示的名称data() {return{studentName: 'tom'}}});// 将组件暴露出去。也可以使用其他export方式,推荐使用 export default 进行暴露export default School;</script><style>.demo{background-color: skyblue;}</style>
定义组件的位置一般使用简写:
<script>// 简写形式:// 不再定义临时的中转变量,直接在定义时就export出去// 不再使用Vue.extend,使用简写形式直接编写optionsexport default {name: 'School',data() {return{studentName: 'tom'}}}</script>
实际开发中,会创建一个App组件管理其他组件:
<template><div><school /><student /></div></template><script>import School from './School'import Student from './Student.vue'export default {name: 'App',components: {School,Student}}</script><style></style>
另外,会创建一个main.js作为入口文件,用来创建vm实例:
import App from './App'new Vue({el: '#root',template: `<app/>`,comments: { App }})
最后在页面中引入main.js:
<!DOCTYPE html><html lang="en"><head><title>首页</title></head><body><div id="root"></div><script src="./scripts/vue.js"></script><!-- 最好在body最下方引入main.js,此时页面已经加载 --><script src="./main.js"></script></body></html>
HTML的其他标签
html中的<head>标签中,出现的<meta>的含义:
<head><!-- 编码 --><meta charset="UTF-8"><!-- 针对IE浏览器的一个特殊配置,含义是让IE浏览器以最高的渲染级别渲染页面 --><meta http-equiv="X-UA-Compatible" content="IE=edge"><!-- 开启移动端的理想视口 --><meta name="viewport" content="width=device-width, initial-scale=1.0"></head>
html中的<noscript>标签,如果浏览器不支持js则会渲染出来:
<body><noscript>不好意思,您的浏览器不支持js。</noscript></body>
