一、传统方式和组件方式编写应用比较
传统方式编写应用
组件方式编写应用
组件:就是实现应用中局部功能代码和资源的整合
二、单文件
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 注册的时候要用引号
第二种写法:CamelCase命名如MyStudent,需要vue脚手架支持
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等这些是不允许传入的
五、mixin
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一样