目录
一、组件介绍
1.传统方式
缺点:结构复杂、代码复用率不高
1.组件化方式
组件的定义:实现应用中局部功能代码和资源的集合
二、非单文件组件
1.使用组件步骤*
(1)创建组件
// 第一步:创建person组件
const person = Vue.extend({
template: `
<div>
<p>名字:{{name}}</p>
<p>年龄:{{age}}</p>
</div>`,
data() {
return {
name: 'csq',
age: '20'
}
},
methods: {
getName() {
return name
}
}
})
【1】使用Vue.extend(options)来创建
【2】模板template最好用反引号来写,支持多行字符串 ;
【3】data使用函数形式返回,避免组件被复用时,数据存在引用关系
(2)注册组件
全局注册和局部注册
// 第二步:注册组件(全局注册)
Vue.component('hello', hello)
// 创建vm
const vm = new Vue({
el: '.root',
components: {
// 第二步:注册组件(局部注册)
person: person, //等同于person(es6写法)
}
})
全局注册:Vue.component('组件名',组件)
局部注册:在vm实例中传入components属性中
(3)加入组件标签
<div class="root">
<!-- 第三步:编写组件标签 -->
<person></person>
<hello></hello>
<hello></hello>
</div>
组件可复用
2.template属性
一个字符串模板作为 Vue 实例的标识使用。模板将会替换挂载的元素
在使用时,需要额外使用一个div标签将模板内容包裹起来
template: `
<div>
<p>名字:{{name}}</p>
<p>年龄:{{age}}</p>
</div>`,
3.注意
1.关于组件名:
一个单词组成:
第一种写法(首字母小写): school
第二种写法(首字母大写): school
多个单词组成:
第一种写法(kebab-case命名): my-school
第二种写法(CamelCase命名): MySchool (需要Vue脚手架支持)
备注:
(1)组件名尽可能回避HTML中已有的元素名称,例如: h2、H2都不行。
(2)可以使用name配置项指定组件在开发者工具中呈现的名字。
2.关于组件标签:
第一种写法:<school></school>
第二种写法:<school/> 备注:不用使用脚手架时,<schoo1/>会导致后续组件不能渲染。
3.一个简写方式:
const school = Vue.extend(options) 可简写为: const school = options
// 第一步:创建hello组件
const hello = ({
template: ``,
data() {
return {}
}
})
三、组件的嵌套
1.书写规则
(1)嵌套方法
在父组件中注册: components:{子组件名,...}
在父组件模板中调用:template:`<子组件名></子组件名>`
(2)创建一个app组件用来管理其他组件
(3)创建组件顺序
需要嵌套的组件要先创建,否则嵌套进组件的组件名会提示不存在
2.示例
const student = Vue.extend({
template: `
<div>
<p>学生名字:{{name}}</p>
<p>学生年龄:{{age}}</p>
</div>
`,
data() {
return {
name: 'csq',
age: '18'
}
},
})
const school = Vue.extend({
template: `
<div>
<p>学校名字:{{name}}</p>
<p>学校地址:{{address}}</p>
<student></student>
</div>
`,
data() {
return {
name: 'CTBU',
address: 'chongqing'
}
},
components: {
student
}
})
const hello = Vue.extend({
template:
`
<div>
<h1>hello Vue!!!</h1>
</div>
`
})
const app = Vue.extend({
template: `
<div>
<school></school>
<hello></hello>
</div>
`,
components: {
school,
hello
}
})
const vm = new Vue({
el: '.root',
components: {
app
},
template: `
<app></app>
`
})
四、VueComponent构造函数
关于VueComponent:
1.组件的本质
school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的
(1)vc存放在vm的$children属性中
(2)school组件的本质
(3)组件嵌套
2.组件实例对象
我们只需要写<school/>或<school></school>,Vue解析时会帮我们创建school组件的实例对象,即Vue帮我们执行的: new VueComponent(options)
组件实例被创建了4次
3.VueComponent是不同的
特别注意: 每次调用Vue.extend,返回的都是一个全新的VueComponent!!!!
school组件和hello组件创建时返回的VueComponent构造函数不是同一个
school === hello // false
4.关于this指向
(1)组件配置中:data函数、methods中的函数、watch中的函数、computed中的函数,它们的this均是VueComponent实例对象
(2)new Vue(options)配置中:data函数、methods中的函数、watch中的函数、computed中的函数,它们的this均是Vue实例对象
5.简称
VueComponent的实例对象,以后简称vc(也可称之为: 组件实例对象)
Vue的实例对象,以后简称vm
五、VueComponent原型链内置关系**
VueComponent.prototype.__proto__ === Vue.prototype
让组件实例对象vc可以访问到Vue原型上的属性和方法
// Vue原型链赋一个参数
Vue.prototype.x = 99
const school = Vue.extend({
name: 'school',
template: `
<div>
<button @click='showname'>点我出名字</button>
</div>
`,
data() {
return {
//...
}
},
methods: {
showname() {
// 查看Vue原型链的内置关系是否成立
console.log(this.x) //99
}
}
})
六、单文件组件
1.文件基本结构
<template>
<!-- 组件结构 -->
</template>
<script>
// 组件交互相关的代码(数据、方法等)
</script>
<style>
/* 组件的样式 */
</style>
2.单文件组件项目语法
和多文件组件一样,所有组件由App组件领导,再写入vm实例中
// index.html
<div class="root">
</div>
<script src="../../js/vue.js"></script>
<script src="main.js"></script>
// main.js
import App from './App.vue'
const vm = new Vue({
template: `
<app></app>
`,
el: '.root',
data() {
return {
}
},
components: {
App
}
})
// App.vue
<template>
<div>
<School></School>
<Student></Student>
</div>
</template>
<script>
import School from './School'
import Student from './Student'
export default {
name: 'App',
components: {
School,
Student
}
}
</script>
// School.vue 略
// Student.vue 略
这就是vue单文件组件项目的基本结构啦
however,这样运行后会报错Cannot use import statement outside a module
原因是:浏览器不能直接支持es6的模块化语法。。。
所以!脚手架老师即将登场了!!!
七、Vue脚手架
1.基本方法
(1)基本操作
创建cli:vue create hello-world
运行cli:npm run serve
(2)基本结构
main.js文件
new Vue({...}).$mount('#app') 等同于在vue实例内写el:'#app'
2.render()函数
new Vue({
// 将App组件放入容器中
render: h => h(App),
}).$mount('#app')
import Vue from 'vue' 引入运行版vue没有模板解析器,所以不能使用template配置项,这时候就需要使用render函数去接收到的createElement函数去指定具体内容,创建html模板
render函数的解析
这个函数的作用就是生成一个 VNode节点,render 函数得到这个 VNode 节点之后,返回给 Vue.js 的 mount 函数,渲染成真实 DOM 节点,并挂载到根节点上
3.修改默认配置
(1)这五个配置项不可修改
(2)可修改项
4.ref属性
$ref属性获取到的真实dom信息和组件实例都以对象形式存储在$ref属性中
(1)用来给元素和子组件注册引用信息(类似于id的功能)
(2)应用在html标签上引用的是真实DOM元素;应用在组件标签上引用的是组件实例对象(vc)
(3)使用方式:
<h1 v-text="msg" ref="title"></h1>
<School ref="school"></School>
调用方式:this.$ref.自定义ref名
5.props配置选项
功能:让组件接收外部传进来的数据
(1)接收数据方式:
1、简单接收
props: ['name', 'age']
2、接收时设置接收数据类型
props: {
name: String,
age: Number
}
3、接收时设置:接收数据类型+是否必要接收+默认值
props: {
name: {
type: String,
required: true
},
age: {
type: Number,
default: 20
}
}
(2)传入方式
父组件调用时直接写入传数据的名字和数据
<Student name="csq" :age="18" />
注意:需要传入Number类型数据时,采用v-bind绑定age,这样引号内传入的是js表达式而不是字符串
(3)对传入数据进行修改
props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,若业务需求确实需要修改,那么需要复制props的内容到data中一份,然后去修改data中的数据
修改方法:
data() {
return {
stuAge: this.age
}
}
6.mixin混入配置选项
功能:将多个组件共同的配置提取成一个混入对象
(1)定义混入对象
创建一个mixin.js文件存储混入对象
// 分别暴露 适合一个文件内多个导出
export const mixin1 = {
methods: {
showname() {
console.log(this.name)
}
}
}
export const mixin2 = {
data() {
return {
age: 100,
yy: 99
}
}
}
(2)引入混入对象
1、局部混入
在需要该配置的地方引入:import {混入对象名} from '文件路径'
在vc配置中使用:mixins:[混入对象1,混入对象2...] 必须使用数组形式
注意:混入数据对象时,该组件中已存在的数据名的值不会改变,无则添加,有则不覆盖
2、全局混入
在main.js中混入
import { mixin1, mixin2 } from './mixin'
Vue.mixin(mixin1)
Vue.mixin(mixin2)
注意:混入后,所有的vc甚至vm上都有了混入的配置
7.plugins插件配置
功能:用于增强vue
(1)定义插件
本质是包含install方法的一个对象,install接收的第一个参数是Vue,第二个以后的参数是使用者在插件中传入的参数创建一个plugins.js文件
export default {
install(Vue, ...arr) {
console.log(arr)
// 关闭vue生产时提示
Vue.config.productionTip = false
// 1.定义全局混入Vue.mixin()
Vue.mixin({
//...
})
// 2.自定义全局指令Vue.directive()
Vue.directive('fbind',{
//...
})
// 3.全局过滤器 Vue.filter()
Vue.filter({
//...
})
// 4.给vue原型链添加自定义属性(vm和vc都可用)
Vue.prototype.ss = 100
}
}
(2)使用插件
在main.js文件中
//引入插件
import plugins from './plugins'
//plugins插件用于在创建vm、vc实例前进行全局化配置
//可写入多个参数,plugins会接收
Vue.use(plugins, 1, 2, 3)
8.scoped样式
作用:让样式在局部生效,防止冲突
各组件的样式名相同会导致样式覆盖,添加scoped避免冲突
使用方式:<style scoped> ... </style>
实际是给每个设定了scoped的dom元素添加一段独一无二的属性标识
关于样式的其他设置
lang=“less”用less书写style
<style scoped lang="less">
/* 组件的样式 */
.demo {
background-color: orange;
div:first-of-type {
height: 100px;
p:first-child {
color: red;
}
}
}
</style>