Vue全家桶:vue2+vue3全部搞懂:第八篇,重要!正式工程化项目开发——开始怎么写代码

前提,建议先学会前端几大基础:HTML、CSS、JS、Ajax,不然不好懂

这一专栏知识将一次性将vue、vue2vue3全部讲明白

这一篇内容蛮多,我本人也打算加快学习速度,于是下面大量解释将出自于黑马程序员的视频课堂截图,本人就不在拿自己写的案例做解释。

一、了解一下项目文件的结构

上一篇经历了痛苦折磨地创建vue脚手架之后,我们就可以开始工程化开发写代码了,写代码之前先了解一下vue脚手架的各个文件结构,下面是个简单的介绍图:

重点看一下:

1、【src】里的index.html

我们不会再在HTML里写vue的模板语法,而是在App.vue里提供渲染结构,而index.html就是一个容器,相当于你要涂鸦,index.html就为你提供一面可涂鸦的墙

2、接下来是【src】里的main.js文件

我们打开Vscode的终端,然后在这也可以打开vue项目脚手架的服务器

这里补充一下,上一篇我讲得比较模糊,如果你创建的vue项目的key是yarn,那就只能【yarn serve】启动;如果是npm,那就只能【npm run serve】启动

打开浏览器之后我们就可以边改代码边看浏览器的变化

那么现在我把main.js这些初始代码的解释通过下图解释一下:

然后下面那个vue实例化跟我们以前学的不太一样,我稍微改一下各位看看,做个对比

那还有人看不懂render函数是什么玩意,这里我把render函数完整写法写出来解释一下

以前我们是在HTML里用{{ }}来创建vue渲染的结构

而现在是用App.vue,而App.vue就需要搭配main.js里的render函数来创建渲染结构,所以要写一个render函数,里面通过一个基于App的函数创建渲染结构

3、然后是App.vue

当我们点开这个文件,代码可能会是灰色的,可能会跳出提示“是否安装Vue-Official”,安装它就完事,然后回到文件,就变成彩色了

 或者还有个插件可以帮助把.vue文件代码变成高亮模式

然后App.vue文件就是用来渲染index.html的,当然他自己也有自己的组件

总结:那么大致看完应该就有个思路了

首先我们开启服务器,然后就进入【main.js】这个入口文件

然后【main.js】导入【App.vue文件】创建渲染结构,就相当于一个“时尚服装品牌公司”找到了一个优秀的“服装设计师”

然后【App.vue】这个“服装设计师”设计好了几套精美绝伦的衣服,那现在给谁穿呢?

通过【main.js】里的实例Vue对“#app”的绑定,相当于“时尚服装品牌公司”找到了“模特公司”——index.html,在这个“模特公司”里选定了给id名字叫“app”的这个“模特”穿上【App.vue】设计好的服装

二、Vue的组件化开发:什么是组件

先直接拿黑马程序员视频截图看一下解释

以前我们布局一个页面,全都是在HTML里,然后一个大页面就是一个<div>,然后有头部、主体、导航......,可是一个复杂的页面每个部分都还有很多很多细节,比如一个头部有logo、搜索框、登录注册按钮......一乱的话整个页面div可能都得改,那就得用组件化开发

简单来说,以前HTML的标签代码就还是HTML的DOM标签元素

然后像这种可以我们直接自定义名字,然后单独在一个【.vue文件】里设置好它的样式,然后通过一些“声明”让它们可以在任何文件里用的,就叫组件

组件又分:根组件、普通组件

根组件:App.vue文件就是根组件!它包括了整个页面的各大块

普通组件:【整个页面的各大块(头部、侧边、底部、中间......)】 以及 【各大快里的各小块(头部里的小按钮、搜索框、小图标.......)】

然后既然每一个.vue】文件就是一个组件,那么来看一下一个【.vue】文件的三大部分主要是以下:

提示:

这里将一个快捷写法直接生成【.vue】文件这三大部分:直接"<vue"就出来了

三、怎么用组件

1、分析【.vue】文件怎么写,怎么用.vue文件创建一个组件

(1)、首先想要有一个结构必须得先有<template></template>

它提供一个结构,然后可以在里面写div容器、自定义组件,你可以暂时按照以前HTML的逻辑把它当成<body>体

注意了,在vue2里面,<template></template>里只能有一个父容器,也就是说你设了一个div,你就只能在这个div里面去添加别的容器,而不能写一个跟它同级别的div

不过在vue3里面没有这个规则,在vue2需要注意

(2)、接着你就像HTML那样写一个<style></style>标签

在里面写样式即可

(3)、我们还可以在<script></script>标签里写行为

不过这里会自动生成这么一堆代码,我们都不要

然后我们要自己先写上【export default{  }】,意思是导出当前组件的配置项,有了它就可以往里面配置我们之前学vue里的【data、methods、computed、watch、生命周期8大钩子函数】

总结:

2、怎么去创建一个App.vue根组件里的【各个小组件】,并使用他们?

1、根组件

这没什么好讲的,就跟写HTML一样,在【App.vue】代码里开启一个<templat></template>结构,接着往里面设置一个大容器<div>,然后往里直接添加普通小组件即可

