组件传值-provide-inject
通常情况下,父组件向孙组件传递数据,可以采用父子props
层层传递,也可以使用bus
和Vuex
直接交互。在Vue2.2.0之后,Vue还提供了provide/inject
选项
但是官网还是不太建议我们直接使用这个方法,因为怕我们“管不好”
//爷爷
<template>
<div>
<p>{{ title }}</p>
<son></son>
</div>
</template>
<script>
import Son from "./son"
export default {
name: 'Father',
components: { Son },
// provide选项提供变量
provide: {
message: 'provided by father'
},
data () {
return {
title: '父组件'
}
},
methods: { ... }
}
</script>
//爸爸
<template>
<div>
<p>{{ title }}</p>
<grand-son></grand-son>
</div>
</template>
<script>
import grandSon from "./grandSon "
export default {
name: "Son",
components: { grandSon },
data () {
return {
title: '子组件'
}
},
};
</script>
//孙子
<template>
<div>
<p>message:{{ message }}</p>
</div>
</template>
<script>
export default {
name: "GrandSon",
inject: [ "message" ],
data () {
return {
title: '孙组件'
}
},
methods: { ... }
};
</script>
我在App中可以调用Box2的数据,但是当我点击按钮时,是修改不了页面的数据的。
组件传值-provide-inject 响应式设计
这个就比较麻烦,provide得是一个函数返回值是data中的数据,使用者使用的时候,就是Box中使用的时候得把msg当成一个函数来使用,通过调用来收到数据
这里我点击按钮,可以发现页面变了
自定义事件的语法
Vue提供的技术:某继承Vue的组件有三个功能:
1.触发x组件的a事件: x.$emit(“a事件”,参数…)
2.给x组件绑定a事件 x.$on(“a事件”,监听器函数)
3.给x组件解绑a事件 x.$off(“a事件”,监听器函数)
现在当我直接点击第二个按钮时是界面是没有仍和反应的
现在我点击了第一个按钮,界面也没有仍和反应,但是当我现在点击第二个按钮时,控制台出现了打印,说明我点第一个按钮时成功给App组件绑定了myclick事件
<template>
<div>
<button @click="fn1">给App组件绑定一个myclick事件</button>
<button @click="fn2">触发自定义myclick事件</button>
</div>
</template>
<script>
export default {
methods:{
fn1(){
// 给App组件绑定myclick事件
this.$on('myclick',
function(arg1,arg2){
console.log('myclick事件触发了',arg1,arg2);
})
},
// 触发App组件的myclick事件
fn2(){
this.$emit('myclick',1,2)
}
}
};
</script>
<style scoped="scoped" lang="scss"></style>
中央事件总线
$bus 思路是在全局挂载一个实例,通过这个实例里的事件派发和事件监听实现跨组件通信,设计模式叫做观察者模式。一般用于跨多层级组件传参。
使用$bus的时候在接受bus的组件中别忘了再beforDestroy函数中销毁bus,不销毁的话会一直叠加的调用这个方法:
beforDestroy(){
this.$bus.$off("event"); //当这个组件销毁的时候bus也跟着一起销毁
}
通过创建一个新的vm对象,专门统一注册事件,供所有组件共同操作,达到所有组件随意隔代传值的效果
//vue-bus.js文件
const install = function (Vue) {
const Bus = new Vue({
methods: {
emit(event, ...args) {
this.$emit(event, ...args);
},
on(event, callback) {
this.$on(event, callback);
},
off(event, callback) {
this.$off(event, callback);
}
}
});
Vue.prototype.$bus=Bus;//由于这个新的vm放在与界面绑定的那个vm的原型上,因此页面上的所有组件都能通过this.$bus访问这个新vm对象
};
export default install;
//main.js文件
import VueBus from './vue-bus'
Vue.use(VueBus);
//组件文件中:
任意业务中都可以通过调用来绑定事件,触发事件并传值,和销毁事件
this.$bus.on(event,callback)
this.$bus.off(event,callback)
this.$bus.emit(event, ...args)
示例:
组件1:
this.$bus.on('changedFormObject',(val) =>{
//接受并处理传过来的值:val
this.msg = val;
});
组件2:
this.$bus.emit('changedFormObject',this.inputValue);//把组件2的data中的给inputValue值传给组件1
动态组件
有的时候,我们希望页面中的某个地方,在不同组件之间进行动态切换,这时候除了条件渲染,还可以使用动态组件
component 标签的 is属性语法:is后跟组件的变量名决定使用哪个组件来渲染
注意: is是组件名 :is是data中的变量中保存的组件名
<template>
<div id="app">
<button @click="fn">xx</button>
<components :is="com"></components>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
import HelloWorld2 from './components/HelloWorld2.vue'
export default {
name: 'app',
data(){return{
flag:true,
com:"HelloWorld",
}},
components: {
HelloWorld,"HelloWorld2"
},
methods:{
fn(){
this.flag=!this.flag
this.com=this.flag?"HelloWorld":"HelloWorld2"
}
}
}
</script>
缓存组件keep-alive
动态组件的切换,切换后是不会缓存之前被切换掉的组件的,每次切换新组件的时候,Vue 都创建了一个新的组件对象。
有时候我们希望在A组件时用户做了一些操作,切换B组件时做了一些操作,当切回A组件时希望记住A的操作,不要重新创建A组件,keep-alive可以缓存动态切换的组件
<!-- 失活的组件将会被缓存!-->
<keep-alive>
<component v-bind:is="currentTabComponent"></component>
</keep-alive>
<!-- 提供有include 和exclude 属性决定哪些组件可以被缓存(字符串或正则表达式)。!-->
<keep-alive :include="/a|b/">
<component v-bind:is="currentTabComponent"></component>
</keep-alive>
//include表示a,b组件被缓存,其他组件不缓存,exclude代表除了xx组件其他的组件缓存
匹配首先检查组件自身的 name 选项,匿名组件不能被匹配。
<template>
<div id="app">
<button @click="fn">xx</button>
<keep-alive>
<components :is="com"></components>
</keep-alive>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
import HelloWorld2 from './components/HelloWorld2.vue'
export default {
name: 'app',
data(){return{
flag:true,
com:"HelloWorld",
}},
components: {
HelloWorld,"HelloWorld2"
},
methods:{
fn(){
this.flag=!this.flag
this.com=this.flag?"HelloWorld":"HelloWorld2"
}
}
}
</script>
异步组件
vue开发过程中,我们会做出特别多特别多的组件,包括login,header,footer,main等等。这样使整个网站看起来就十分的庞大,当我们在打开网页的时候,突然一下子把这些所有的组件加载上来,这么多的请求全部同时开始请求,势必会造成网页打开很慢,使客户得到的是非常差劲的体验。
SPA: single page app
在单页应用中,如果没有用懒加载,运用webpack打包后的文件将会异常的大,造成进入首页时,需要加载的内容过多,延时过长,不利于用户体验,而运用懒加载则可以将页面进行划分,需要的时候加载页面,可以有效的分担首页所承担的加载压力,减少首页加载用时
异步加载并缓存组件:
1、 异步加载组件:用不到的组件不会加载,因此网页打开速度会很快,当你用到这个组件的时候,才会通过异步请求进行加载;
官方解释:Vue允许将组件定义为一个异步解析(加载)组件定义的工厂函数,即Vue只在实际需要渲染组件时,才会触发调用工厂函数,并且将结果缓存起来,用于将来再次渲染。
2、 组件缓存起来:通过异步加载的组件会缓存起来,当你下一次再用到这个组件时,丝毫不会有任何的疑迟,组件很快会从缓存中加载出来。
vue组件中require和import的区别
1.本质不同
import是一个解构过程,import语法会被转码为require;而require是一个赋值过程,其结果就是对象、数字、字符串、函数等,再把require的结果赋值给变量。
2.遵循的规范不同
import是es6中的一个语法标准,需要转化成es5语法;而require本身就是AMD规范的引入方式。
3.调用方式不同
import是在编译时调用,且必须在文件开头调用;而require是在运行时调用,可以在代码的任何地方进行调用。
4.性能不同
import只需要依据import中的接口在编译时引入指定模块;而require在在运行时引入模块并赋值给变量,性能相对于import稍低。
5.基本语法不同
使用import导出的对象与整个模块进行结构赋值,且对象必须与模块中的值一一对应;而require在导出的文件中定义module.export,其导出的对象的类型可以是任何类型,只需要在引入的文件中使用require()方法调用对象即可。