快速详细解释前端框架Vue最强大的功能
组件是vue.js最强大的功能之一,组件实例的范围是相互独立的,这意味着不同组件之间的数据不能相互引用。一般来说,组件可以具有以下关系:
如上图所示,A和B,B和C,B和D都是父子关系,C和D是兄弟,A和C是代际关系(可能相隔多代)。
如何针对不同的使用场景选择有效的沟通方式?这就是我们要讨论的主题。总结了props、$emit/$on、vuex、$parent/$children、$attrs/$listeners、提供/注入等几种vue组件间的通信模式,并以通俗易懂的例子讲述了其中的区别和使用场景,希望对小伙伴们有所帮助。
请把这篇文章的代码戳到https://github.com/ljianshu/Blog,当你把它写在纸上时,它会很浅,所以每个人都应该多敲代码!
方法1:道具/$emit
父组件A通过道具传递给子组件B,B到A通过B组件中的$ emit和A组件中的v-on实现。
1.父组件将值传递给子组件
接下来,我们用一个例子来说明父组件如何将值传递给子组件:如何获取子组件Users.vue中的数据users 3360[' Henry ',' Bucky ',' Emily']
//App.vue父组件模板div id=' app ' users v-bind : users=' users '/users//前者的自定义名称方便子组件调用。后者将从'传递数据名称/div/模板脚本导入用户'。/components/users ' export default { name : ' app ',data(){ return { users :[' Henry ',' bucky ',Emily']},components 3360 { ' users ' : users } }//users子组件模板div class=' hello ' ul liv-for=' user in users ' { user } }/Li//遍历传递的值。然后呈现给页面/ul/div/template脚本导出默认{ name: ' hello world,prop : { user 3360 {//这是父组件type3360array中子标签的自定义名称,required d 3360 true } }/脚本摘要:父组件通过props向下传递数据给子组件。注意:组件中有三种形式的数据:数据、道具和计算数据
2.子组件将值传递给父组件(以事件的形式)
接下来,我们用一个例子来说明子组件如何向其父组件传递值:当我们点击“Vue.js Demo”时,子组件向其父组件传递值,文本由“传递一个值”变为“从子组件向父组件传递值”,从而实现子组件向父组件的值传递。
//子组件template header h1 @ click=' change title ' { title } }/h1//绑定一个click事件/header/templatescript导出默认值{name:' app-header ',Data(){ return { title : ' vue . jsdemo ' } },方法: {change title () {this。$ emit('标题已更改','子组件将值传递给父组件');//自定义事件传输值“子组件将值传输到父组件”}}} /script//父组件template div id=' app ' app-header v-: title changed=' UpdateTitle '/app-header//与子组件title保持一致changed自定义事件///UpdateTitle($ event)接受传递的文本H2 { { title } }/H2/div/模板脚本导入header from '。/components/header '导出默认{name:' app '。Data(){ return{ title: '传递了一个值' }},methods : { updatetitle(e){//将此函数声明为this . title=e;}},components 3360 { ' app-header ' : header,} }/脚本摘要:子组件通过事件向父组件发送消息,实际上,子组件向父组件发送自己的数据。
方法2,$emit/$on
该方法使用一个空的Vue实例作为中心事件总线(event center),并利用它来触发事件和监控事件,从而巧妙地、轻松地实现了包括父子、兄弟和跨级在内的任何组件之间的通信。当我们的项目相对较大时,我们可以选择更好的状态管理解决方案vuex。
1.具体实现:
var Event=new Vue();事件。$emit(事件名称,数据);事件。$on(事件名称,数据={ });2.举个例子
假设有三个兄弟组件,即A、B和C,C如何获取A或B的数据?
div id=' it any ' my-a/my-Amy-b/my-bmy-c/my-c/div模板id=' a' divh3a组件:{{name}}/h3button @click='send '将数据发送到c组件/按钮/div/template template id=' b ' div h3b组件:{{age}}/h3button @click='send '将数组发送到c组件/按钮/div/template template id=' c ' div h3c组件:{{name}},{{age}}/H3//定义一个空的Vue实例var a={template:' # a ',data () {return {name:' Tom'}},methods: {send () {event。$ emit ('data-a ',这个。姓名);} } } var B={ template: '#b ',data() { return { age: 20 } },methods: { send() { Event。$emit('data-b ',this . age);}}} var c={template:' # c ',data () {return {name3360 ' ',age:''},mounted () {//execute event。$ on ('data-a ',名称={this。名称)。//箭头函数内部不会有新的this。如果这里没有使用=的话,这里指的是event})事件。$ on ('data-b),age={this。年龄=年龄;})} } var VM=new Vue({ El : ' # itany ',components: { 'my-a': A,' my-b': B,' my-C ' : C } });/脚本
$on侦听自定义事件data-a和data-b,因为有时事件何时被触发是不确定的,通常在挂载或创建的钩子中侦听。
方法三,vuex
1.简要介绍Vuex原理
Vuex实现了单向数据流,并有一个全局存储数据的状态。当一个组件想要改变状态中的数据时,它必须通过突变来实现。突变还为外部插件调用和获取状态数据的更新提供了订阅者模式。
但是当所有异步操作(一般称为后端接口异步获取更新数据)或者批量同步操作都需要采取Action,但是Action不能直接修改State,或者State的数据需要通过突变进行修改时。最后,根据状态的变化,将其渲染到视图中。
2.简要介绍流程中各模块的功能:
Vue组件:Vue组件。在HTML页面上,负责接收用户操作等交互行为,并执行调度方法触发相应动作进行响应。
Dispatch:一种操作行为触发方法,是唯一可以执行动作的方法。
Actions:由组件中的$store.dispatch('action name ',data1)触发的操作行为处理模块。然后commit()触发突变的调用来间接更新状态。处理Vue组件接收到的所有交互行为。它包含同步/异步操作,支持多个同名方法,按照注册顺序依次触发。后台API请求的操作在这个模块中执行,包括触发其他动作和提交变异操作。该模块提供了承诺包,以支持行动链触发。
Commit:状态更改提交操作方法。提交变异是执行变异的唯一方法。
变体:状态改变操作方法,由动作中的提交(“突变名称”)触发。是Vuex修改状态的唯一推荐方法。方法只能同步,方法名只能是全局唯一的。在操作过程中,会暴露一些钩子来监控状态。
状态:页面状态管理容器对象。Vue组件中数据对象的分散数据被集中存储,并且对于统一的状态管理是全局唯一的。页面显示所需的数据是从这个对象中读取的,并且通过使用Vue的细粒度数据响应机制来高效地更新状态。
Getters:状态对象读取方法。该模块没有在图中单独列出,应该包含在渲染中。Vue组件通过这个方法读取全局状态对象。
3.Vuex和localStorage
Vuex是vue的状态管理器,存储的数据是响应的。但是,它不会被保存。刷新后会回到初始状态。具体来说,当vuex中的数据发生变化时,应该将数据的副本保存在localStorage中。刷新后,如果localStorage中有保存的数据,取出来替换存储中的状态。
让' defaultCity='上海尝试{ //用户关闭了本地存储功能,此时在外层加个尝试.catchif(!默认城市){默认城市=JSON。解析(窗口。本地存储。getitem('默认城市')} } catch(e){ }导出默认的新Vuex .商店({ state : { city 3360 default city }),突变: { changeCity(州、市){ state。city=city try { window。本地存储。设置项目(' DefaultCiTY ',JSON.stringify(州、市));//数据改变的时候把数据拷贝一份保存到localStorage里面} catch (e) {}})这里需要注意的是:由于状态管理里,我们保存的状态,都是数组,而localStorage只支持字符串,所以需要用数据转换:
JSON。stringify(state。订阅列表);//array-stringjson。解析(窗口。本地存储。getitem(' subscribe list ');//字符串数组方法四$attrs/$listeners 1 .简介
多级组件嵌套需要传递数据时,通常使用的方法是通过vuex。但如果仅仅是传递数据,而不做中间处理,使用状态管理处理,未免有点大材小用。为此Vue2.4版本提供了另一种方法- $attrs/$listeners
$ attrs:包含了父作用域中不被支柱所识别(且获取)的特性绑定(类和风格除外)。当一个组件没有声明任何支柱时,这里会包含所有父作用域的绑定(类和风格除外),并且可以通过v-bind='$attrs '传入内部组件。通常配合国际信托基金选项一起使用。
$listeners:包含了父作用域中的(不含。当地的修饰器的)v-on事件监听器。它可以通过v-on='$listeners '传入内部组件
接下来我们看个跨级通信的例子:
//index.vuetemplatedivh2浪里行舟/H2 child-com 1 : foo=' foo ' : boo=' boo ' :首席运营官='首席运营官' : doo=' doo ' title='前端工匠/child-com 1/div/模板脚本const child com 1=()=import(' ./child com 1。vue’);导出默认值{ components: { childCom1 },data(){ return { foo : ' JavaScript ',boo: 'Html ',coo: 'CSS ',do : ' Vue ' };} };/script//childcom 1。vuetemplate class=' border ' div pfoo : { { foo } }/ppchildcom 1的$ attrs : { { $ attrs } }/pchild-com 2v-bind=' $ attrs '/child-com 2/div/模板脚本const child com 2=()=import(' ./child com 2。vue’);导出默认值{ components: { childCom2 },inheritAttrs: false,//可以关闭自动挂载到组件根元素上的没有在小道具声明的属性道具: { foo : String//foo作为小道具属性绑定},创建了(){ console.log(this .$ attrs/{ ' boo ' : ' Html ',' coo': 'CSS ',' doo': 'Vue ',' title': '前端工匠' } } };/script//childcom 2。vuetemplatediv类=' border ' pboo : { { boo } }/ppchildcom 2: { { $ attrs } }/pchild-com 3v-bind=' $ attrs '/child-com 3/div/模板脚本const childcom 3=()=import(' ./child com 3。vue’);导出默认值{ components: { childCom3 },inheritAttrs: false,props: { boo: String },created() { console.log(this .$ attrs/{ ' boo ' : ' Html ',' coo': 'CSS ',' doo': 'Vue ',' title': '前端工匠' } } };/script//childcom 3。vuetemplatediv类=' border ' pchildcom : { { $ attrs } }/p/div/模板脚本导出默认值{ props: { coo: String,title: String } }/脚本
如上图所示$attrs表示没有继承数据的对象,格式为{属性名:属性值}。Vue2.4提供了$attrs,$listeners来传递数据与事件,跨级组件之间的通讯变得更简单。
简单来说:$ attrs与$listeners是两个对象,$attrs里存放的是父组件中绑定的非小道具属性,$listeners里存放的是父组件中绑定的非原生事件。
方法五、提供/注入
1.简介
Vue2.2.0增加了API,需要配合使用,让一个祖先组件可以将依赖注入到它的所有后代中,不管组件层次有多深,在建立上下游关系的时候总会生效。总之:祖先组件通过provider提供变量,然后后代组件通过inject注入变量。提供/注入API主要解决跨级组件之间的通信问题,但其使用场景是子组件获取上级组件的状态,跨级组件之间建立主动提供和依赖注入的关系。
2.举个例子
假设有两个组件:A.vue和B.vue,B是a的子组件。
//a.vue导出默认值{provide: {name: '乘风破浪' }}//b.vue导出默认值{inject: ['name'],mounted(){ console . log(this . name);//在波浪中划船}}可以看到,在A.vue中,我们设置了一个provide:名称,值为“在波浪中划船”。它的功能是为所有子组件提供变量名。
在B.vue中,组件a提供的name变量是通过inject注入的,所以在组件b中,这个变量可以通过this.name直接访问,它的值也是浪中之舟。这是提供/注入应用编程接口的核心用法。
请注意,提供和注入绑定没有响应。这是故意的。然而,如果你传入一个可监视的对象,它的对象的属性仍然是响应的——VUE的官方文件。因此,如果上面的A.vue的名字改变了,B.vue的这个.名字也不会改变,它仍然是一艘在波浪中的船。
3.如何实现3 .提供和注入之间的数据响应
一般来说,有两种方式:
提供一个祖先组件的实例,然后将依赖注入到后代组件中,这样就可以在后代组件中直接修改祖先组件实例的属性。但是,这种方法的缺点是许多不必要的东西,如道具和方法,都安装在这个实例上。
优化响应提供2.6中可观察到的最新API Vue(推荐)
举个例子:孙子D、E、F得到A组件传递的颜色值,可以实现数据响应式变化,即A组件颜色变化后,D、E、F组件不会随之变化(核心代码如下:)
//A组件div h1A组件/h1按钮@ click=' ()=changecolor()'更改颜色/button children b/children c//div.data(){ return { color : ' blue ' };},//提供(){//返回{//them : {//color : this。color//以这种方式绑定的数据没有响应。//}//组件A颜色改变后,组件D、E、F不会改变//};//},provide(){ return { them : this//方法1:提供祖先组件的实例};},methods : { change color(color){ if(color){ this . color=color;} else { this . color=this . color===' blue '?红色‘:’蓝色;}}}//Method 2 :优化了responsive provide//provide(){//this . theme=vue . observable({//color : ' blue '//});//返回{//them : this . theme//};//},//methods : {//change color(color){//if(color){//this . theme . color=color;//} else {//this . theme . color=this . theme . color===' blue '?红色‘:’蓝色;//}/}/}/}//F组件模板functional div类=' border 2 ' h : style=' { color 3360 injects . theme . color } ' F组件/h3 /div/Template脚本导出默认值{ inject : { theme : {//functional组件具有不同的默认值default 3360()=({ })} } };/script虽然provide和inject主要为高级插件/组件库提供用例,但如果能在业务中熟练使用,就能事半功倍!
方法6。$父项/$子项& ref
引用:如果在普通的DOM元素上使用,引用指向DOM元素;如果在子组件上使用,引用将指向组件实例
$parent/$children:访问父/子实例
需要注意的是,这两种方法都可以直接获取组件实例,使用后可以直接调用组件的方法或者访问数据。让我们首先看一个使用ref访问组件的例子:
//component-a subcomponent export default { data(){ return { title : ' vue . js ' } },methods : { say hello(){ window . alert(' hello ');} } }//父组件template component-a ref=' coma '/组件-a/templatescriptordefault { mounted(){ const coma=this。$ refs.com;console . log(CoMa . title);//Vue . js CoMa . SayHello();//弹出窗口} }/脚本然而,这两种方法的缺点是不能跨级别或者兄弟之间进行交流。
//parent.vue component-a/component-component-b/component-b/component-b我们想要访问引用它的页面中的两个component-b组件(这里是parent . vue)。在这种情况下,我们必须配置额外的插件或工具,例如Vuex和Bus解决方案
摘要
常见的使用场景可以分为三类:
亲子沟通:家长通过道具向孩子传递数据,孩子通过事件($ emit)向家长传递数据;
沟通也可以通过父链/子链($ parent/$ children);
引用也可以访问组件实例;
提供/注入API
$attrs/$listeners
兄弟交流:公交;状态管理
跨级通信:总线;Vuex提供/注入应用编程接口、$ attrs/$监听器
摘要
以上是边肖带来的前端框架Vue最强大的功能的快速详细讲解,希望对大家有所帮助。如果你有任何问题,请给我留言,边肖会及时回复你的!
版权声明:快速详细解释前端框架Vue最强大的功能是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。