2、普通组件

首先】:凡是普通组件都是在【components】文件夹里创建的【.vue】文件

(1)、局部组件

局部组件简单来说:自定义好后,你在哪个【.vue】文件里手动“引入”了,就能在那个【.vue】文件里使用,然后各个局部组件之间设置好了自己的样式,互相之间不会影响

(这里以后【引入】我们称为【注册】;【.vue文件】称为【组件】)

大概语法模板:

(一)先到【components】文件夹下创建【.vue】文件

注意名字一定要用“小驼峰”命名(大写字母...大写字母...),否则会强制报错,哪怕你定义的名字至少一个单词,反正你就是要么一个单词里全是小写字母,要么你就至少两个单子拼起来,这两个单词首字母都大写

(二)到要使用它的其他组件里写下面这些【注册】语法

具体例子:

解释一下【注册】这块

(2)、全局注册

简单来说就是:在【main.js】里去【注册】(引入),然后就不需要再去某个组件里分别去注册了,想在哪用在哪用

比如现在我需要在每一个普通组件里设置一个【通用按钮】这么个普通小组件,那我总不可能到每一个组件的【.vue】文件里去声明【注册】吧?那就只需要在【main.js】里进行一次全局注册即可

(一)、还是第一步,到【components】文件夹创建【组件】并设置好样式

(二)、然后再【main.js】文件里写入以下代码:

具体例子:

搞定!

四、组件的一些注意点:

(1)先讲一下全局样式局部样式

如果你在多个组件里用同名的选择器设置样式,那么是跟以前在HTML里一个CSS选择器对多个同名元素的影响一样,虽然你只是在某一个组件的【.vue】里设置它的样式,但是如果其他组件里又相同名字的元素一样会受影响,这就是【全局样式】

比如下面这个例子,我只想在BaseOne这里设置它有边框,于是我直接在BaseOne.vue里用了div选择器

但是我的BaseTwo里面也有div,虽然我并没有给它设置样式,但是BaseOne.vue的对div的样式也给到了BaseTwo,甚至App.vue里也因为有div而被赋予了这个样式

怎么办?1、要么你专门给它一个独立的class、id选择器

               2、要么在当前组件的<style>标签加上一个【scoped】,设置为【局部样式】!

至于scoped的原理我就简单讲一下,只想快速学会怎么使用的可以跳过,原理就是加上了之后,vue会自动给他标签里加上一个“自定义属性名”——也就是【data-xxx】这种就叫自定义属性名,然后vue生成的自定义属性名具体形式是【data-v-哈希值】,然后css选择器也都会被添加上【data-v-哈希值】,最后vue再通过哈希值找到对应的标签和样式选择器

(2)script部分的原来vue里的data只能是函数了

以前写vue是这样,data是一个对象,里面配成员变量

现在的data只能是函数,写成对象就错!

不过data函数return的值是对象

然后在组件部分,我们要显示值得地方还是一样用{{  }}绑定上【data】里【return的对象值】里的【其中一个成员】就行,而且v-on触发事件那里也不需要绑定函数名,直接绑定对{{ }}绑定的这个元素的【运算操作】即可,如下图

那这样有什么用?这样的话,存在多个该组件的的时候,每个组件对应一个data函数返回的值,那么这多个组件之间的数据是相互独立、互不影响的,比如下图

五、组件之间数据的“通信”

因为组件和组件之间是相互独立的,那么他们的数据也是独立的,那要怎么在一个组件里获取别的组件的数据呢?

1、不同的组件关系

首先看一下有哪些组件关系:

2、不同组件关系的不同组件通信方案

父子组件关系:

父传子

注意:

1、在【父组件里】的子组件,用【v-bind】指令添加一个自定义的属性(【v-bind: xxx = "..."】可以省略成【: xxx = "..."】)

2、在【子组件里】的script里设置props来获取数据,这里props只是简单获取(1到多个)值的话就写成【数组】形式,里面的成员的名字必须跟父组件用【v-bind】传过去的自定义属性名一样!如果对传过来的值有要求限制,那就设置成对象

props补充

这里再给个例子,更清晰的理解props:

那么props不仅仅可以【单个字符串对应一个值】这样传递,还可以以【单个对象对应一个值】,这样写法的好处是可以像数据库那样,限制传过来的值是错误的、不符合要求的乱值

子传夫

子传夫有点绕,我这里给大伙捋一捋:

1、子传夫不能直接传,必须一定要通过触发一个事件才能传。

那么就在子组件里设置一个函数,这个函数里通过【this.$emit( )函数】把修改的值传过去,最后要设置一个DOM元素,通过对这个元素的一些“点击、输入......”这些事件来触发刚刚设置的函数执行

2、this.$emit( )函数需要传两个参数,第一个是【自定义事件名】,意思就是你自定义了一个事件,然后当父组件文件里的子组件触发了这个【自定义事件】就可以获得传过来的值;第二个参数就是要传过去的值

3、那么前面已经在子组件里设置了【自定义事件】了,那么在父组件里的子组件就要触发这个【自定义事件】,并再触发时绑定执行父组件文件的一个函数

