上一篇:vue生命周期
Vue组件化编程
组件化编码流程(通用)
- 实现静态组件:抽取组件,使用组件实现静态页面效果
- 展示动态数据:
- 数据的类型、名称是什么?
- 数据保存在哪个组件?
- 交互——从绑定事件监听开始
非单文件组件
<body>
<!--
Vue中使用组件的三大步骤:
一、定义组件(创建组件)
二、注册组件
三、使用组件(写组件标签)
一、如何定义一个组件?
使用Vue.extend(options)创建,其中options和new Vue(options)时传入的那个options几乎一样,但也有点区别;
区别如下:
1.el不要写,为什么? ——— 最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器。
2.data必须写成函数,为什么? ———— 避免组件被复用时,数据存在引用关系。
备注:使用template可以配置组件结构。
二、如何注册组件?
1.局部注册:靠new Vue的时候传入components选项
2.全局注册:靠Vue.component('组件名',组件)
三、编写组件标签:
<school></school>
-->
<!-- 准备好一个容器-->
<div id="root">
<hello></hello>
<hr>
<h1>{{msg}}</h1>
<hr>
<!-- 第三步:编写组件标签 -->
<school></school>
<hr>
<!-- 第三步:编写组件标签 -->
<student></student>
</div>
<div id="root2">
<hello></hello>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
//第一步:创建school组件
const school = Vue.extend({
template:`
<div class="demo">
<h2>学校名称:{{schoolName}}</h2>
<h2>学校地址:{{address}}</h2>
<button @click="showName">点我提示学校名</button>
</div>
`,
// el:'#root', //组件定义时,一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器。
data(){
return {
schoolName:'Kylincsg',
address:'北京昌平'
}
},
methods: {
showName(){
alert(this.schoolName)
}
},
})
//第一步:创建student组件
const student = Vue.extend({
template:`
<div>
<h2>学生姓名:{{studentName}}</h2>
<h2>学生年龄:{{age}}</h2>
</div>
`,
data(){
return {
studentName:'张三',
age:18
}
}
})
//第一步:创建hello组件
const hello = Vue.extend({
name: '在vue调试工具中展示的名字'
template:`
<div>
<h2>你好啊!{{name}}</h2>
</div>
`,
data(){
return {
name:'Tom'
}
}
})
//第二步:全局注册组件
Vue.component('hello',hello)
//创建vm
new Vue({
el:'#root',
data:{
msg:'你好啊!'
},
//第二步:注册组件(局部注册)
components:{
school,
student
}
})
new Vue({
el:'#root2',
})
</script>
<!--
几个注意点:
1.关于组件名:
一个单词组成:
第一种写法(首字母小写):school
第二种写法(首字母大写):School
多个单词组成:
第一种写法(kebab-case命名):my-school
第二种写法(CamelCase命名):MySchool (需要Vue脚手架支持)
备注:
(1).组件名尽可能回避HTML中已有的元素名称,例如:h2、H2都不行。
(2).可以使用name配置项指定组件在开发者工具中呈现的名字。
2.关于组件标签:
第一种写法:<school></school>
第二种写法:<school/>
备注:不用使用脚手架时,<school/>会导致后面组件不能渲染。
3.一个简写方式:
const school = Vue.extend(options) 可简写为:const school = options
4. 嵌套组件:
在指定父组件中注册,并使用即可. 全局组件,则直接使用
-->
单文件组件
<template>
<div>
<img src="./assets/logo.png" alt="logo">
<!-- 使用组件 -->
<School></School>
<Student></Student>
</div>
</template>
<script>
//引入组件
import School from './components/School'
import Student from './components/Student'
export default {
name:'App',
components:{
// 注册组件
School,
Student
}
}
</script>
ref
- 作用:用于给节点打标识
- 读取方式:
this.$refs.xxxxxx
<template>
<div>
<h1 v-text="msg" ref="title"></h1>
<button ref="btn" @click="showDOM">点我输出上方的DOM元素</button>
<School ref="sch"/>
</div>
</template>
<script>
//引入School组件
import School from './components/School'
export default {
name:'App',
components:{School},
data() {
return {
msg:'欢迎学习Vue!'
}
},
methods: {
showDOM(){
console.log(this.$refs.title) //真实DOM元素
console.log(this.$refs.btn) //真实DOM元素
console.log(this.$refs.sch) //School组件的实例对象(vc)
}
},
}
</script>
props
-
作用:用于父组件给子组件传递数据
-
读取方式一: 只指定名称
props: ['name', 'age', 'setName']
-
读取方式二: 指定名称和类型
props: { name: String, age: Number, setNmae: Function }
-
读取方式三: 指定名称/类型/必要性/默认值
props: { name: {type: String, required: true, default:xxx}, }
-- app.vue
<template>
<div>
<Student name="李四" sex="女" :age="18"/>
</div>
</template>
<script>
import Student from './components/Student'
export default {
name:'App',
components:{Student}
}
</script>
-- sutdent.vue
<template>
<div>
<h1>{{ msg }}</h1>
<h2>学生姓名:{{ name }}</h2>
<h2>学生性别:{{ sex }}</h2>
<h2>学生年龄:{{ myAge + 1 }}</h2>
<button @click="updateAge">尝试修改收到的年龄</button>
</div>
</template>
<script>
export default {
name: 'Student',
data() {
console.log(this)
return {
msg: '我是一个学生',
myAge: this.age,
}
},
methods: {
updateAge() {
this.myAge++
},
},
//简单声明接收
// props:['name','age','sex']
//接收的同时对数据进行类型限制
/* props:{
name:String,
age:Number,
sex:String
} */
//接收的同时对数据:进行类型限制+默认值的指定+必要性的限制
props: {
name: {
type: String, //name的类型是字符串
required: true, //name是必要的
},
age: {
type: Number,
default: 99, //默认值
},
sex: {
type: String,
required: true,
},
},
}
</script>
mixin(混入)
混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能
-- mixin.js
export const hunhe = {
methods: {
showName() {
console.log(this, this.name)
},
},
mounted() {
console.log('你好啊!')
},
}
export const hunhe2 = {
data() {
return {
x: 100,
y: 200,
}
},
}
-- main.js
import Vue from 'vue'
import App from './App.vue'
import { hunhe, hunhe2 } from './mixin'
Vue.config.productionTip = false
// 全局混入, 整个应用中的vue实例,以及所有组件都可以使用混入的数据和方法
Vue.mixin(hunhe)
Vue.mixin(hunhe2)
new Vue({
el: '#app',
render: (h) => h(App),
})
-- school.vue
<template>
<div>
<div class="demo">{{ name }}</div>
<div>{{ address }}</div>
<div>{{ x }}</div>
<div>{{ y }}</div>
<button @click="showName">sch-mixin-btn</button>
</div>
</template>
<script>
import { hunhe, hunhe2 } from '../mixin'
export default {
data() {
return {
x: 666, // 数据冲突时,组件数据优先
name: 'Kylincsg',
address: '深圳',
}
},
mixins: [hunhe, hunhe2], // 局部混入. 只有school组件可以使用混入的数据和方法
methods: {
// 方法冲突时,以组件方法优先
showName() {
console.log('组件的showName', this, this.name)
},
},
// 钩子函数冲突时,将多个钩子合并成数组,每一个钩子都会调用,但是混入的钩子先执行
mounted() {
console.log('school-mounted你好啊!')
},
}
</script>
<style scoped>
.demo {
color: red;
}
</style>
插件
-- plugins.js
// 定义插件
export default {
install(Vue, a,b,c) {
// Vue是Vue的构造函数, a,b,c可以接收到使用插件时传入的参数
console.log('install方法被调用了', a,b,c)
//全局过滤器
Vue.filter('mySlice', function(value) {
return value.slice(0, 4)
})
//定义全局指令
Vue.directive('fbind', {
//指令与元素成功绑定时(一上来)
bind(element, binding) {
element.value = binding.value
},
//指令所在元素被插入页面时
inserted(element) {
element.focus()
},
//指令所在的模板被重新解析时
update(element, binding) {
element.value = binding.value
},
})
//定义混入
Vue.mixin({
data() {
return {
x: 100,
y: 200,
}
},
})
//给Vue原型上添加一个方法(vm和vc就都能用了)
Vue.prototype.hello = () => {
alert('你好啊')
}
},
}
-- main.js
Vue.use(plugin, 1, 2, 3) // 使用插件
下一篇:使用Vue脚手架