vue教程8.09学习(VUE开发0基础)
vue教程8.09学习(VUE开发0基础)这里是vuecli的官方站点 https://cli.vuejs.org/zh/guide/通常我们通过vuecli来创建一个工程,这样可以获得标准的vue工程目录结构。为了更好地帮助你理解本文介绍的知识点,请下载例子工程进行调试https://github.com/lshxq/examples_tsyvue创建一个vue工程
哈喽哈喽 大家好,今天给大家分享一个vue的进阶课程。
在大部分的vue教学课程中,介绍的内容都比较基础,其实呢,那么基础的内容,我推荐大家直接去vue官方站点看 文档就好,那里最权威,vue作者尤玉溪本身就是华裔,所以中文文档非常完善,如果您有html和js的基础知识,那直接去看官方文档,里面详细介绍了vue的各种特性,自己阅读文档是吸收效率最高的方式,看视频课程大脑容易分神。
vue官方教程 https://cn.vuejs.org/v2/guide/
本期课程主要是vue在实际项目中的一些进阶知识点。
为了更好地帮助你理解本文介绍的知识点,请下载例子工程进行调试
https://github.com/lshxq/examples_tsyvue
创建一个vue工程
通常我们通过vuecli来创建一个工程,这样可以获得标准的vue工程目录结构。
这里是vuecli的官方站点 https://cli.vuejs.org/zh/guide/
当然,vuecli完成的事情手动也是可以完成的,他就是个命令行工具,把原版手动创建工程的过程做了一些批处理。
无论是手动创建,还是vuecli自动创建,我们期待的工程目录应该是这个样子。
main.js是整个前端程序的入口,现在前端开发有别于传统页面开发,传统页面开发是,首先通过html编写一个页面的主结构,页面的大致内容就在这个html文件中了,如果页面中涉及到动态内容,比如从后端拉取的数据,那就通过页面内引入的js发起ajax请求拉去数据,然后通过js创建页面dom解构,每个页面是一个独立的html文件。
现在的前端,包括vue react在内,都是单页面应用程序SPA (Single page application),整个工程就一个index.html,而且这个文件几乎是空的,仅放了一个id为app的div,作为以后所有动态页面的挂载点,也就是说,页面刚开始加载的时候是一个空dom,没有任何页面内容,之后你看到的所有有页面都是通过 js 动态创建出来的dom。
vue的核心 会通过状态机 动态 维护页面内容。这些由vue创建出来的dom,我们叫 托管的dom,在现在工程中,我们也提倡所有dom都应该交给vue来托管,不要通过js手动修改dom节点。
main.js中,首先借助es6的模块管理,把相关依赖引入工程,有些模块还需要初始化,比如vue插件element-ui,需要vue.use一下来注册全局组件。我们自定义的全局组件,全局mixin也是在main.js中处理的,最后 实例化vue对象,把这个vue对象挂在到ID为app的div中。下面是一个最简单的main.js的例子。
App.vue ,在main.js 中我们看到工程引入了一个app.vue 的根组件,并且要求vue实例渲染了这个app组件。那么App.vue中通常是用来干什么的呢?以下是一个最基础的App.vue的实例。
为了提高html的编写效率,我这里使用的pug语言作为html模板语言,后面会进一步介绍pug。
可以看到app.vue中主要就是构建了页面主要结构,这个页面首先按照上下分为header和body两部分,body又按照左右解构分为了左侧导航菜单,和右侧的主视图,其中主视图是通过vue-router根据url 映射,动态渲染的router-view组件。例子中的header和navi是两个为了简化app.vue的书写,而提供的进一步细化的子组件。
NPM
npm 就是 node package management,也就是node的包管理器, 现在前端工程主要是 按照es6的标准开发的,和传统的 js 相比, es6有完善的包管理机制,传统的js 都是以文件为单位,在页面中引入后,当前页面就是他的生活环境,这样开发简单,但弊端非常明显,被引入同一html的不同js都在同一个命名空间下,变量、函数非常容易重名,变量提升,引入js太多容易引起不可预计的bug。
为了前端开发的工程化的管理,我们现在都是在node环境下,利用es6的module来区分命名空间,各个module可以互相引用(import),但是之间又是相互隔离的,不会产生重名和变量提升的问题。很多人开了了很多方便的js小工具,就通过npm来发布,这样在node的环境下,可以通过在package中注册 dependency的方式引入外部依赖。比较有名的小工具如 lodash、vue、axios、element-ui、还有本人开发的tsyvue都是通过npm发布的,使用相当方便, npm就等价于java环境中的maven这样的工程配置工具。
vue-router
现在前端都会有一个前端路由,SPA既然是单页面程序,那是如何实现页面迁移效果的呢?就是通过前端路由,前端路由的原理其实很简单,你自己也可以写一个前端路由,只是考虑的没有人家成熟,功能没有人家丰富罢了,前端路由最基础的一个功能,就是url映射,把不同的视图组件映射到各自的url上。
也就是前端路由一直在监听url的变化,只要url发生改变,他就会到 路由配置 数组中去寻找,看看有没有对应该url的视图组件,然后把匹配的视图组件,通过 v-if 给显示显示出来,v-if是从无到有的构建过程,这里加载的视图组件就有了组件的生命周期,并且前端路由会把url解析结果,作为一个对象,绑定在 this.$route上, 你可以从$route上拿到url中携带的信息。前端路由最复杂的部分也就是url解析的部分了,他会把url中携带的各种参数绑定在$route的params和query当中。
这里是vue-router的官方文档, 详细功能 请参阅 https://router.vuejs.org/zh/introduction.html
路由的配置通常就是一个大数组,记录着url和对应组件的关系。在实例化vue-router时传入该数组。并在main.js中把实例化出来的vue-router实例挂在vue实例上(参考main.js第35行)。
路由数组实例
path是url的pattern,说它是pattern,是因为这里可以通过模式匹配绑定参数。
name是路由的名字,全局唯一,在页面跳转时推荐使用路由名字作为页面跳转的参数。
component就是对应的视图组件,决定当前url到底显示哪个组件。
meta是绑定在$route对象的元数据,非必须,通常用来绑定用来构建导航菜单的信息,或者鉴权信息。非必须。
前端路由还会提供路由拦截的功能,我们叫导航守卫,也就在url发生变化时,优先走路由拦截器,根据拦截器的结果决定是否继续初始化视图组件,或者迁移到其他组件上。路由拦截器通常也是做权限管理的地方,可以根据用户身份信息,决定 他到底能不能访问这个页面,还是给他迁移到友好地拒绝页面上。
关于导航守卫的介绍请 看官方文档 https://router.vuejs.org/zh/guide/advanced/navigation-guards.html
鉴权
现在工程开发通常是无会话的方式鉴权。传统的server会结合浏览器分配一个sessionid,然后服务器端维护一个session对象,每次相同的sessionid访问时,server会更新对应session对象的时间戳,来保持会话活跃,并且有个独立线程清理 过期(默认30分钟)session对象,用户的登录信息就放在这个session对象内,session一旦过期,需要用户重新登录。这种模式已经不适应门户站点的开发了,门户站点的一个特点就是流量大,所以后端不可能是单服务节点,通常都是服务集群,每个请求上来时,会被负债平衡到不同的服务节点上,这样就不具备session对象了。
现在比较主流的是利用jwt 来维持登录状态, jwt是一个服务器分配的字符串,前端上报用户登录信息后,后端验证通过,根据用户信息,签发jwt token,前端拿到登录应答返回的jwt token后,把他把存在cookie里,这样每个请求都会自动上报这个jwt token。后端服务节点的鉴权拦截器 从request header 中 拿到 jwt token来解析用户信息,如果解析失败,认为用户没有的登录,在需要的场合可以在jwt 拦截器中直接返回401要求用户登录(内部信息系统,门户网站通常不登录也能使用大部分功能)。jwt token中通常编码了 用户信息,登录信息,时效信息,服务端的jwt 拦截器可以解析出来这些信息。前端点击logout(登出)时,其实就是清理了本地cookies中的 jwt 信息,这样下一个请求 的header中就不包含登录信息了。
Axios
前端页面要展示的数据都是后端接口 返回的。前端通过ajax 调用接口获得想用数据,绘制页面。Axios是对ajax的封装,非常好用,同类型了还有vue-resource,都是同一类东西,我推荐使用axios。下面是axios发起ajax请求的一个例子。
可以看到axios函数返回的是一个Promise对象。then代表服务器成功处理并返回的结果。catch是服务器返回了非2XX系列的http应答码,代表有需要关注的错误。axios的请求配置中,关于参数分为 params和data两种,请求类型如果是GET,那么需要通过params上报参数,这时参数是放在url后买的,注意url的长度限制。当请求为post put patch时,以data上报参数,参数是放在请求体中的,无长度限制。
工程中,我们通过只实例化一个axios实例,这个axios实例会做一下工作:
1. 携带身份信息,如果后台需要鉴权,那么身份信息可能是存在cookie中的,但对于大部分后台系统,都约定 jwt应该放在请求头的Authorization可以在axios的请求拦截器中 读取 cookies信息统一添加 请求头信息。
2. 401的批量处理,当后台返回http应答码401时,通常需要前端统一迁移到login页面,这个应该在axios的应答拦截器中实现。
3. 后台报错消息统一处理,我们可以和后台约定 统一的报错消息字段,在应答拦截器中发现该字段有值时直接在页面上弹出,不用每个页面单独处理。
上面代码中我们实例化了一个axios对象,挂在了请求拦截器和应答拦截器。之后把这个实例绑定到vue实例上,就可以使用了。
HTTP请求报文
http是基于tcp/ip之上的一个超文本传输协议,报文内容是存文本,明文,可读,如果你用代理的方式拦击网卡数据,你会发现http请求报文是这个样子的。
第一行分别是请求方法,url,http版本。
请求头
空一行
请求体
Content-Type指出请求体是一个json。
HTTP应答码
2XX: 代表服务器成功处理的请求, 通常是200, 也可以根据公司情况细化应答码, 比如检索接口返回 204 代表没有找到匹配的记录。
3XX: 通常需要浏览器改变行为,比如301,请求重定向,相当于呼叫转移,就是后端接口改了地址,你调用老地址,他返回301帮你自动指向到新地址。 304,表示浏览器存在该资源的缓存版本,且资源没有变化,无需重新下载。
4XX:通常指用户能修正的错误。比如401,未登录,通常会迁移到登录页面要求用户登录, 403,权限不足,比如普通用户访问了其他用户的私有资源,提示无权限访问。404,代表这个资源找不到了,没有了。
5XX:代表服务器产生了没有处理的错误,比如程序有bug,空指针异常,除数为0等等吧,就是程序员考虑不周全的地方,或者是硬件问题,导致内存读取不了啥的,内存溢出等等。
这里仅仅是给出一些通俗易懂的例子,更详细的请另行检索。
单文件组件
在工程中最常用的vue开发模式就是单文件组件的。 这里是他的官方介绍 https://cn.vuejs.org/v2/guide/single-file-components.html
单文件组件就是一个 .vue的文件,比如 订单列表 可以是 order-list-index.vue 。这个文件内容 上中下 分为三部分。当然这三个部分都是可选的,可有可无。
模板
最上面是页面模板 ,内容放在 template标签内。template默认语言是html, 但本人推荐 使用pug, 因为pug书写更简洁美观,更程序员。html是早年的基于xml的语言,标签有开始和闭合,虽然严谨,不要求格式,但是作为coder,pug可以帮你少敲50%的代码量,这才是coder的追求,精简美观优雅。pug主要是使用缩进表达 包含关系, 配合css选择器,来修饰标签。
这是两个等价的模板的对比,可以看到pug省略了很多无意义的字符。代码写的越多,pug越省。越少的字符读起来也越快,代码越多越混乱,越难以维护。
使用pug需要在工程下引入pug相关依赖,用来翻译pug到html
控制程序
vue2的控制程序是基于options的配置方式
这些官方教程介绍的非常详细了,这里只针对 vue初级用户容易混淆的 computed 和 watch做一下介绍。
computed,计算属性,他的目的时为了 得到一个新的值,重点在于 你期待得到一个值, 虽然这个得到的值 也可以 通过watch的方式来计算,但是那样会很笨拙。
这是一个用计算属性的例子。根据依赖自动产生 新的值。
watch的用途是当资源变化的时候去干一个关联是事情,watch的重点是要触发一个行为,当然这个行为可能会产生新的值,也可能不会。
比如我们观察检索条件对象,当检索条件发生变化后,自动触发检索,这个检索组要是通过ajax向后台拉取数据,当然相当于产生了需要在页面上显示的新内容。但watch主要是触发行为。
初学vue的很多程序员经常把computed该做的事交给watch去做,看起来很麻烦,也很蹩脚。
面试时如果不能清楚的介绍出computed和watch的区别,面试官就会大概了解你的水平了。
样式
样式放在style标签里面,和template一样,也可以指定语言,默认时css,我推荐 采用 sass,sass和pug的语法高度匹配,可以是你的文件看起来整体感很强。
使用sass作为 预处理css 需要在工程下引入下面的依赖
更多关于sass的功能,请 参考官方文档 https://sass.bootcss.com/documentation
需要注意的是,node-sass的版本需要和node-js的版本对应,不然工程会产生编译错误,相应sass-loader的版本,也需要和node-sass的对应版本相匹配,具体的对应关系,可以在node-sass以及sass-loader的官网找到。
工程中,每个被路由声明成一个页面的组件 都是一个 xxx.vue, 放在views文件夹下按模块分类。
element-ui
element-ui是在vue生态中使用非常广泛的ui组件,现在页面开发中,如果是用html基础标签,那自己要做的事情就太多了,基础的html标签,比如form个各种input,样貌丑陋,功能单一,自己从美化,到很多基础功能都需要自己来编写代码,开发工作量太大了。element-ui就是解决这个问题的。官方文档 https://element.eleme.cn/#/zh-CN/component/installation
element-ui的组件首先很漂亮,比如修饰后的form的各种input 按钮
从外观到动画都有相应的修饰,节省了我们很大部分的时间。element还提供了各式各样的功能组件,布局组件,甚至常用的ICON,基本上涵盖了日常开发你会用到的所有功能人家都开发好了。
tsyvue
element-ui非常强大,但是如果只使用element-ui,那么在开发信息系统的时候,依然要有大量工作没有提炼成共通。比如分页查询,比如表单开发,tsyvue就是解决这个问题的,介绍文档在这里
http://tsy.zone/tsyvue/home
一个信息系统中,页面主要分为两大类,一类是检索页面,另一类就是表单页面。
检索页面的共通特点是,存在检索条件,用户出发检索按钮,向后台发起检索请求,拉取去要显示的数据,通常还会一页显示10条记录,当匹配的结果多余10条时,还需要做分页,分页控制中,还要做连续点击的处理,当多次点击下一页按钮后,应确服务器乱序返回的数据能够正确回显到页面上。
表单页面通常分为新建和编辑两套逻辑,其中新建和编辑,在layout上应该高度相同,仅部分字段可能是在编辑页面中不可变更的,需要一些特殊控制,另外编辑页面,在页面初始化时会拉去待编辑的数据。剩下关于表单验证,数据提交,提交后处理应该都是一样的。
基于上面的总结,我们发现,无论是检索页面,还是表单页面,都存在大量的共性,如果每个程序员都去自己开发这些过程,那么会因为各个程序员的能力不同、认知不同导致原本应该一致的行为,在各个页面中千奇百怪,给人留下产品一致性差,质量差的印象。
tsyvue的核心就是为了解决这个问题,把检索页面、和表单页面都做了规范处理,开发这只需要传入少量参数,就能轻松开发检索和表单页面,只需要把精力投入在layout的搭建上即可,大大减少了开发工作量,提升产品一致性。
tsyvue可以通过npm引入到工程中
npm install tsyvue
注意,因为tsyvue还比较新,在cnpm的库中可能不存在,如果安装失败,请切换会npm的源。
安装后需要在main.js中注册一下,以载入全局组件
tsyvue的组件全部时 sy-XXXXX。
下面是 检索页面的开发样例,使用了sy-pagin-data组件
这里使用的html模板部分使用的是pug语言,可以看到,第4行到第9行是构建的检索条件。第11行到第17行是核心的检索组件,提供了数据检索,分页的功能,其中仅url是唯一的必须参数,代表检索请求的目标接口位置,query是 检索条件,可有可无,非必须,看需求,如果执行了query对象,那么当query对象的内容发生变化时,会自动完成检索。第20行开始,你可以通过slot-scope拿到当前页面的数据,你只需要专注在每一条数据的绘制上就可以了。应用了 sy-pagin-data后,开发一个检索页面变得尤其简单。这就是tsyvue的强大之处。