一、传统方式和组件方式编写应用比较
传统方式编写应用
组件方式编写应用
组件:就是实现应用中局部功能代码和资源的整合
二、单文件
1、非单文件组件
1、什么是非单文件组件:一个文件中包含n个组件
2、单文件组件
一个文件只包含一个组件,单文件组件都是.vue结尾的
3、使用组件三大步骤
第一步:定义组件
第二步:注册组件
第三步:使用组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="root">
<!--第三步骤:使用组件-->
<student></student>
</div>
</body>
<script>
/*第一步:定义组件*/
const student = Vue.extend({
/*自定义组件时,不要用el属性,
因为最终所有的组件都是被vm管理,由vm决定要挂载到哪个容器*/
//使用template可以配置组件结构
template:`
<div>
<span>{{name}}</span>
<span>{{age}}</span>
</div>
`,
/*data要写成普通函数形式,不能写成对象形式,因为一个组件被多个地方使用,任何一个地方修改了data对象,其他地方也会发生变化*/
data(){
return{
name:'张三',
age:20
}
}
});
//第二步:注册组件(全局注册)
Vue.component('student',student);
const vm = new Vue({
el:"#root",
/*第二步:注册组件(局部注册)*/
components:{
student
}
});
</script>
</html>
备注:
1、组件名写法
一个单词组成
第一种写法:首字母小写如student
第二种写法:首字母大写Student
多个单词组成
第一种写法:kebab-case命名如my-student 注册的时候要用引号
2、一个简写方式
const student = Vue.extend(options) 简写 const student = options
上面案例简写
const student = {
/*自定义组件时,不要用el属性,
因为最终所有的组件都是被vm管理,由vm决定要挂载到哪个容器*/
//使用template可以配置组件结构
template:`
<div>
<span>{{name}}</span>
<span>{{age}}</span>
</div>
`,
/*data要写成普通函数形式,不能写成对象形式,因为一个组件被多个地方使用,任何一个地方修改了data对象,其他地方也会发生变化*/
data(){
return{
name:'张三',
age:20
}
}
}
三、ref
1、作用
获取dom元素或者组件实列对象vc
2、实现
<template>
<div>
<!--ref应用在组件上-->
<student ref="stu"></student>
<!--ref应用在dom元素是-->
<h1 ref="dom" id="dom"></h1>
<button @click="showDom">获取h1dom</button>
</div>
</template>
<script>
import student from "./student";
export default {
name: "test",
components:{
student
},
data(){
return{
}
},
methods:{
showDom(){
//原生通过id获取元素
console.log(document.getElementById('dom'))
//ref应用在组件上获取的是组件实列对象vc
console.log(this.$refs.stu)//
//ref应用在dom元素是 获取真实的dom元素
console.log(this.$refs.dom)//
}
}
}
</script>
<style scoped>
</style>
结果
四、props
1、作用
同一个组件传入不同数据展示不同界面
2、实现
定义一个展示学生信息的组件(模板),传入数据展示不同的学生信息
<template>
<div>
<h1>{{msg}}</h1>
<h1>{{name}}</h1>
<h1>{{age}}</h1>
</div>
</template>
<script>
export default {
name: "student",
data(){
return{
msg:'hello'
}
},
/*第1种:声明简单接受*/
props:['name', 'age']
//第2种:接受+限制类型
props:{
name:String,
age:Number
}
//第3种:接受+限制类型+默认值+必填指定
props:{
name:{
type:String,//类型
required:true//必填
},
age:{
type: Number,
required: false,
default:10//默认值
}
}
}
</script>
<style scoped>
</style>
调用
<template>
<div>
<!--传入组件所需值即可-->
<student name="张三" :age="15"></student>
</div>
</template>
<script>
import student from "./student";
export default {
name: "test",
components:{
student
},
data(){
return{
}
}
}
</script>
<style scoped>
</style>
说明
1、props不允许修改的,如上面的student页面修改age值,控制台有错误提示,若业务有需要可以在student中的data中定义一个属性,将props的复制即可
<template>
<div>
<h1>{{msg}}</h1>
<h1>{{name}}</h1>
//这里是data中的值
<h1>{{myAge}}</h1>
</div>
</template>
<script>
export default {
name: "student",
data(){
return{
msg:'hello',
//复制props的属性值
myAge:this.age
}
},
props:['name', 'age']
}
</script>
<style scoped>
</style>
2、有些值不能传比如key ref等这些是不允许传入的
1、作用
把多个组件共用的配置提取成一个混入(mixin)对象
2、定义混入
定义一个js文件 文件名自定义 内容
export const hunru1 = {
data(){
return{
x:200
}
},
methods:{
showNum(){
alert("111")
}
},
mounted() {
console.log("minin钩子函数")
}
};
export const hunru2 = {
data(){
return{
xx:400
}
}
}
3、局部混入
<template>
<div>
<h1>{{name}}</h1>
<h1>{{age}}</h1>
<!--直接使用混入中的属性值-->
<h1>{{x}}</h1>
<h1>{{xx}}</h1>
</div>
</template>
<script>
import {hunru1, hunru2} from "../mixin";
export default {
name: "student",
data(){
return{
name:'张三',
age:10
}
},
//如果混入也有挂载 先执行混入的
mounted() {
console.log("1111")
},
//必须是数组,所以可以引入多个
mixins:[hunru1,hunru2]
}
</script>
<style scoped>
</style>
4、全局混入
再main.js中使用
import Vue from 'vue'
import App from './App.vue'
import {hunru1, hunru2} from "./mixin";
//项目中所有的vc 和vm引入
Vue.mixin(hunru2)
Vue.mixin(hunru1)
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
5、说明
混入中定义data和methods中属性或者和方法在原组件中的重复了 则以原组件为准,但是如果钩子重复了则都会执行 先执行原组件的再执行混入的
六、scoped
1、scoped作用
让样式局部生效 防止全局冲突
<style scoped>
</style>
2、原理
通过给当前组件根元素加一个data-v,然后结合选择器实现
说明
<!--如果不写lang 则默认使用css,使用less需要安装less-loader 安装如果出现webpack版本错误 将less-loader版本降低-->
<style lang="less" scoped>
</style>
七、组件化通信
1、父传子
方式:通过props
2、子传父
方式:自定义emit事件
3、任意组件之间通信
1、安装全局事件总线
new Vue({
render: h => h(App),
beforeCreate() {
Vue.prototype.$bus = this
}
}).$mount('#app')
2、使用事件总线
在要接受数据的组件中给bus绑定自定义事件,事件的回调留在组件自身
mounted(){
this.$bus.on('hello',mydata)
}
提供数据
this.$bus.$emit('hello',mydata)
最好在beforeDestroy钩子中,用$off去解绑当前组件所用到的事件
this.$bus.$off('hello')
第二种方式:消息订阅与发布
八、浏览器存储
localstorage和sessionStorage统称webStorage
1、localStorage
1、特定
浏览器关闭 存储的数据不会消失,只有以下两种情况会消失
引导用户操作了localstorage的clear()或者removeItem()
用户清空了浏览器缓存
2、相关api
/*存储相关*/
//存储相同的key会替换
localStorage.setItem("name","dddd")
localStorage.setItem("name","dddd1")
//数值类型存储会转成字符串
localStorage.setItem("age",19)
//只要value给的不是string 会转成string,即调用的tostring 所以下面存储的[object,object]
localStorage.setItem("person",person)
//可以通过json.stringify()将对象转成字符串存储
localStorage.setItem("person1",JSON.stringify(person))
/*读取*/
console.log(localStorage.getItem("name"))
console.log(localStorage.getItem("age"))
console.log(localStorage.getItem("person1"))
//读没有存储的数据 返回的是null,JSON.parse(xxx)也返回null
console.log(localStorage.getItem("xx"))
//读取对象字符串并转成对象
console.log(JSON.parse(localStorage.getItem("person1")))
/*删除*/
//删除指定的key
localStorage.removeItem("person")
//清空
localStorage.clear();
2、sessionStorage
1、会话存储,浏览器一关闭 sessionStorage存储的数据消失
2、所有的api和localStorage一样