目录
一、ref 属性
1.1 之前获取DOM
<template>
<div>
<h1 v-text="msg" id="title"></h1>
<button @click="showDOM">点我输出上方的DOM元素</button>
<School></School>
<School></School>
</div>
</template>
下面是原生的方式调用DOM
methods: {
showDOM() {
console.log("@@");
//拿到h1标签并输出
console.log(document.getElementById('title'))
},
},
输出结果
1.2 Vue获取DOM
<template>
<div>
<h1 v-text="msg" ref="title"></h1>
<button @click="showDOM">点我输出上方的DOM元素</button>
<School></School>
<School></School>
</div>
</template>
采用ref属性获取DOM元素
methods: {
showDOM() {
console.log("@@");
//拿到h1标签并输出
// console.log(document.getElementById('title'))
//因为我们此vue文件是一个组件,此this代表着vc实例对象
console.log(this.$refs.title)
},
},
vc组件实例对象上有一个$refs属性
1.3 组件元素添加ref属性
<template>
<div>
<h1 v-text="msg" ref="title"></h1>
<button @click="showDOM">点我输出上方的DOM元素</button>
<School ref="sch"></School>
</div>
</template>
methods: {
showDOM() {
console.log("@@");
//拿到h1标签并输出
//因为我们此vue文件是一个组件,此this代表着vc实例对象
console.log(this.$refs.sch)
},
},
控制台输出结果
输出School组件的vc实例对象
1.4 总结
-
用来给HTML元素或子组件注册引用信息(id的替代者)
-
应用在html标签上获取的是真实DOM元素,应用在组件标签上获取的是组件实例对象(vc)
-
使用
<h1 ref="xxx"> ....</h1>
或者
<School ref="xxx"></School>
获取DOM元素
this.$refs.xxx
二、props 配置
功能:让组件接受外部传过来的数据
备注:props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,
若业务需求确实需要修改,name请复制props的内容到data中一份,然后去修改data中的数据,具体做法查看下面的案例
2.1 传递数据
普通传递
<demo name="xxx" sex="xxx" age="xxx">
传递的数据组件要接收,否则会报错,下面就是在接收数据的时候没接收"age"数据
传递number数据
此时传递的age字段是数字类型, 冒号代表v-bind,含义是传递的值必须是引号中JS表达式执行的结果
<demo name="xxx" sex="xxx" :age="xxx">
2.2 接收数据
2.2.1 简单接收
props:['name','sex','age']
也确实存在于vc实例中,并且下面三个字段都是靠props来的
2.2.2 限制类型
限制接收的字段的类型
让接收的字段是某个类型时才进行接收
props:{
name: String,
age:Number,
sex:String
}
假如说不一致的话可能会出现下面的错误
2.2.3 限制类型+限制必要性+指定默认值
props:{
name:{
type:String,
// 必须传入值
required:true
},
age:{
type:Number,
// 如果不传入值的话,会有一个默认值
default:99
},
sex:{
type:String,
required:true
}
}
2.3 案例
2.3.1 Student.vue
<template>
<!-- <template>标签不参与编译,在页面展现的是下面的一段结构 -->
<!-- 组件结构 -->
<div class="demo">
<h2> 学生名称:{{name}}</h2>
<h2> 学生年龄:{{age}}</h2>
<h2> 学生性别:{{sex}}</h2>
<button @click="showName">点我提示学生名</button>
</div>
</template>
<script>
export default {
name:'Student',
data(){
return{
// name:'张三',
// sex:'男',
// age:18
//this.name是外部传进来的 this在这里值得vc
// 这样也说明了props的优先级更高,要不然这里不能调用
MyName:this.name
}
},
methods: {
showName(){
alert(this.name)
}
},
// 顺序不一定要对上
// 接收外部传入数据
// props:['name','sex','age'] //最简单的写法,但是不能限制传进来的数据
// 接收的同时对数据进行类型限制
// props:{
// name: String,
// age:Number,
// sex:String
// }
// 接收的同时对数据进行类型限制+默认值的指定+必要性的限制
props:{
name:{
type:String,
// 必须传入值
required:true
},
age:{
type:Number,
// 如果不传入值的话,会有一个默认值
default:99
},
sex:{
type:String,
required:true
}
}
}
</script>
<style>
/* 组件的样式 */
.demo{
background-color:orange
}
</style>
2.3.2 App.vue
<template>
<div>
<!-- 在组件标签中还可以传入值 :age确保传入的值是数字,单向绑定,要传入双引号内表达式运行的结果
双引号内的表达式就是18 运行结果也是18数字,故可以-->
<Student name="李四" sex="女" :age="18"></Student>
</div>
</template>
<script>
// 引入组件
import Student from './components/Student'
export default {
name:'App',
// 注册组件
components:{
Student
}
}
</script>
<style>
</style>
三、mixin 混入
两个组件共享一个配置
我们Student.vue组件和School.vue组件中有一部分的代码是相同的,这个时候我们可以把相同的配置提取出来
假如组件中data和methods配置与mixin混入中的配置冲突了,以什么配置为准?
以组件中的配置为准
但是有特殊情况:假如组件A中有生命周期函数mounted,minxin配置中也有mounted配置,怎么办?
都会执行,有先后顺序。先执行minxin配置中的mounted,再执行组件A中的mounted函数
生命周期中的钩子函数不以任何一个组件为主,都会执行,来者不拒
3.1 mixin.js文件
创建mixin.js文件
这个文件名随便定义
export const mixin={
methods:{
showName(){
alert(this.name)
}
}
}
3.2 局部混入
Student.vue组件
<template>
<div>
<h2 @click="showName">学生姓名:{{ name }}</h2>
<h2>学生性别:{{ sex }}</h2>
</div>
</template>
<script>
//引入混合
import { mixin } from "../mixin.js";
export default {
//组件名称
name: "Student",
data() {
return {
name: "张三",
sex: "男",
};
},
//应用混合
mixins: [mixin],
};
</script>
<style scoped>
</style>
School.vue组件
<template>
<div>
<h2 @click="showName">学校名称:{{ name }}</h2>
<h2>学校地址:{{ address }}</h2>
</div>
</template>
<script>
//引入混合
import { mixin } from "../mixin.js";
export default {
//组件名称
name: "School",
data() {
return {
name: "齐工大",
address: "济南",
};
},
//应用混合
mixins: [mixin],
};
</script>
<style scoped>
</style>
3.3 全局混入
mixin不在组件中引入
在main.js中进行配置
// 该文件是整个项目的入口文件
// 引入vue,这个vue不能解析template配置项
import Vue from 'vue'
// 下面这个是引入完整版的vue。这个vue能解析template配置项
// import Vue from 'vue/dis/vue'
// 引入APP组件,它是所有组件的父组件
import App from './App.vue'
// 引入混合
import {mixin} from './mixin'
Vue.mixin(mixin) //这样一来所有的vc和vm都会得到这个混合
// Vue.mixin(mixin2) 有几个,就写一个这样的语句
// 关闭vue的生产提示
Vue.config.productionTip = false
// 创建vue实例对象---vm
new Vue({
el:'#app',
render: h => h(App),
})
其他组件就不需要配置了,直接使用即可
四、plugin.js 插件
功能:合理合法增强Vue
插件本质:包含install方法的一个对象,install的第一个参数是vue,第二个以后的参数是插件使用者传递数据
Vue会帮我们调用install函数
4.1 语法
4.1.1 plugin.js 文件
编写插件
export default{
install(){
console.log('@@@install')
}
}
插件还可以收到参数
接收的第一个参数a是Vue
export default{
install(a,b,c){
console.log('@@@install',a,b,c)
}
}
4.1.2 应用插件
一定要在创建Vue之前应用插件
//引入Vue
import Vue from 'vue'
//引入所有组件的外壳组件
import App from './App.vue'
//关闭Vue生产提示
Vue.config.productionTip = false
//引入插件
import plugins from './plugins'
//应用插件
Vue.use(plugins)
//创建vm
new Vue({
render: h => h(App),
}).$mount('#app')
配置完成后刷新页面,观察控制台
自动执行了插件中的install方法
还可以传递参数
//引入Vue
import Vue from 'vue'
//引入所有组件的外壳组件
import App from './App.vue'
//关闭Vue生产提示
Vue.config.productionTip = false
//引入插件
import plugins from './plugins'
//应用插件
Vue.use(plugins,10000000,2000000)
//创建vm
new Vue({
render: h => h(App),
}).$mount('#app')
4.2 应用
插件到底可以做什么呢? 如下所示
export default {
install(Vue) {
//1. 全局过滤器
Vue.filter('mySlice', function (value) {
return value.slice(0, 4)
})
//2. 全局自定义指令
Vue.directive('fbind', {
//指令与元素成功绑定时(初始时)
bind(element, binding) {
element.value = binding.value
},
//指令所在元素被插入页面时
inserted(element, binding) {
element.focus()
},
//指令所在的模板被重新解析时
update(element, binding) {
element.value = binding.value
},
})
//3. 定义混入
Vue.mixin({
data() {
return {
x: 100,
y: 200
}
}
})
//4. 向Vue原型上存放hello方法(vm和vc就都可以使用了)
Vue.prototype.hello = () => { alert('你好啊') }
}
}
五、scoped 样式
作用:让样式在局部生效,防止冲突
组件A中编写的样式和在组件B中编写的样式其实最终会汇总到一起,但是汇总到一起后会出现类名冲突
假如冲突了会以哪个结果为准?
关键是看在App.vue文件中后引入的是谁,以后引入的组件的样式为准,后来者居上
为了防止样式冲突,我们可以在样式上标注scoped 属性
<style scoped>
.demo {
background: skyblue;
}
</style>
这是怎么实现的呢?
其实是给最外侧的div加了一个特殊的标签属性,而且data-v后面的值都是随机生成的,每次运行的时候都会不一样
但是App.vue组件不适合用scoped属性
一般来说如果App.vue组件写样式的话,就是许多组件都在使用