一、组件化编程
1. 对比传统编写与组件化编程(下面两个解释图对比可以直观了解)
传统组件编写:不同的HTML引入不同的样式和行为文件
组件方式编写:组件单独,复用率高(前提组件拆分十分细致)
理解为封装行为:html,css,js封装在一个文件中
解释模块化和组件化的区别:
组件化:css,js,html三件套使用在同一部分的代码封装在一个组件中
模块化:只是将js文件进行拆分为多个文件
2. 组件化编程区分
非单文件组件:一个文件中包含n个组件
单文件组件:一个文件中只包含一个组件:后缀名是.vue(项目中多使用此方法)
3. 非单文件组件的引出
使用两类数据进行划分组件包装部分,引出单文件组件的使用
可以给每一部分进行划分并命名
<div id="root">
<h2>学校名称:{{schoolName}}</h2>
<h2>学校地址:{{addrss}}</h2>
<hr />
<h2>学生名称:{{studentName}}</h2>
<h2>学生年龄:{{age}}</h2>
</div>
//vue数据
const vm = new Vue({
el: "#root",
data: {
schoolName: "清华",
addrss: "北京",
studentName: "李华",
age: "18",
},
});
4. 单文件组件的使用
(1)局部注册(在vue配置项components中注册)
Vue.extend({}):创建组件(可以给此组件进行命名)
出现很多配置项:但是几乎和Vue实例的配置项相同
const school = Vue.extend({})
注意:此处不可以使用el绑定模板(template:``配置进行展示容器内容)
// el: "#root",//组件定义:一定不写el配置项:因为最终都要被vm管理, //由vm决定服务于哪个容器 // 利用函数式写data:如果使用对象式,当其他模板调用时候修改也会修改原来的数据 template: ` <div> <h2>学校名称:{{schoolName}}</h2> <h2>学校地址:{{address}}</h2> <button @click="showName">点我提示学校名</button> </div> `,
注意:此处的data使用的是函数式返回(不是对象式):因为多次一使用同一个组件,当后使用组件部分改变data中数据,前面组件使用组件的数据也会改变
data() { return { schoolName: "清华", address: "北京", }; },
components:{'组件名','...'} :注册组件(在Vue实例中使用此配置项):局部注册
components: { // 完整写法:重新组件命名,创建组件的名字不是组件名,注册组建的名字才是组件名 // xuexiao: school, // xueshneg: student, // 简写:相同的名字 school, student, },
组件标签:使用组件(将组件标签写在容器中,可以写多个组件标签=复用)
<!-- 第三步编写组件标签 --> <school></school> <school></school>
给单文件组件添加事件:直接在组件的配置模板中绑定事件,并在组件中添加配置回调方法
(2)全局注册 :Vue.component('组件名',创建名)
创建组件并进行全局注册:此时的组件标签就可以在任何Vue绑定的模板中使用
//1. hello全局组件创建 const hello = Vue.extend({ template: ` <div> <h2>你好{{name}}</h2> </div> `, data() { return { name: "TOM", }; }, }); // 2. 全局注册组件(组件名字,组件在哪):可以使用在任何vue绑定的模板中 Vue.component("hello", hello);
5. 单文件组建的注意点
组件名:
一个单词组件名:就是纯小写或者首字母大写(例如school、School)
多个单词组件名:
kebab-case命名:my-school
CamelCase命名:MySchool(需要脚手架支持)
备注:
组件名回避html标签
使用name配置项指定组件在开发者工具中呈现的名字(创建组件时候直接使用配置项name:进行命名=开发者工具中名字展示)
组件标签:
第一种写法:school组件标签写法 <school></school>
第二种写法:<school/> (需要脚手架环境支持),以为不在脚手架环境复用多个组件标签只会渲染一个组件
组件创建时候的简写方式:没有了extend()
// 简写创建组件 const school = { name: "xlf", template: ` <div> <h2>学校名称:{{name}}</h2> <h2>学校地址:{{address}}</h2> </div>`, data() { return { name: "xlf", address: "北京", }; }, };
6. 组件的嵌套
以下展示说明大组件种包含着小组件也就是所谓的嵌套
创建student子组件:必须在子组件创建好之后然后在父组件中注册
创建school父组件:直接在此组件使用components(注册student,注册在哪里需要在那个模板中使用标签)
//子组件创建 const student = Vue.extend({ name: "student", template: ` <div> <h2>学生姓名{{name}}</h2> <h2>学生年龄{{age}}</h2> </div> `, data() { return { name: "德华", age: "18", }; }, }); //父组件创建并注册子组件(在负组件中使用子组件标签) const school = Vue.extend({ name: "school", template: ` <div> <h2>学校名称:{{name}}</h2> <h2>学校地址;{{address}}</h2> <student></student> </div> `, data() { return { name: "清华", address: "北京", }; }, // 在组件内直接注册 components: { student, }, }); //最后总结在vue中 new Vue({ template: `<school></school>`, el: "#root", data: {}, // 2.注册组件 components: { school, }, });
开发中一创建app组件:管理所有组件(用法都是套娃)
// 1.定义组件:注册给谁就在谁的模板上写组件标签 const school = Vue.extend({ name: "school", template: ` <div> <h2>学校名称:{{name}}</h2> <h2>学校地址;{{address}}</h2> <student></student> </div> `, data() { return { name: "清华", address: "北京", }; }, // 在组件内直接注册 components: { student, }, }); // 定义app组件:注册亲子级组件,并及那个子级组件模板写入 const app = Vue.extend({ template: ` <div> <hello></hello> <school></school> </div> `, components: { hello, school, }, }); new Vue({ template: `<app></app>`, el: "#root", data: {}, // 2.注册组件 components: { app, }, });
7. Vue.Component(组件实例化)
使用一个组件:进行了解Vue.Component
<div id="root"> <!-- 3.使用标签 --> <school></school> </div> //vue // 1.定义组件school const school = Vue.extend({ template: ` <div> <h1>学校名称:{{name}}</h1> <h1>学校地址:{{address}}</h1> </div> `, data() { return { name: "清华", address: "北京", }; }, }); new Vue({ el: "#root", // 2.注册组件 components: { school, }, });
查看一下创建的组件:构造函数表示使用需要new一下(封装在源码)
构造函数时Vue.extend生成的
只需要使用组件标签就会创建组件实例=vc实例(使用两次组件标签就会实例化两次vc)
console.log(school);
特别注意:每次调用Vue.extend就会创建一个全新的vc
测试:在上面school组件基础上创建第二个个组件并对一个组件进行修改然后查看两个组件实例之间的区别
// 定义组件hello const hello = Vue.extend({ template: ` <div> <h2>学校名称:{{msg}}</h2> <button @click="showName">点我显示学校名字</button> </div> `, data() { return { msg: "hello", }; }, methods: { showName() { console.log("showName", this); }, }, }); // 检验VuComponent的不同 school.a = 99; console.log(school === hello); //false console.log(school.a); //99 console.log(hello.a); //没有
- this指向:
- vm:vue的配置项中this指向的都是vm(Vue实例对象)
- vc:组件中的配置项中this指向的都是vm(VueComponent实例对象)
8. 重要的内置关系
组件是可复用的Vue实例
vc存在的属性配置vm都有
但是vm存在的其中el,组件实例vc就没有
并且组件中的data必须使用函数方式(return返回数据)
区分显示原型对象和隐式原型对象
// 定义构造函数 function demo() { this.a = 1; this.b = 2; } const d = new demo(); // 以下构造函数原型对象和实例对象原型对象最后都指向一个原型对象 console.log(demo.prototype); //显示原型属性(一般放东西) console.log(d.__proto__); //隐式原型对象(一般开始找) console.log(demo.prototype === d.__proto__);//true //程序员通过显示原型属性操作原型对象,追加一个x属性,值为99 demo.prototype.x = 99;
Vue.Component.prototype.__proto__===Vue.prototype
Vue.Component原型对象的原型对象执行Vue原型对象
让组件实例对象那个vc可以访问到Vue原型上的属性、方法
9. 单文件组件方式:.vue后缀
vue文件需要(处理加工变成js文件)两种处理方式
webpack:插件搭建工作流
vue脚手架
vue文件命名
安装插件可以生成vue模板:<v 自动生成模板
<template> </template> <script> export default { //注意组件模块化引入,所以需要把js暴露 } </script> <style> </style>
此处需要使用暴露方式把文件暴露出去:也就是允许其他文件引入
export :直接分别暴露:直接使用并取消组件的创建方法直接暴露options
esprot {name} :统一暴露
默认暴露
(1) 创建两个组件:School组件、Student组件(这个类似)
<template>
<div class="demo">
<h2>学校名称:{{ schoolName }}</h2>
<h2>学校地址:{{ address }}</h2>
<button @click="showName">点我提示学校名</button>
</div>
</template>
<script>
export default {
name: "School",
data() {
return {
schoolName: "清华",
address: "北京",
};
},
methods: {
showName() {
alert(this.schoolName);
console.log(this); //指向当前组件
},
},
};
</script>
<style>
.demo {
background-color: pink;
}
</style>
(2)引入组件文件并在app组件中嵌套注册:注意模板需要div包裹
<template>
<div>
<School></School>
<Student></Student>
</div>
</template>
<script>
// 先引入组件
import School from './School.vue'
import Student from './Student.vue'
// 再进行对外暴露并注册组件
export default {
name: 'App',
components: {
School,
Student
}
}
</script>
<style>
</style>
(3) 组件分配完毕之后需要由vm统一管理
创建:main.js
直接引入app组件
绑定模板并注册app组件:注意在main模块中配置template配置项可以取消在html也买那种使用app标签进行组件实例
import App from './App.vue' // 浏览器不支持模块化语法 new Vue({ el: '#root', template:`<App></App>`, components: {App} })
(4)需要容器:index.html与vue实例进行关联
先创建模板
引入vue文件
引入main文件
<div id="root"></div> <script src="../vue/vue.js"></script> <!-- 入口文件 --> <script src="./main.js"></script>
浏览器不能能直接支持ed6模块化语法:也就是引入模块化(需要配置脚手架环境进行运行)