4、那么当父组件里的子组件就要触发这个【自定义事件】时要执行的函数,就是做修改值操作的函数,在我们父组件里设置一个函数,然后设置一个形参,这个形参就能获得【this.$emit( )】传过去的值,那么最后在函数里把【要修改的值 = 形参】就修改成功了

易错点:

如果一个数据是在父组件里写好的,然后通过【父传子】给到子组件,那么子组件绝对绝对不可以直接去修改这个值,因为props不支持外部传进来的值被直接修改

那么这时候我们就可以调用一些函数,去通过this.$emit( )函数,把想要把这个值修改成什么样的这个“愿望”反传回给父组件,然后在父组件里面改

比如,在父组件设置了count,然后传给子组件,子组件通过props获得之后,想直接在button里通过@click="count++"这样去该值,不行!!  只能在子组件里配置methods,然后设置一个可以调用this.$emit( )的函数,然后通过@click来触发执行这个函数,而this.$emit( )的函数传过去的值就是【this.count+1】这个“愿望”给到父亲,父亲接受后执行修改操作即可

记住:谁的数据谁负责!父亲的数据还回给父亲改,儿子的数据儿子自己改

非父子关系数据通信:

简单捋一捋:

【1、创建一个空vue】相当于一个媒婆、话事人

【2、在接收方组件里调用这个“空Vue”的$on监听事件】,男方叫媒婆去“打听”一下女方对于“相亲”(自定义事件)什么意愿呢?

【3、在发送方组件里调用“空Vue”的$emit函数发送数据】,女方叫媒婆“传话”,针对“相亲”(自定义事件)这件事自己的想法是什么(数据值)

具体例子:

首先要去utils创建一个js文件,在js文件里做三个常规操作:【导入vue】、【创一个空Vue实例】、【用export default导出这个空Vue】

拓展:怎样跨过儿子,直接将父组件的数据一直往子孙后代传下去

我们知道了父传子的通信方式,那么如果我想一直把父亲组件的数据继续往下传,传给孙子、曾孙子......我总不能每次都按照父传子的方式一级一级往下传吧,这就用到了provide和inject配置项

具体例子:

另外注意,如果传的是普通类型,后期修改后新的值并不会影响到子孙组件;只有对象类数据,在后期改动过后,还剩子孙组件那边也会跟着改

六、重要!搭配v-model修改组件之间的值

首先回顾一下v-model数据双向流通的底层原理:

v-model的原理其实就是结合了【v-bind:value = "xxx"】和【@事件 = "进行对value数据的操作"】

这里讲一下【@事件 = "xxx = $event.target.value"】这种形式,如果想获得【事件event】的“形参”的话,要写成【$event】才行,e、event这些都不行

比如下面这个例子,在input输入框内输入时直接将输入数据和data的数据双向流通,这两种写法都是一样的:

然后先在来看一下v-model怎么配合【组件间数据流通】,前面我们讲过,父亲传给儿子组件的值是不可以直接在儿子组件里改的,父亲的值只能在父亲里改!

那么如果我在父亲里设置了值,然后传给儿子组件;然后在儿子组件里使用了【v-model】来操作父亲传过来的数据;此时就会报错!因为开启了v-model,数据在子组件里的(DOM标签)和(JavaScript的vue)就双向流通了,那么如果(DOM标签)触发了某些事件,就会导致在子组件里修改了父组件的数据值

说的有点乱,没耐心的估计不会看,我举个例子:我自定义设置了一个子组件【下拉菜单】,然后我在父组件里设置了city这个值【传给子组件】,用父组件这个city当成子组件的下拉菜单的value,那么此时在子组件设置了v-model就会错!因为子组件要是改变了下拉菜单选项,就是在修改父组件传过来的city的值!

那要是想在点下拉菜单的时候改变这个数据值怎么办?

那就把【v-model】拆开成:【v-bind:value = "xxx"】和【@事件 = "进行对value数据的操作"】

然后通过【@事件 = "进行对value数据的操作"】把修改的值传给父亲组件那边,让父组件在自己那边修改

(上面的例子是拿黑马程序员的截图做一个错误示范,下面这个是我自己写的例子,绿色表示父亲传儿子的路径,蓝色表示儿子传回给父亲的路径)

这里会有一些不理解的地方:

1、为什么儿子传过去的的【e.target.value】,而父亲不是用【$event.target.value】接收?

因为【$event】是一个【事件的形参!!】只要对方传的是事件或者事件的属性,就统一用它来接收,如果对方传过来的是事件对象e,那【$event】就是一个事件对象;如果只是事件的某个属性,那【$event】也就是一个事件属性

2、这些自定义名字看着乱七八糟的,到底谁对应谁?

看下面这个图这样理解,你们就当成函数之间的实参形参传递就行了

因人而异吧,可能有的人觉得我这个图看完更乱了哈哈

那么怎么在Vue工程化项目名里写组件(可理解为DOM元素)、怎么互相传数据,就先大概讲到这

下一篇接着讲深入的Vue工程化项目代码编写。

  • 24
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值