当前位置: 首页 > Web前端 > vue.js

Vue的流线型结构认知介绍

时间:2023-03-31 16:40:58 vue.js

@import'./App.scss'Vue的结构化前端开发由三部分组成:HTML(template模板)样式(CSS)逻辑(js)vue据此分为三部分。更精妙的整合来自单组件文件.vue的引入,可以将这三部分整合在一个组件中,然后将其作为一个微小的单元在其他地方使用。这里涉及到一个非常微妙的平衡:如果展示模板、展示样式、数据逻辑都由同一种语言来完成,那么就完全没有那么复杂的事情了。所谓的集成和组件,只是一个抽取的函数,或者抽取的一个公共类。把这三个部分分开,我觉得最初的思路是解耦,就是让三个不同功能的部分分别负责三种不同类型的文件。但是显然,通过这种方式要做到更好的权限控制和模块控制,并不容易。动不动就全局,造成各种命名空间冲突和不同模块之间未经授权的相互影响。所以需要整合。但是把小范围的三套结合起来,就很微妙了。这充分体现了“思想分离”不等同于“文件分离”。好的分离是在逻辑上做适当的分离,而不是分离文件。组件的概念被提取出来,充分展现了创作者分离的深刻思想,将耦合切割得恰到好处。使用vue-cli,可以在模板和样式部分设置相应的预编译工具,比如模板用pug,样式用scss或less。通过vue-cli脚手架集成这些模块化工具,可以快速提升您的开发效率,大大增强您代码的可维护性和健壮性。目录结构:Vue是一个单组件文件,通常将模板(HTML)、脚本(js)、样式(css)放在一起。但这不一定是好的做法。更好的办法是将css单独解压成一个文件,然后导入到.vue文件中。.├──index.scss└──index.vue这样做的原因是,与HTML中的少量代码不同,css中的代码量通常会急剧膨胀,这会影响可读性。将css和vue文件放在同一个目录下,保证了它们的整体完整性,同时也为后期维护css和调试提供了方便:可以根据视图快速定位到相应的位置。我们一般是按照视图区域的划分来提取组件。每个视图区域分别命名为一个文件夹。其src的目录结构如下:.├──App.scss├──App.vue├──assets│├──logo.png│└──style.scss├──main.js└──页面└──first_page├──components│├──query-nav││├──index.scss││└──索引。vue│└──res-content│├──index.scss│└──index.vue├──index.scss├──index.vue└──utils├──gen_test_data.js└──first_page_util.jsvue单组件文件示例:#app#vue-learningolli(v-for="todointodos"){{todo.text}}span(v-bind:title="message")将鼠标悬停在我身上几秒钟pspan(v-if="seen")现在你看到我了。p{{message}}button(@click="reverseMessage")反向消息输入(v-model="message")oltodo_item(v-for="itemingroceryList":todo="item":keyc="item.id")@import'./App.scss'可以看到在脚本部分,我们会导出一个default的对象,这个对象定义了vue需要的所有代码,并将它们归类为:datamethodscomponentspropscreatedmounted...从这个角度来说,这种结构将各个部分的代码进行了分类,更能构建复杂的项目清楚地。组件间的消息传递父子组件关系可以概括为:props向下,events向上。父组件通过props向下传递数据给子组件;子组件通过事件向父组件发送消息。当我们把整个项目按照视图区域分解成组件时,每个组件就相当于一个岛或者节点。如果一个组件的运行需要调用另一个方法,则需要相应的消息传递机制。从这个角度来说,引入组件之后的前端开发其实和后端开发没有太大区别。您需要在微观层面考虑各个组件的实现细节,在宏观层面提供合适的架构,高效整合组件间的通信。至于展示内容的骨架(HTML)和内容的样式(CSS)已经完全分离,你只需要专心用js实现相应的交互逻辑和数据流逻辑。不得不说,组件的引入让曾经混乱的类似于汇编语言的前端开发从原始时代进入了steam时代。组件之间的调用可以统一通过event-bus来完成,也可以通过传递信息给父组件来完成。个人更喜欢后一种方式,因为它迫使你对整个项目进行更清晰的逻辑拆分,否则你将很难通过父组件实现对各个子组件的消息统一分发。父组件使用:foo="foo_val"(v-bind:foo="foo"的简写)将父组件的foo_val传递给子组件。对应的补全语句可以写成:childComp(:foo="foo_val")。注意此时不需要设置父组件的数据部分。但是更好的办法是在父组件中设置foo_val的值,这样子组件接收到的foo值就可以随着父组件中foo_val值的变化而变化,即实现动态绑定。父组件代码:div(class="par-container")childComp(:foo="foo_val")@import"./index.scss";注意这里之所以在最外层定义了一个par-container是因为模板中只允许有一个根节点。所以通常我们在模板中做的第一件事就是定义一个根节点容器。对应的子组件代码:div(class="child-container")...tabletbodytemplate(v-for="taskinfoo")trtd{{task.id}}td{{task.name}}@import"./index.scss";子组件只需要在props中声明接受的参数即可。子组件可以直接使用这个声明的变量。这样,父组件将自己控制的一段数据传递给子组件,子组件的视图就动态绑定父组件的数据。这就是所谓的道具倒。然后就是事件上来了,也就是子组件触发了父组件的一个事件。它的使用场景是:子组件控制的视图区域有一个交互事件想要改变某个数据的值,但是这个值是在父组件中定义的。所以需要通过eventemit来触发父组件的一个事件,然后修改相应的数据。首先,父组件需要传递相应的事件给子组件,类似上面的:foo="foo_val",使用@bar="bar_func"传递:div(class="par-container")childComp(:foo="foo_val"@bar="bar_func")@import"./index.scss";子组件直接由this.$emit()方法触发。通常,我们会在子组件中再定义一个函数来表示相应事件的响应,然后在相应事件的函数中调用this.$emit()方法来触发父组件的事件:div(class="par-container")...表tbody模板(v-for="taskinfoo")trtd{{task.id}}i(@click="change_bar")td{{task.name}}@import"./index.scss";OK看,这里的change_bar就是子组件中click的响应事件函数。在其实现中,我们调用从父组件注册的事件栏。通过propsdown和eventsup,我们可以在组件之间自由交换数据。这里要注意整个逻辑拆分和项目设计的原则:父组件控制核心数据结构,子组件只负责展示核心数据(通过props动态绑定)。即:类似于调用getter。子组件触发的对核心数据的修改应该触发相应的父组件事件完成,而不是在子组件中进行修改。即:被调用的setter应该由父组件提供。之所以写在父组件中使用闭包构造data()部分的数据,是为了防止子组件对其进行修改,使其不得不依赖父组件的事件方法进行修改数据。这样就控制了父组件中核心数据的访问控制权限,使其封装更加完整。至于Vue其他有用的hook方法,比如双向绑定、computed、created、mounted等,都可以在相应的文档中找到使用方法,并没有本质上的难点。因为这些方法是在一个单独的vue组件中使用的,没有考虑组件之间的调用。