当前位置: 首页 > 后端技术 > Node.js

【Vue】组件基础与组件间通信

时间:2023-04-03 15:56:39 Node.js

div{color:red}Vue.js的核心功能是组件(Component)。从组件构建、注册到组件间通信,Vue2.x提供了更多方式让我们更灵活地使用组件来实现不同的需求。1.构建组件1.1组件基础组件由模板、数据、计算、方法等选项组成。注意:模板的DOM结构必须有一个根元素data必须是一个函数,数据通过return返回//示例:定义一个组件MyComponentvarMyComponent={{data:function(){return{//data}},template:'

Componentcontent
'}由于HTML特性不区分大小写,当使用kebab-case(小写破折号分隔的名称)定义组件时,引用也需要使用这种格式例如作为使用;在使用PascalCase(驼峰命名法)定义组件时,可以引用两种格式。1.2单文件组件.vue如果项目中使用了打包编译工具webpack,那么可以通过引入vue-loader,使用.vue后缀文件构建组件。一个.vue单文件组件(SFC)示例://MyComponent.vuefilediv{color:red}.vue文件让组件结构清晰。使用.vue还需要安装vue-style-loader等加载器,并配置webpack.config.js以支持解析.vue文件和ES6语法。进一步学习可以参考文章:SFC与vue-loader详解二、注册组件2.1定义了组件的手动注册后,需要注册后才能使用。注册分为全局注册和本地注册://全局注册,任何Vue实例都可以引用Vue.component('my-component',MyComponent)//本地注册,在注册实例的范围内有效varMyComponent={/*...*/}newVue({components:{'my-component':MyComponent}})//部分注册,使用模块系统,组件定义在统一文件夹中importMyComponentfrom'./MyComponent.vue'exportdefault{components:{MyComponent//ES6语法,相当于MyComponent:MyComponent}}注意全局注册的行为必须在创建根Vue实例(通过newVue)之前发生。2.2自动注册一般模块使用枚举注册方式代码很不方便,推荐使用自动全局注册。如果项目使用webpack,可以使用require.context一次性导入组件文件夹下的所有组件:importVuefrom'vue'importupperFirstfrom'lodash/upperFirst'//使用lodash进行字符串处理importcamelCasefrom'lodash/camelCase'constrequireComponent=require.context('./components',//其组件目录的相对路径为false,//是否查询其子目录/Base[A-Z]\w+\.(vue|js)$///匹配基础组件文件名的正则表达式)requireComponent.keys().forEach(fileName=>{//获取组件配置constcomponentConfig=requireComponent(fileName)//获取组件的PascalCase名称constcomponentName=upperFirst(camelCase(//去除文件名开头的`./`和结尾的扩展名fileName.replace(/^\.\/(.*)\.\w+$/,'$1')))//全局注册组件Vue.component(componentName,componentConfig.default||componentConfig)})3.组件通信3.1父单向propsVue2.x及之后的父组件使用props传递数据给子组件,这个传输是单向/正向的,反之则不行。这种设计是为了防止子组件无意中修改父组件的状态。子组件需要选项props来声明从父组件接收的数据。props可以是字符串数组或对象。.vue单文件组件示例如下//ChildComponent.vue父组件可以直接传入单个数据值,也可以使用命令v-bind动态绑定数据://parentComponent.vue配置路由后效果如下:3.2$emitfromchildtoparent当子组件向父组件传递数据时,需要使用自定义事件。在子组件中使用$emit()触发自定义事件,父组件使用$on()监听,类似于观察者模式。使用子组件$emit()的例子如下://ChildComponent.vue父组件监听自定义事件增加,并响应示例://parentComponent.vue访问parentComponent.vue页面,点击按钮,子组件会传值给父组件:3.3子孙关系链和索引组件有很多层次,这些组件的调用形式多个父链和子链父组件可以通过this.$children访问它的所有子组件,并且可以无限递归访问到最里面的组件。同样,子组件可以通过this.$parent访问父组件,无限递归访问到根实例。以下是子组件通过父链传值的部分示例代码://parentComponent.vue//ChildComponent.vue显然是点击按钮在父组件页面上,并接收子组件传递过来的消息。在业务中,尽量避免使用父链或子链,因为这种数据依赖会使父子组件紧耦合。一个组件被其他组件任意修改显然是不好的,所以组件间的父子通信常用props和$emit。3.4中央事件总线总线后代的链式通信显然会使组件紧耦合。同时,如何实现兄弟组件之间的通信?中央事件总线的方法就介绍到这里。实际上,使用了一个Vue实例(Bus)作为媒介。将需要通信的组件引入到Bus中,然后分别通过触发和监听Bus事件来实现组件之间的通信和参数传递。首先构建一个Vue实例作为总线://Bus.jsimportVuefrom'vue'exportdefaultnewVue;导入需要与Bus.js通信的组件,使用$emit发送信息://ComponentA.vue如果需要组件A的信息,使用$on监听://ComponentB.vue4.递归组件组件可以在自己的模板模板中调用自己,需要设置名称选择//??递归组件ComponentRecursion.vue如果递归组件没有count这样的限定数,会抛出错误(UncaughtRangeError:Maximumcall超出堆栈大小)。父页面使用了这个递归组件,Chrome中的VueDevtools可以看到组件递归了3次:递归组件可以开发层级关系未知的独立组件,比如级联选择器、树形控件。5.动态组件如果将Vue组件命名为Component,会报错(Donotusebuilt-inorreservedHTMLelementsascomponentid:Component),因为Vue提供了一个特殊的元素来动态挂载不同的组件.并使用is属性选择要挂载的组件。下面是使用动态挂载不同组件的例子://parentComponent.vuechangethis.currentView的值可以自由切换AB组件:类似于vue-router的实现原理,前端路由到不同的页面其实就是加载不同的组件。继续前进,男孩!