Vue 知识点汇总(下)--附案例代码及项目地址

文章目录

  • Vue
      • 预备知识与后续知识及项目案例
    • 一、简介
      • 1.Vue (读音 /vjuː/,类似于 view)的简单认识
      • 2.Vue.js安装
    • 二、Vue知识量化
    • 三、内容
      • 1、Webpack 详解
        • 什么是Webpack?
        • 前端模块化
        • **和grunt/gulp的对比**
        • webpack安装
        • Webpack 起步
        • Webpack配置
        • css-loader的使用
        • less文件处理
        • 图片文件处理
        • ES6语法处理
        • Webpack 配置 Vue
        • el和template区别
        • Vue组件化开发引入
        • plugin的使用
        • 搭建本地服务器
      • 2、Vue CLI
        • **什么是Vue CLI**
        • **Vue CLI使用前提 - Node**
        • Vue CLI使用前提 - Webpack
        • Vue CLI2详解
        • Vue CLI3
      • 3、vue-router详解
        • 认识路由
        • 后端路由阶段
        • 前端路由阶段
        • 认识vue-router
        • 细节处理
        • 路由的懒加载
        • **路由嵌套**
        • 传递参数
        • **导航守卫**
        • keep-alive遇见vue-router
        • 案例:[TabBar](#TabBar)
      • 4、Promise
        • 什么是Promise呢?
        • Promise的基本使用
        • Promise的链式调用
      • 5、Vuex详解
        • 认识Vuex
        • Vuex的基本使用
        • Vuex核心概念
        • 项目结构
      • 6、网络模块封装
        • 网络模块的选择
        • jsonp
        • **axios**
        • axios的实例
        • 拦截器
    • 四、案例
      • 1、TabBar

Vue

预备知识与后续知识及项目案例

HTML入门与进阶以及HTML5
CSS
JS-上
JS-下
jQuery
Node.js + Gulp 知识点汇总
MongoDB + Express 入门及案例代码
Vue项目开发-仿蘑菇街电商APP

Vue 知识点汇总(上)–附案例代码及项目地址

一、简介

1.Vue (读音 /vjuː/,类似于 view)的简单认识

(1)Vue是一个渐进式的框架,什么是渐进式的呢?

  • 渐进式意味着你可以将Vue作为你应用的一部分嵌入其中,带来更丰富的交互体验。
  • 或者如果你希望将更多的业务逻辑使用Vue实现,那么Vue的核心库以及其生态系统。
  • 比如Core+Vue-router+Vuex,也可以满足你各种各样的需求。

(2)Vue有很多特点和Web开发中常见的高级功能

  • 解耦视图和数据
  • 可复用的组件
  • 前端路由技术
  • 状态管理
  • 虚拟DOM

这些特点,你不需要一个个去记住,我们在后面的学习和开发中都会慢慢体会到的,一些技术点我也会在后面进行讲解。
(3)学习Vuejs的前提?
从零学习Vue开发,并不需要你具备其他类似于Angular、React,甚至是jQuery的经验。
但是你需要具备一定的HTML、CSS、JavaScript基础。

2.Vue.js安装

使用一个框架,我们第一步要做什么呢?安装下载它

安装Vue的方式有很多:

方式一:直接CDN引入
你可以选择引入开发环境版本还是生产环境版本

 



方式二:下载和引入

开发环境 https://vuejs.org/js/vue.js

生产环境 https://vuejs.org/js/vue.min.js

方式三:NPM安装

后续通过webpack和CLI的使用,我们使用该方式。

二、Vue知识量化

Vue 知识点汇总(下)--附案例代码及项目地址_第1张图片

三、内容

注:本文多数内容属于Vue2.6之前的内容,只有较为重要的地方才会补充2.6版本之后的内容,望周知。

1、Webpack 详解

什么是Webpack?

什么是webpack?
这个webpack还真不是一两句话可以说清楚的。
我们先看看官方的解释:
At its core, webpack is a static module bundler for modern JavaScript applications.
从本质上来讲,webpack是一个现代的JavaScript应用的静态模块打包工具。
但是它是什么呢?用概念解释概念,还是不清晰。
我们从两个点来解释上面这句话:模块 和 打包

Vue 知识点汇总(下)--附案例代码及项目地址_第2张图片

前端模块化

前端模块化:

在前面学习中,我已经用了大量的篇幅解释了为什么前端需要模块化。
而且我也提到了目前使用前端模块化的一些方案:AMD、CMD、CommonJS、ES6。
在ES6之前,我们要想进行模块化开发,就必须借助于其他的工具,让我们可以进行模块化开发。
并且在通过模块化开发完成了项目后,还需要处理模块间的各种依赖,并且将其进行整合打包。
而webpack其中一个核心就是让我们可能进行模块化开发,并且会帮助我们处理模块间的依赖关系。
而且不仅仅是JavaScript文件,我们的CSS、图片、json文件等等在webpack中都可以被当做模块来使用(在后续我们会看到)。
这就是webpack中模块化的概念。

打包如何理解呢?

理解了webpack可以帮助我们进行模块化,并且处理模块间的各种复杂关系后,打包的概念就非常好理解了。
就是将webpack中的各种资源模块进行打包合并成一个或多个包(Bundle)。
并且在打包的过程中,还可以对资源进行处理,比如压缩图片,将scss转成css,将ES6语法转成ES5语法,将TypeScript转成JavaScript等等操作。
但是打包的操作似乎grunt/gulp也可以帮助我们完成,它们有什么不同呢?

和grunt/gulp的对比

grunt/gulp的核心是Task

  • 我们可以配置一系列的task,并且定义task要处理的事务(例如ES6、ts转化,图片压缩,scss转成css)
  • 之后让grunt/gulp来依次执行这些task,而且让整个流程自动化。
  • 所以grunt/gulp也被称为前端自动化任务管理工具。

我们来看一个gulp的task

下面的task就是将src下面的所有js文件转成ES5的语法。
并且最终输出到dist文件夹中。

Vue 知识点汇总(下)--附案例代码及项目地址_第3张图片

什么时候用grunt/gulp呢?

如果你的工程模块依赖非常简单,甚至是没有用到模块化的概念。
只需要进行简单的合并、压缩,就使用grunt/gulp即可。
但是如果整个项目使用了模块化管理,而且相互依赖非常强,我们就可以使用更加强大的webpack了。

所以,grunt/gulp和webpack有什么不同呢?

grunt/gulp更加强调的是前端流程的自动化,模块化不是它的核心。
webpack更加强调模块化开发管理,而文件压缩合并、预处理等功能,是他附带的功能。

webpack安装

安装webpack首先需要安装Node.js,Node.js自带了软件包管理工具npm
查看自己的node版本:
在这里插入图片描述

全局安装webpack(这里我先指定版本号3.6.0,因为vue cli2依赖该版本)
在这里插入图片描述

局部安装webpack(后续才需要)
–save-dev`是开发时依赖,项目打包后不需要继续使用的。
在这里插入图片描述

为什么全局安装后,还需要局部安装呢?
在终端直接执行webpack命令,使用的全局安装的webpack
当在package.json中定义了scripts时,其中包含了webpack命令,那么使用的是局部webpack

Webpack 起步

准备工作

我们创建如下文件和文件夹:
文件和文件夹解析:

  • dist文件夹:用于存放之后打包的文件
  • src文件夹:用于存放我们写的源文件
    • main.js:项目的入口文件。具体内容查看下面详情。
    • mathUtils.js:定义了一些数学工具函数,可以在其他地方引用,并且使用。具体内容查看下面的详情。
  • index.html:浏览器打开展示的首页html
  • package.json:通过npm init生成的,npm包管理的文件(暂时没有用上,后面才会用上)

mathUtils.js文件中的代码:

main.js文件中的代码:

Vue 知识点汇总(下)--附案例代码及项目地址_第4张图片

js文件的打包

现在的js文件中使用了模块化的方式进行开发,他们可以直接使用吗?不可以。
因为如果直接在index.html引入这两个js文件,浏览器并不识别其中的模块化代码。
另外,在真实项目中当有许多这样的js文件时,我们一个个引用非常麻烦,并且后期非常不方便对它们进行管理。

我们应该怎么做呢?使用webpack工具,对多个js文件进行打包。
我们知道,webpack就是一个模块化的打包工具,所以它支持我们代码中写模块化,可以对模块化的代码进行处理。(如何处理的,待会儿在原理中,我会讲解)
另外,如果在处理完所有模块之间的关系后,将多个js打包到一个js文件中,引入时就变得非常方便了。
OK,如何打包呢?使用webpack的指令即可

Vue 知识点汇总(下)--附案例代码及项目地址_第5张图片

使用打包后的文件

打包后会在dist文件下,生成一个bundle.js文件
文件内容有些复杂,这里暂时先不看,后续再进行分析。
bundle.js文件,是webpack处理了项目直接文件依赖后生成的一个js文件,我们只需要将这个js文件在index.html中引入即可

Vue 知识点汇总(下)--附案例代码及项目地址_第6张图片

Webpack配置

入口和出口

我们考虑一下,如果每次使用webpack的命令都需要写上入口和出口作为参数,就非常麻烦,有没有一种方法可以将这两个参数写到配置中,在运行时,直接读取呢?
当然可以,就是创建一个webpack.config.js文件

Vue 知识点汇总(下)--附案例代码及项目地址_第7张图片
局部安装webpack

目前,我们使用的webpack是全局的webpack,如果我们想使用局部来打包呢?
因为一个项目往往依赖特定的webpack版本,全局的版本可能很这个项目的webpack版本不一致,导出打包出现问题。
所以通常一个项目,都有自己局部的webpack。
第一步,项目中需要安装自己局部的webpack
这里我们让局部安装webpack3.6.0
Vue CLI3中已经升级到webpack4,但是它将配置文件隐藏了起来,所以查看起来不是很方便。
在这里插入图片描述

第二步,通过node_modules/.bin/webpack启动webpack打包

Vue 知识点汇总(下)--附案例代码及项目地址_第8张图片

package.json中定义启动

但是,每次执行都敲这么一长串有没有觉得不方便呢?
OK,我们可以在package.json的scripts中定义自己的执行脚本。

Vue 知识点汇总(下)--附案例代码及项目地址_第9张图片
package.json中的scripts的脚本在执行时,会按照一定的顺序寻找命令对应的位置。
首先,会寻找本地的node_modules/.bin路径中对应的命令。
如果没有找到,会去全局的环境变量中寻找。
如何执行我们的build指令呢?

在这里插入图片描述

css-loader的使用

loader是webpack中一个非常核心的概念。

webpack用来做什么呢?
在我们之前的实例中,我们主要是用webpack来处理我们写的js代码,并且webpack会自动处理js之间相关的依赖。
但是,在开发中我们不仅仅有基本的js代码处理,我们也需要加载css、图片,也包括一些高级的将ES6转成ES5代码,将TypeScript转成ES5代码,将scss、less转成css,将.jsx、.vue文件转成js文件等等。
对于webpack本身的能力来说,对于这些转化是不支持的。
那怎么办呢?给webpack扩展对应的loader就可以啦。

loader使用过程:
步骤一:通过npm安装需要使用的loader
步骤二:在webpack.config.js中的modules关键字下进行配置
大部分loader我们都可以在webpack的官网中找到,并且学习对应的用法。

https://www.webpackjs.com/concepts/

css文件处理 - 准备工作

项目开发过程中,我们必然需要添加很多的样式,而样式我们往往写到一个单独的文件中。
在src目录中,创建一个css文件,其中创建一个normal.css文件。
我们也可以重新组织文件的目录结构,将零散的js文件放在一个js文件夹中。
normal.css中的代码非常简单,就是将body设置为red
但是,这个时候normal.css中的样式会生效吗?
当然不会,因为我们压根就没有引用它。
webpack也不可能找到它,因为我们只有一个入口,webpack会从入口开始查找其他依赖的文件。

在入口文件中引用:

Vue 知识点汇总(下)--附案例代码及项目地址_第10张图片

css文件处理 – 打包报错信息

重新打包,会出现如下错误:

Vue 知识点汇总(下)--附案例代码及项目地址_第11张图片

这个错误告诉我们:加载normal.css文件必须有对应的loader。

css文件处理 – css-loader

在webpack的官方中,我们可以找到如下关于样式的loader使用方法:
按照官方配置webpack.config.js文件
注意:配置中有一个style-loader,我们并不知道它是什么,所以可以暂时不进行配置。
Vue 知识点汇总(下)--附案例代码及项目地址_第12张图片

重新打包项目:
但是,运行index.html,你会发现样式并没有生效。
原因是css-loader只负责加载css文件,但是并不负责将css具体样式嵌入到文档中。
这个时候,我们还需要一个style-loader帮助我们处理。

css文件处理 – style-loader

我们来安装style-loader
在这里插入图片描述

注意:style-loader需要放在css-loader的前面。
疑惑:不对吧?按照我们的逻辑,在处理css文件过程中,应该是css-loader先加载css文件,再由style-loader来进行进一步的处理,为什么会将style-loader放在前面呢?
答案:这次因为webpack在读取使用的loader的过程中,是按照从右向左的顺序读取的。
目前,webpack.config.js的配置如下:

Vue 知识点汇总(下)--附案例代码及项目地址_第13张图片

less文件处理

less文件处理 – 准备工作

Vue 知识点汇总(下)--附案例代码及项目地址_第14张图片

less文件处理 – less-loader

继续在官方中查找,我们会找到less-loader相关的使用说明
首先,还是需要安装对应的loader
注意:我们这里还安装了less,因为webpack会使用less对less文件进行编译
在这里插入图片描述

其次,修改对应的配置文件
添加一个rules选项,用于处理.less文件

Vue 知识点汇总(下)--附案例代码及项目地址_第15张图片

图片文件处理

图片文件处理 – 资源准备阶段

首先,我们在项目中加入两张图片:
一张较小的图片test01.jpg(小于8kb),一张较大的图片test02.jpeg(大于8kb)
待会儿我们会针对这两张图片进行不同的处理
我们先考虑在css样式中引用图片的情况,所以我更改了normal.css中的样式:
在这里插入图片描述

如果我们现在直接打包,会出现如下问题

Vue 知识点汇总(下)--附案例代码及项目地址_第16张图片

图片文件处理 – url-loader

图片处理,我们使用url-loader来处理,依然先安装url-loader
在这里插入图片描述

修改webpack.config.js配置文件:

Vue 知识点汇总(下)--附案例代码及项目地址_第17张图片

再次打包,运行index.html,就会发现我们的背景图片选出了出来。
而仔细观察,你会发现背景图是通过base64显示出来的
OK,这也是limit属性的作用,当图片小于8kb时,对图片进行base64编码

图片文件处理 – file-loader

那么问题来了,如果大于8kb呢?我们将background的图片改成test02.jpg
这次因为大于8kb的图片,会通过file-loader进行处理,但是我们的项目中并没有file-loader
Vue 知识点汇总(下)--附案例代码及项目地址_第18张图片

所以,我们需要安装file-loader
在这里插入图片描述
再次打包,就会发现dist文件夹下多了一个图片文件

在这里插入图片描述

图片文件处理 – 修改文件名称

我们发现webpack自动帮助我们生成一个非常长的名字
这是一个32位hash值,目的是防止名字重复
但是,真实开发中,我们可能对打包的图片名字有一定的要求
比如,将所有的图片放在一个文件夹中,跟上图片原来的名称,同时也要防止重复

Vue 知识点汇总(下)--附案例代码及项目地址_第19张图片

所以,我们可以在options中添加上如下选项:
img:文件要打包到的文件夹
name:获取图片原来的名字,放在该位置
hash:8:为了防止图片名称冲突,依然使用hash,但是我们只保留8位
ext:使用图片原来的扩展名

但是,我们发现图片并没有显示出来,这是因为图片使用的路径不正确
默认情况下,webpack会将生成的路径直接返回给使用者
但是,我们整个程序是打包在dist文件夹下的,所以这里我们需要在路径下再添加一个dist/

Vue 知识点汇总(下)--附案例代码及项目地址_第20张图片

ES6语法处理

如果你仔细阅读webpack打包的js文件,发现写的ES6语法并没有转成ES5,那么就意味着可能一些对ES6还不支持的浏览器没有办法很好的运行我们的代码。
在前面我们说过,如果希望将ES6的语法转成ES5,那么就需要使用babel。
而在webpack中,我们直接使用babel对应的loader就可以了。

npm install --save-dev babel-loader@7 babel-core babel-preset-es2015

配置webpack.config.js文件

Vue 知识点汇总(下)--附案例代码及项目地址_第21张图片

重新打包,查看bundle.js文件,发现其中的内容变成了ES5的语法

Webpack 配置 Vue

引入vue.js

后续项目中,我们会使用Vuejs进行开发,而且会以特殊的文件来组织vue的组件。
所以,下面我们来学习一下如何在我们的webpack环境中集成Vuejs
现在,我们希望在项目中使用Vuejs,那么必然需要对其有依赖,所以需要先进行安装
注:因为我们后续是在实际项目中也会使用vue的,所以并不是开发时依赖
在这里插入图片描述

那么,接下来就可以按照我们之前学习的方式来使用Vue了

Vue 知识点汇总(下)--附案例代码及项目地址_第22张图片

打包项目 – 错误信息

修改完成后,重新打包,运行程序:
打包过程没有任何错误(因为只是多打包了一个vue的js文件而已)
但是运行程序,没有出现想要的效果,而且浏览器中有报错

Vue 知识点汇总(下)--附案例代码及项目地址_第23张图片

这个错误说的是我们使用的是runtime-only版本的Vue,什么意思呢?
这里我只说解决方案:Vue不同版本构建,后续我具体讲解runtime-only和runtime-compiler的区别。
所以我们修改webpack的配置,添加如下内容即可

Vue 知识点汇总(下)--附案例代码及项目地址_第24张图片

el和template区别

正常运行之后,我们来考虑另外一个问题:
如果我们希望将data中的数据显示在界面中,就必须是修改index.html
如果我们后面自定义了组件,也必须修改index.html来使用组件
但是html模板在之后的开发中,我并不希望手动的来频繁修改,是否可以做到呢?

定义template属性:
在前面的Vue实例中,我们定义了el属性,用于和index.html中的#app进行绑定,让Vue实例之后可以管理它其中的内容
这里,我们可以将div元素中的{{message}}内容删掉,只保留一个基本的id为div的元素
但是如果我依然希望在其中显示{{message}}的内容,应该怎么处理呢?
我们可以再定义一个template属性,代码如下:

Vue 知识点汇总(下)--附案例代码及项目地址_第25张图片

重新打包,运行程序,显示一样的结果和HTML代码结构

那么,el和template模板的关系是什么呢?
在我们之前的学习中,我们知道el用于指定Vue要管理的DOM,可以帮助解析其中的指令、事件监听等等。
而如果Vue实例中同时指定了template,那么template模板的内容会替换掉挂载的对应el的模板。

这样做有什么好处呢?
这样做之后我们就不需要在以后的开发中再次操作index.html,只需要在template中写入对应的标签即可
但是,书写template模块非常麻烦怎么办呢?
没有关系,稍后我们会将template模板中的内容进行抽离。
会分成三部分书写:template、script、style,结构变得非常清晰。

Vue组件化开发引入

在学习组件化开发的时候,我说过以后的Vue开发过程中,我们都会采用组件化开发的思想。
那么,在当前项目中,如果我也想采用组件化的形式进行开发,应该怎么做呢?
查看下面的代码:
当然,我们也可以将下面的代码抽取到一个js文件中,并且导出。

Vue 知识点汇总(下)--附案例代码及项目地址_第26张图片

.vue文件封装处理

但是一个组件以一个js对象的形式进行组织和使用的时候是非常不方便的
一方面编写template模块非常的麻烦
另外一方面如果有样式的话,我们写在哪里比较合适呢?

现在,我们以一种全新的方式来组织一个vue的组件

但是,这个时候这个文件可以被正确的加载吗?
必然不可以,这种特殊的文件以及特殊的格式,必须有人帮助我们处理。
谁来处理呢?vue-loader以及vue-template-compiler。
安装vue-loader和vue-template-compiler

npm install vue-loader vue-template-compiler --save-dev

修改webpack.config.js的配置文件:

Vue 知识点汇总(下)--附案例代码及项目地址_第27张图片

plugin的使用

plugin是什么?
plugin是插件的意思,通常是用于对某个现有的架构进行扩展。
webpack中的插件,就是对webpack现有功能的各种扩展,比如打包优化,文件压缩等等。

loader和plugin区别
loader主要用于转换某些类型的模块,它是一个转换器。
plugin是插件,它是对webpack本身的扩展,是一个扩展器。

plugin的使用过程:
步骤一:通过npm安装需要使用的plugins(某些webpack已经内置的插件不需要安装)
步骤二:在webpack.config.js中的plugins中配置插件。
下面,我们就来看看可以通过哪些插件对现有的webpack打包过程进行扩容,让我们的webpack变得更加好用。

添加版权的Plugin

我们先来使用一个最简单的插件,为打包的文件添加版权声明
该插件名字叫BannerPlugin,属于webpack自带的插件。
按照下面的方式来修改webpack.config.js的文件:

Vue 知识点汇总(下)--附案例代码及项目地址_第28张图片

重新打包程序:查看bundle.js文件的头部,看到如下信息

在这里插入图片描述

打包html的plugin

目前,我们的index.html文件是存放在项目的根目录下的。
我们知道,在真实发布项目时,发布的是dist文件夹中的内容,但是dist文件夹中如果没有index.html文件,那么打包的js等文件也就没有意义了。
所以,我们需要将index.html文件打包到dist文件夹中,这个时候就可以使用

HtmlWebpackPlugin插件
HtmlWebpackPlugin插件可以为我们做这些事情:
自动生成一个index.html文件(可以指定模板来生成)
将打包的js文件,自动通过script标签插入到body中

安装HtmlWebpackPlugin插件

npm install html-webpack-plugin --save-dev

使用插件,修改webpack.config.js文件中plugins部分的内容如下:
这里的template表示根据什么模板来生成index.html
另外,我们需要删除之前在output中添加的publicPath属性
否则插入的script标签中的src可能会有问题

Vue 知识点汇总(下)--附案例代码及项目地址_第29张图片

js压缩的Plugin

在项目发布之前,我们必然需要对js等文件进行压缩处理
这里,我们就对打包的js文件进行压缩
我们使用一个第三方的插件uglifyjs-webpack-plugin,并且版本号指定1.1.1,和CLI2保持一致

npm install [email protected] --save-dev

修改webpack.config.js文件,使用插件:

Vue 知识点汇总(下)--附案例代码及项目地址_第30张图片

查看打包后的bunlde.js文件,是已经被压缩过了。

搭建本地服务器

webpack提供了一个可选的本地开发服务器,这个本地服务器基于node.js搭建,内部使用express框架,可以实现我们想要的让浏览器自动刷新显示我们修改后的结果。
不过它是一个单独的模块,在webpack中使用之前需要先安装它

npm install --save-dev [email protected]

devserver也是作为webpack中的一个选项,选项本身可以设置如下属性:
contentBase:为哪一个文件夹提供本地服务,默认是根文件夹,我们这里要填写./dist
port:端口号
inline:页面实时刷新
historyApiFallback:在SPA页面中,依赖HTML5的history模式
webpack.config.js文件配置修改如下:
我们可以再配置另外一个scripts:
–open参数表示直接打开浏览器

Vue 知识点汇总(下)--附案例代码及项目地址_第31张图片

2、Vue CLI

什么是Vue CLI

如果你只是简单写几个Vue的Demo程序, 那么你不需要Vue CLI.

如果你在开发大型项目, 那么你需要, 并且必然需要使用Vue CLI
使用Vue.js开发大型应用时,我们需要考虑代码目录结构、项目结构和部署、热加载、代码单元测试等事情。
如果每个项目都要手动完成这些工作,那无以效率比较低效,所以通常我们会使用一些脚手架工具来帮助完成这些事情。

CLI是什么意思?
CLI是Command-Line Interface, 翻译为命令行界面, 但是俗称脚手架.
Vue CLI是一个官方发布 vue.js 项目脚手架
使用 vue-cli 可以快速搭建Vue开发环境以及对应的webpack配置.

Vue CLI使用前提 - Node

安装NodeJS
可以直接在官方网站中下载安装.
网址: http://nodejs.cn/download/
检测安装的版本
默认情况下自动安装Node和NPM
Node环境要求8.9以上或者更高版本

在这里插入图片描述

什么是NPM呢?
NPM的全称是Node Package Manager
是一个NodeJS包管理和分发工具,已经成为了非官方的发布Node模块(包)的标准。
后续我们会经常使用NPM来安装一些开发过程中依赖包.

cnpm安装
由于国内直接使用 npm 的官方镜像是非常慢的,这里推荐使用淘宝 NPM 镜像。
你可以使用淘宝定制的 cnpm (gzip 压缩支持) 命令行工具代替默认的 npm:
npm install -g cnpm --registry=https://registry.npm.taobao.org
这样就可以使用 cnpm 命令来安装模块了:
cnpm install [name]

Vue CLI使用前提 - Webpack

Vue.js官方脚手架工具就使用了webpack模板
对所有的资源会压缩等优化操作
它在开发过程中提供了一套完整的功能,能够使得我们开发过程中变得高效。
Webpack的全局安装
npm install webpack -g

Vue 知识点汇总(下)--附案例代码及项目地址_第32张图片

Vue CLI的使用

安装Vue脚手架
npm install -g @vue/cli

在这里插入图片描述
注意:上面安装的是Vue CLI3的版本,如果需要想按照Vue CLI2的方式初始化项目时不可以的。

Vue 知识点汇总(下)--附案例代码及项目地址_第33张图片

Vue CLI2初始化项目
vue init webpack my-project

Vue CLI3初始化项目
vue create my-project

Vue CLI2详解

Vue 知识点汇总(下)--附案例代码及项目地址_第34张图片

目录结构详解

Vue 知识点汇总(下)--附案例代码及项目地址_第35张图片

Runtime-Compiler和Runtime-only的区别

在这里插入图片描述

Vue 知识点汇总(下)--附案例代码及项目地址_第36张图片

简单总结
如果在之后的开发中,你依然使用template,就需要选择Runtime-Compiler
如果你之后的开发中,使用的是.vue文件夹开发,那么可以选择Runtime-only

render和template

Runtime-Compiler 和 Runtime-only

Vue 知识点汇总(下)--附案例代码及项目地址_第37张图片

为什么存在这样的差异呢?
我们需要先理解Vue应用程序是如何运行起来的。
Vue中的模板如何最终渲染成真实DOM。
我们来看下面的一幅图。

Vue程序运行过程

Vue 知识点汇总(下)--附案例代码及项目地址_第38张图片

render函数的使用

Vue 知识点汇总(下)--附案例代码及项目地址_第39张图片

npm run build

Vue 知识点汇总(下)--附案例代码及项目地址_第40张图片

npm run dev

Vue 知识点汇总(下)--附案例代码及项目地址_第41张图片

修改配置:webpack.base.conf.js起别名

Vue 知识点汇总(下)--附案例代码及项目地址_第42张图片

Vue CLI3

Vue 知识点汇总(下)--附案例代码及项目地址_第43张图片

vue-cli 3 与 2 版本有很大区别
vue-cli 3 是基于 webpack 4 打造,vue-cli 2 还是 webapck 3
vue-cli 3 的设计原则是“0配置”,移除的配置文件根目录下的,build和config等目录
vue-cli 3 提供了 vue ui 命令,提供了可视化配置,更加人性化
移除了static文件夹,新增了public文件夹,并且index.html移动到public中

Vue 知识点汇总(下)--附案例代码及项目地址_第44张图片

目录结构详解

Vue 知识点汇总(下)--附案例代码及项目地址_第45张图片

配置去哪里了?

Vue 知识点汇总(下)--附案例代码及项目地址_第46张图片

自定义配置:起别名

Vue 知识点汇总(下)--附案例代码及项目地址_第47张图片

3、vue-router详解

认识路由

说起路由你想起了什么?
路由是一个网络工程里面的术语。
路由(routing)就是通过互联的网络把信息从源地址传输到目的地址的活动. — 维基百科

在生活中, 我们有没有听说过路由的概念呢? 当然了, 路由器嘛.
路由器是做什么的? 你有想过吗?

路由器提供了两种机制: 路由和转送.

  • 路由是决定数据包从来源到目的地的路径.
  • 转送将输入端的数据转移到合适的输出端.

路由中有一个非常重要的概念叫路由表.

路由表本质上就是一个映射表, 决定了数据包的指向.

后端路由阶段

早期的网站开发整个HTML页面是由服务器来渲染的.
服务器直接生产渲染好对应的HTML页面, 返回给客户端进行展示.

但是, 一个网站, 这么多页面服务器如何处理呢?

  • 一个页面有自己对应的网址, 也就是URL.
  • URL会发送到服务器, 服务器会通过正则对该URL进行匹配, 并且最后交给一个Controller进行处理.
  • Controller进行各种处理, 最终生成HTML或者数据, 返回给前端.
  • 这就完成了一个IO操作.

上面的这种操作, 就是后端路由.

当我们页面中需要请求不同的路径内容时, 交给服务器来进行处理, 服务器渲染好整个页面, 并且将页面返回给客户顿.
这种情况下渲染好的页面, 不需要单独加载任何的js和css, 可以直接交给浏览器展示, 这样也有利于SEO的优化.

后端路由的缺点:
一种情况是整个页面的模块由后端人员来编写和维护的.
另一种情况是前端开发人员如果要开发页面, 需要通过PHP和Java等语言来编写页面代码.
而且通常情况下HTML代码和数据以及对应的逻辑会混在一起, 编写和维护都是非常糟糕的事情.

Vue 知识点汇总(下)--附案例代码及项目地址_第48张图片

前端路由阶段

前后端分离阶段:

  • 随着Ajax的出现, 有了前后端分离的开发模式.
  • 后端只提供API来返回数据, 前端通过Ajax获取数据, 并且可以通过JavaScript将数据渲染到页面中.
  • 这样做最大的优点就是前后端责任的清晰, 后端专注于数据上, 前端专注于交互和可视化上.
  • 并且当移动端(iOS/Android)出现后, 后端不需要进行任何处理, 依然使用之前的一套API即可.
  • 目前很多的网站依然采用这种模式开发.

单页面富应用阶段:
其实SPA最主要的特点就是在前后端分离的基础上加了一层前端路由.
也就是前端来维护一套路由规则.

前端路由的核心是什么呢?
改变URL,但是页面不进行整体的刷新。
如何实现呢?

Vue 知识点汇总(下)--附案例代码及项目地址_第49张图片

URL的hash
URL的hash也就是锚点(#), 本质上是改变window.location的href属性.
我们可以通过直接赋值location.hash来改变href, 但是页面不发生刷新

Vue 知识点汇总(下)--附案例代码及项目地址_第50张图片

HTML5的history模式:pushState

history接口是HTML5新增的, 它有五种模式改变URL而不刷新页面.
history.pushState()

Vue 知识点汇总(下)--附案例代码及项目地址_第51张图片

HTML5的history模式:replaceState

history.replaceState()

Vue 知识点汇总(下)--附案例代码及项目地址_第52张图片

HTML5的history模式:go

history.go()

Vue 知识点汇总(下)--附案例代码及项目地址_第53张图片

补充说明:
上面只演示了三个方法

  • 因为 history.back() 等价于 history.go(-1)
  • history.forward() 则等价于 history.go(1)
  • 这三个接口等同于浏览器界面的前进后退。

Vue 知识点汇总(下)--附案例代码及项目地址_第54张图片

看到这里,你可以自问自答一下,下面这个几个问题。

(1)什么是前端渲染, 什么是后端渲染?

(2)什么是前后端分离?

(3)什么是前端路由, 什么是后端路由?

(1)什么是前端渲染, 什么是后端渲染?

前端渲染:

指的是后端返回JSON数据,前端利用预先写的html模板,循环读取JSON数据,拼接字符串(es6的模板字符串特性大大减少了拼接字符串的的成本),并插入页面。

好处:网络传输数据量小。不占用服务端运算资源(解析模板),模板在前端(很有可能仅部分在前端),改结构变交互都前端自己来了,改完自己调就行。

坏处:前端耗时较多,对前端工作人员水平要求相对较高。前端代码较多,因为部分以前在后台处理的交互逻辑交给了前端处理。占用少部分客户端运算资源用于解析模板。

后端渲染:

前端请求,后端用后台模板引擎直接生成html,前端接受到数据之后,直接插入页面。

好处:前端耗时少,即减少了首屏时间,模板统一在后端。前端(相对)省事,不占用客户端运算资源(解析模板)

坏处:占用服务器资源。

前端渲染与后端渲染对比:

后端渲染:

页面呈现速度:快,受限于用户的带宽
流量消耗:少一点点(可以省去前端框架部分的代码)
可维护性:差(前后端东西放一起,掐架多年,早就在闹分手啦)
seo友好度:好
编码效率:低(这个跟不同的团队不同,可能不对)

前端渲染:

页面呈现速度:主要受限于带宽和客户端机器的好坏,优化的好,可以逐步动态展开内容,感觉上会更快一点。

流量消耗:多一点点(一个前端框架大概50KB)当然,有的用后端渲染的项目前端部分也有在用框架。

可维护性:好,前后端分离,各施其职,代码一目明了。
SEO友好度:差,大量使用ajax,多数浏览器不能抓取ajax数据。
编码效率:高,前后端各自只做自己擅长的东西,后端最后只输出接口,不用管页面呈现,只要前后端人员能力不错,效率不会低。

(2)什么是前后端分离?

Vue 知识点汇总(下)--附案例代码及项目地址_第55张图片

现在 Web 服务器不再处理任何业务,它接收到请求后,经过转换,发送给各个相关后端服务器,将各个后端服务器返回的,处理过的业务数据填入 HTML 模板,最后发送给浏览器。Web 服务器和后端服务器间,可以选用任何你觉得合适的通信手段,可以是 REST,可以是 RPC,选用什么样的通信手段,这是另一个议题了。

这样,前端人员和后端人员约定好接口后,前端人员彻底不用再关心业务处理是怎么回事,他只需要把界面做好就可以了,后端人员也不用再关系前端界面是什么样的,他只需要做好业务逻辑处理即可。服务的切离,代码管理,服务部署也都独立出来分别管理,系统的灵活性也获得了极大的提升。

注意,这不是个微服务架构,那是另外一个议题了

总结,任何系统架构设计,实际上是对组织结构在系统上进行映射,前后端分离,就是在对前端开发人员和后端开发人员的工作进行解耦,尽量减少他她们之间的交流成本,帮助他她们更能专注于自己擅长的工作。

最后是几个常见误解的说明:

1、前后端分离是说浏览器和后端服务分离吗?

不是,前后端分离里的前端不是浏览器,指的是生成 HTML 的那个服务,它可以是一个仅仅生成 HTML 的 Web 服务器,也可以是在浏览器中通过 JS 动态生成 HTML 的 单页应用。实践中,有实力的团队往往在实现前后端分离里时,前端选用 node 服务器,后端选用 C#、Java 等(排名不分先后)

2、前后端分离是种技术吗?

不是,前后端分离是种架构模式,或者说是最佳实践。所谓模式就是大家这么用了觉得不错,你可以直接抄来用的固定套路。

3、前后端分离是最佳实践吗?

看你团队和项目的情况,如果是短平快的小项目,真的没必要。如果是面向简历开发,那绝对在任何时候都应该使用前后端分离这种架构。

(3)什么是前端路由, 什么是后端路由?

1、什么是前端路由?

很重要的一点是页面不刷新,前端路由就是把不同路由对应不同的内容或页面的任务交给前端来做,每跳转到不同的URL都是使用前端的锚点路由. 随着(SPA)单页应用的不断普及,前后端开发分离,目前项目基本都使用前端路由,在项目使用期间页面不会重新加载。

2、什么是后端路由?

​ 浏览器在地址栏中切换不同的url时,每次都向后台服务器发出请求,服务器响应请求,在后台拼接html文件传给前端显示, 返回不同的页面, 意味着浏览器会刷新页面,网速慢的话说不定屏幕全白再有新内容。后端路由的另外一个极大的问题就是 前后端不分离。

​ 优点:分担了前端的压力,html和数据的拼接都是由服务器完成。

​ 缺点:当项目十分庞大时,加大了服务器端的压力,同时在浏览器端不能输入制定的url路径进行指定模块的访问。另外一个就是如果当前网速过慢,那将会延迟页面的加载,对用户体验不是很友好。

3,什么时候使用前端路由?

​ 在单页面应用,大部分页面结构不变,只改变部分内容的使用

4,前端路由有什么优点和缺点?

优点:

​ 1.用户体验好,和后台网速没有关系,不需要每次都从服务器全部获取,快速展现给用户

​ 2.可以再浏览器中输入指定想要访问的url路径地址。

​ 3.实现了前后端的分离,方便开发。有很多框架都带有路由功能模块。

缺点:

​ 1.使用浏览器的前进,后退键的时候会重新发送请求,没有合理地利用缓存

​ 2.单页面无法记住之前滚动的位置,无法在前进,后退的时候记住滚动的位置

认识vue-router

目前前端流行的三大框架, 都有自己的路由实现:
Angular的ngRouter
React的ReactRouter
Vue的vue-router

当然, 我们的重点是vue-router
vue-router是Vue.js官方的路由插件,它和vue.js是深度集成的,适合用于构建单页面应用。
我们可以访问其官方网站对其进行学习: https://router.vuejs.org/zh/
vue-router是基于路由和组件的
路由用于设定访问路径, 将路径和组件映射起来.
在vue-router的单页面应用中, 页面的路径的改变就是组件的切换.

安装和使用vue-router

因为我们已经学习了webpack, 后续开发中我们主要是通过工程化的方式进行开发的.
所以在后续, 我们直接使用npm来安装路由即可.
步骤一: 安装vue-router
npm install vue-router --save
步骤二: 在模块化工程中使用它(因为是一个插件, 所以可以通过Vue.use()来安装路由功能)
第一步:导入路由对象,并且调用 Vue.use(VueRouter)
第二步:创建路由实例,并且传入路由映射配置
第三步:在Vue实例中挂载创建的路由实例

使用vue-router的步骤:
第一步: 创建路由组件
第二步: 配置路由映射: 组件和路径映射关系
第三步: 使用路由: 通过

import Vue from ‘vue’
import VueRouter from ‘vue-router’

Vue.use(VueRouter)

创建router实例

Vue 知识点汇总(下)--附案例代码及项目地址_第56张图片

挂载到Vue实例中

Vue 知识点汇总(下)--附案例代码及项目地址_第57张图片

步骤一:创建路由组件

Vue 知识点汇总(下)--附案例代码及项目地址_第58张图片

步骤二:配置组件和路径的映射关系

Vue 知识点汇总(下)--附案例代码及项目地址_第59张图片

步骤三:使用路由.

Vue 知识点汇总(下)--附案例代码及项目地址_第60张图片

: 该标签是一个vue-router中已经内置的组件, 它会被渲染成一个标签.
: 该标签会根据当前的路径, 动态渲染出不同的组件.
网页的其他内容, 比如顶部的标题/导航, 或者底部的一些版权信息等会和处于同一个等级.
在路由切换时, 切换的是挂载的组件, 其他内容不会发生改变.

最终效果如下

Vue 知识点汇总(下)--附案例代码及项目地址_第61张图片

细节处理

路由的默认路径

我们这里还有一个不太好的实现:
默认情况下, 进入网站的首页, 我们希望渲染首页的内容.
但是我们的实现中, 默认没有显示首页组件, 必须让用户点击才可以.
如何可以让路径默认跳到到首页, 并且渲染首页组件呢?
非常简单, 我们只需要配置多配置一个映射就可以了.
Vue 知识点汇总(下)--附案例代码及项目地址_第62张图片
配置解析:
我们在routes中又配置了一个映射.
path配置的是根路径: /
redirect是重定向, 也就是我们将根路径重定向到/home的路径下, 这样就可以得到我们想要的结果了.

HTML5的History模式

我们前面说过改变路径的方式有两种:
URL的hash
HTML5的history
默认情况下, 路径的改变使用的URL的hash.
如果希望使用HTML5的history模式, 非常简单, 进行如下配置即可:

Vue 知识点汇总(下)--附案例代码及项目地址_第63张图片

在这里插入图片描述

router-link补充

在前面的中, 我们只是使用了一个属性: to, 用于指定跳转的路径.

还有一些其他属性:
tag: tag可以指定之后渲染成什么组件, 比如上面的代码会被渲染成一个

  • 元素, 而不是

    replace: replace不会留下history记录, 所以指定replace的情况下, 后退键返回不能返回到上一个页面中
    active-class:对应的路由匹配成功时, 会自动给当前元素设置一个router-link-active的class, 设置active-class可以修改默认的名称.

    • 在进行高亮显示的导航菜单或者底部tabbar时, 会使用到该类.
    • 但是通常不会修改类的属性, 会直接使用默认的router-link-active即可.

    在这里插入图片描述

    修改linkActiveClass

    该class具体的名称也可以通过router实例的属性进行修改

    Vue 知识点汇总(下)--附案例代码及项目地址_第64张图片

    exact-active-class
    类似于active-class, 只是在精准匹配下才会出现的class.
    后面看到嵌套路由时, 我们再看下这个属性.

    一.在点击导航栏的时候,让被点击的那一个有背景色,其他的没有背景色?

    const router = new VueRouter({
        routes,
        linkActiveClass: 'is-active'
    });
    .is-active{
      background:red;
    }
    

    这样被点击激活的时候就会被加上is-active这个class了。注意如果没有设置router-link的标签类型,会是标签,标签是没有宽度和高度的。将这样的a标签转化为li标签

    <router-link to='index' tag="li" event="mouseover">
    

    二.自己来操控 active Class 给加的位置,并不想它随着路由的改变而改变
    假如侧边栏我的钱包,路由为’/myWallet’,在’/myWallet’页面可以操作提现,会进入’/withdraw’提现页面,路由发生变化,从’/myWallet’ 身上移到’/withdraw’上了。如何让 ‘/myWallet’ 这个页面的active Class 保留住呢?给’/withdraw’ 加上一个路由元信息,在侧边栏去检查路由元信息,然后看是否需要给其active class

    {
      path: '/myWallet',
      name: 'MyWallet',
      component: MyWallet,
      meta: { 
        requiresAuth: true,
        active: '/MyWallet'
      }
    },
    {
      path: '/withdraw',
      name: 'Withdraw',
      component: withdraw,
      meta: { 
        requiresAuth: true ,
        active: '/MyWallet'
      }
    },
    <router-link tag="li" class="li-item" to="/MyWallet" :class="{'is-active':$route.meta.active === '/MyWallet'}">我的钱包</router-link>
    

    如果只有一个页面 对应一个active的,就不用添加 meta下面的active属性了

    
    

    路由代码跳转

    有时候, 页面的跳转可能需要执行对应的JavaScript代码, 这个时候, 就可以使用第二种跳转方式了
    比如, 我们将代码修改如下:

    Vue 知识点汇总(下)--附案例代码及项目地址_第65张图片

    动态路由

    在某些情况下,一个页面的path路径可能是不确定的,比如我们进入用户界面时,希望是如下的路径:
    /user/aaaa或/user/bbbb
    除了有前面的/user之外,后面还跟上了用户的ID
    这种path和Component的匹配关系,我们称之为动态路由(也是路由传递数据的一种方式)。

    Vue 知识点汇总(下)--附案例代码及项目地址_第66张图片

    路由的懒加载

    认识路由的懒加载

    官方给出了解释:
    当打包构建应用时,Javascript 包会变得非常大,影响页面加载。
    如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了

    官方在说什么呢?
    首先, 我们知道路由中通常会定义很多不同的页面.
    这个页面最后被打包在哪里呢? 一般情况下, 是放在一个js文件中.
    但是, 页面这么多放在一个js文件中, 必然会造成这个页面非常的大.
    如果我们一次性从服务器请求下来这个页面, 可能需要花费一定的时间, 甚至用户的电脑上还出现了短暂空白的情况.
    如何避免这种情况呢? 使用路由懒加载就可以了.

    路由懒加载做了什么?
    路由懒加载的主要作用就是将路由对应的组件打包成一个个的js代码块.
    只有在这个路由被访问到的时候, 才加载对应的组件

    路由懒加载的效果

    Vue 知识点汇总(下)--附案例代码及项目地址_第67张图片

    懒加载的方式

    方式一: 结合Vue的异步组件和Webpack的代码分析.

    const Home = resolve => { require.ensure(['../components/Home.vue'], () => { resolve(require('../components/Home.vue')) })};
    

    方式二: AMD写法

    const About = resolve => require(['../components/About.vue'], resolve);
    

    方式三: 在ES6中, 我们可以有更加简单的写法来组织Vue异步组件和Webpack的代码分割.

    const Home = () => import('../components/Home.vue')
    

    路由嵌套

    嵌套路由是一个很常见的功能
    比如在home页面中, 我们希望通过/home/news和/home/message访问一些内容.
    一个路径映射一个组件, 访问这两个路径也会分别渲染两个组件.
    路径和组件的关系如下:

    Vue 知识点汇总(下)--附案例代码及项目地址_第68张图片
    实现嵌套路由有两个步骤:

    1. 创建对应的子组件, 并且在路由映射中配置对应的子路由.
    2. 在组件内部使用< router-view>标签.

    嵌套路由实现

    Vue 知识点汇总(下)--附案例代码及项目地址_第69张图片

    嵌套默认路径

    嵌套路由也可以配置默认的路径, 配置方式如下:

    Vue 知识点汇总(下)--附案例代码及项目地址_第70张图片

    传递参数

    准备工作

    为了演示传递参数, 我们这里再创建一个组件, 并且将其配置好
    第一步: 创建新的组件Profile.vue
    第二步: 配置路由映射
    第三步: 添加跳转的< router-link>

    Vue 知识点汇总(下)--附案例代码及项目地址_第71张图片

    Vue 知识点汇总(下)--附案例代码及项目地址_第72张图片

    传递参数的方式

    传递参数主要有两种类型: params和query
    params的类型:

    • 配置路由格式: /router/:id
    • 传递的方式: 在path后面跟上对应的值
    • 传递后形成的路径: /router/123, /router/abc

    query的类型:

    • 配置路由格式: /router, 也就是普通配置
    • 传递的方式: 对象中使用query的key作为传递方式
    • 传递后形成的路径: /router?id=123, /router?id=abc

    如何使用它们呢? 也有两种方式: 的方式和JavaScript代码方式

    传递参数方式一:

    Vue 知识点汇总(下)--附案例代码及项目地址_第73张图片

    传递参数方式二: JavaScript代码

    Vue 知识点汇总(下)--附案例代码及项目地址_第74张图片

    获取参数

    获取参数通过 r o u t e 对 象 获 取 的 . 在 使 用 了 v u e − r o u t e r 的 应 用 中 , 路 由 对 象 会 被 注 入 每 个 组 件 中 , 赋 值 为 t h i s . route对象获取的. 在使用了 vue-router 的应用中,路由对象会被注入每个组件中,赋值为 this. route.使vuerouterthis.route ,并且当路由切换时,路由对象会被更新。
    通过$route获取传递的信息如下:

    Vue 知识点汇总(下)--附案例代码及项目地址_第75张图片

    r o u t e 和 route和 routerouter是有区别的

    r o u t e 和 route和 routerouter是有区别的
    r o u t e r 为 V u e R o u t e r 实 例 , 想 要 导 航 到 不 同 U R L , 则 使 用 router为VueRouter实例,想要导航到不同URL,则使用 routerVueRouterURL使router.push方法
    $route为当前router跳转对象里面可以获取name、path、query、params等

    Vue 知识点汇总(下)--附案例代码及项目地址_第76张图片

    导航守卫

    为什么使用导航守卫?

    我们来考虑一个需求: 在一个SPA应用中, 如何改变网页的标题呢?
    网页标题是通过来显示的, 但是SPA只有一个固定的HTML, 切换不同的页面时, 标题并不会改变.
    但是我们可以通过JavaScript来修改的内容.window.document.title = ‘新的标题’.<br/> 那么在Vue项目中, 在哪里修改? 什么时候修改比较合适呢?</p> <p>普通的修改方式:<br> 我们比较容易想到的修改标题的位置是每一个路由对应的组件.vue文件中.<br> 通过mounted声明周期函数, 执行对应的代码进行修改即可.<br> 但是当页面比较多时, 这种方式不容易维护(因为需要在多个页面执行类似的代码).</p> <p>有没有更好的办法呢? 使用导航守卫即可.<br> 什么是导航守卫?<br> vue-router提供的导航守卫主要用来监听监听路由的进入和离开的.<br> vue-router提供了beforeEach和afterEach的钩子函数, 它们会在路由即将改变前和改变后触发.</p> <p><strong>导航守卫使用</strong></p> <p>我们可以利用beforeEach来完成标题的修改.<br> 首先, 我们可以在钩子当中定义一些标题, 可以利用meta来定义<br> 其次, 利用导航守卫,修改我们的标题.</p> <p><a href="http://img.e-com-net.com/image/info8/dd1141dbfd7543a7b8e6805f8fd3a158.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/dd1141dbfd7543a7b8e6805f8fd3a158.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第77张图片" width="650" height="209" style="border:1px solid black;"></a></p> <p>导航钩子的三个参数解析:<br> to: 即将要进入的目标的路由对象.<br> from: 当前导航即将要离开的路由对象.<br> next: 调用该方法后, 才能进入下一个钩子.</p> <p><strong>导航守卫补充</strong></p> <p>补充一:如果是后置钩子, 也就是afterEach, 不需要主动调用next()函数.<br> 补充二: 上面我们使用的导航守卫, 被称之为全局守卫.<br> 路由独享的守卫.<br> 组件内的守卫.</p> <p>更多内容, 可以查看官网进行学习:<br> <strong>导航守卫补充</strong></p> <h4>keep-alive遇见vue-router</h4> <p>keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。<br> 它们有两个非常重要的属性:<br> include - 字符串或正则表达,只有匹配的组件会被缓存<br> exclude - 字符串或正则表达式,任何匹配的组件都不会被缓存<br> router-view 也是一个组件,如果直接被包在 keep-alive 里面,所有路径匹配到的视图组件都会被缓存:</p> <p><a href="http://img.e-com-net.com/image/info8/865674a08f654f46ad80d9be335b1ab6.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/865674a08f654f46ad80d9be335b1ab6.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第78张图片" width="650" height="114" style="border:1px solid black;"></a></p> <p>通过create声明周期函数来验证</p> <h4>案例:TabBar</h4> <ol> <li> <p>如果在下方有一个单独的TabBar组件,你如何封装<br> 自定义TabBar组件,在APP中使用<br> 让TabBar出于底部,并且设置相关的样式</p> </li> <li> <p>TabBar中显示的内容由外界决定<br> 定义插槽<br> flex布局平分TabBar</p> </li> <li> <p>自定义TabBarItem,可以传入 图片和文字<br> 定义TabBarItem,并且定义两个插槽:图片、文字。<br> 给两个插槽外层包装div,用于设置样式。<br> 填充插槽,实现底部TabBar的效果</p> </li> <li> <p>传入 高亮图片<br> 定义另外一个插槽,插入active-icon的数据<br> 定义一个变量isActive,通过v-show来决定是否显示对应的icon</p> </li> <li> <p>TabBarItem绑定路由数据<br> 安装路由:npm install vue-router —save<br> 完成router/index.js的内容,以及创建对应的组件<br> main.js中注册router<br> APP中加入<code><router-view></code>组件</p> </li> <li> <p>点击item跳转到对应路由,并且动态决定isActive<br> 监听item的点击,通过<code>this.$router.replace()</code>替换路由路径<br> 通过<code>this.$route.path.indexOf(this.link) !== -1</code>来判断是否是active</p> </li> <li> <p>动态计算active样式<br> 封装新的计算属性:this.isActive ? {‘color’: ‘red’} : {}</p> </li> </ol> <p><a href="http://img.e-com-net.com/image/info8/4573c2814bca4d0581d2a62f7f5c6bd2.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/4573c2814bca4d0581d2a62f7f5c6bd2.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第79张图片" width="347" height="611" style="border:1px solid black;"></a></p> <h3>4、Promise</h3> <h4>什么是Promise呢?</h4> <p>ES6中一个非常重要和好用的特性就是Promise<br> 但是初次接触Promise会一脸懵逼,这TM是什么东西?<br> 看看官方或者一些文章对它的介绍和用法,也是一头雾水。</p> <p>Promise到底是做什么的呢?<br> Promise是异步编程的一种解决方案。</p> <p>那什么时候我们会来处理异步事件呢?<br> 一种很常见的场景应该就是网络请求了。<br> 我们封装一个网络请求的函数,因为不能立即拿到结果,所以不能像简单的3+4=7一样将结果返回。<br> 所以往往我们会传入另外一个函数,在数据请求成功时,将数据通过传入的函数回调出去。<br> 如果只是一个简单的网络请求,那么这种方案不会给我们带来很大的麻烦。</p> <p>但是,当网络请求非常复杂时,就会出现回调地狱。<br> OK,我以一个非常夸张的案例来说明。</p> <p><strong>网络请求的回调地狱</strong></p> <p>我们来考虑下面的场景(有夸张的成分):<br> 我们需要通过一个url1从服务器加载一个数据data1,data1中包含了下一个请求的url2<br> 我们需要通过data1取出url2,从服务器加载数据data2,data2中包含了下一个请求的url3<br> 我们需要通过data2取出url3,从服务器加载数据data3,data3中包含了下一个请求的url4<br> 发送网络请求url4,获取最终的数据data4</p> <p><a href="http://img.e-com-net.com/image/info8/14d94c75481a4a78b67b07f33fa487a7.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/14d94c75481a4a78b67b07f33fa487a7.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第80张图片" width="423" height="174" style="border:1px solid black;"></a></p> <p>上面的代码有什么问题吗?<br> 正常情况下,不会有什么问题,可以正常运行并且获取我们想要的结果。<br> 但是,这样额代码难看而且不容易维护。<br> 我们更加期望的是一种更加优雅的方式来进行这种异步操作。<br> 如何做呢?就是使用Promise。<br> Promise可以以一种非常优雅的方式来解决这个问题。</p> <h4>Promise的基本使用</h4> <p><strong>定时器的异步事件</strong></p> <p>我们先来看看Promise最基本的语法。<br> 这里,我们用一个定时器来模拟异步事件:<br> 假设下面的data是从网络上1秒后请求的数据<br> console.log就是我们的处理方式。<br> 这是我们过去的处理方式,我们将它换成Promise代码<br> 这个例子会让我们感觉脱裤放屁,多此一举<br> 首先,下面的Promise代码明显比上面的代码看起来还要复杂。<br> 其次,下面的Promise代码中包含的resolve、reject、then、catch都是些什么东西?<br> 我们先不管第一个复杂度的问题,因为这样的一个屁大点的程序根本看不出来Promise真正的作用。</p> <p><a href="http://img.e-com-net.com/image/info8/a0ac2c68b4d34b50a22ec747fe6688f0.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/a0ac2c68b4d34b50a22ec747fe6688f0.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第81张图片" width="545" height="495" style="border:1px solid black;"></a></p> <p><strong>定时器异步事件解析</strong></p> <p>我们先来认认真真的读一读这个程序到底做了什么?</p> <ul> <li>new Promise很明显是创建一个Promise对象</li> <li>小括号中((resolve, reject) => {})也很明显就是一个函数,而且我们这里用的是之前刚刚学习过的箭头函数。 <ul> <li>但是resolve, reject它们是什么呢?</li> <li>我们先知道一个事实:在创建Promise时,传入的这个箭头函数是固定的(一般我们都会这样写)</li> <li>resolve和reject它们两个也是函数,通常情况下,我们会根据请求数据的成功和失败来决定调用哪一个。</li> </ul> </li> <li>成功还是失败? <ul> <li>如果是成功的,那么通常我们会调用resolve(messsage),这个时候,我们后续的then会被回调。</li> <li>如果是失败的,那么通常我们会调用reject(error),这个时候,我们后续的catch会被回调。</li> </ul> </li> </ul> <p>OK,这就是Promise最基本的使用了。</p> <p><strong>Promise三种状态</strong></p> <p>首先, 当我们开发中有异步操作时, 就可以给异步操作包装一个Promise<br> 异步操作之后会有三种状态</p> <p>我们一起来看一下这三种状态:<br> pending:等待状态,比如正在进行网络请求,或者定时器没有到时间。<br> fulfill:满足状态,当我们主动回调了resolve时,就处于该状态,并且会回调.then()<br> reject:拒绝状态,当我们主动回调了reject时,就处于该状态,并且会回调.catch()</p> <p><a href="http://img.e-com-net.com/image/info8/5d2fa1d4dc6a4a468f02e189de0679e9.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/5d2fa1d4dc6a4a468f02e189de0679e9.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第82张图片" width="650" height="232" style="border:1px solid black;"></a></p> <p><a href="http://img.e-com-net.com/image/info8/ccb8d0a142f24811878ec2ac0b1429b6.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/ccb8d0a142f24811878ec2ac0b1429b6.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第83张图片" width="491" height="238" style="border:1px solid black;"></a></p> <h4>Promise的链式调用</h4> <p>我们在看Promise的流程图时,发现无论是then还是catch都可以返回一个Promise对象。<br> 所以,我们的代码其实是可以进行链式调用的:<br> 这里我们直接通过Promise包装了一下新的数据,将Promise对象返回了<br> Promise.resovle():将数据包装成Promise对象,并且在内部回调resolve()函数<br> Promise.reject():将数据包装成Promise对象,并且在内部回调reject()函数</p> <p><a href="http://img.e-com-net.com/image/info8/98a6250210e449b3a494117160bbd4e6.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/98a6250210e449b3a494117160bbd4e6.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第84张图片" width="570" height="548" style="border:1px solid black;"></a></p> <p><strong>链式调用简写</strong></p> <p>简化版代码:<br> 如果我们希望数据直接包装成Promise.resolve,那么在then中可以直接返回数据<br> 注意下面的代码中,我讲return Promise.resovle(data)改成了return data<br> 结果依然是一样的</p> <p><a href="http://img.e-com-net.com/image/info8/fc2eb2fdf39d475f82b034bb7cf3ab8e.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/fc2eb2fdf39d475f82b034bb7cf3ab8e.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第85张图片" width="567" height="557" style="border:1px solid black;"></a></p> <h3>5、Vuex详解</h3> <h4>认识Vuex</h4> <p><strong>Vuex是做什么的?</strong></p> <p>官方解释:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。</p> <ul> <li>它采用 集中式存储管理 应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。</li> <li>Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。</li> </ul> <p>状态管理到底是什么?<br> 状态管理模式、集中式存储管理这些名词听起来就非常高大上,让人捉摸不透。<br> 其实,你可以简单的将其看成把需要多个组件共享的变量全部存储在一个对象里面。<br> 然后,将这个对象放在顶层的Vue实例中,让其他组件可以使用。<br> 那么,多个组件是不是就可以共享这个对象中的所有变量属性了呢?<br> 等等,如果是这样的话,为什么官方还要专门出一个插件Vuex呢?难道我们不能自己封装一个对象来管理吗?</p> <p>当然可以,只是我们要先想想VueJS带给我们最大的便利是什么呢?没错,就是响应式。<br> 如果你自己封装实现一个对象能不能保证它里面所有的属性做到响应式呢?当然也可以,只是自己封装可能稍微麻烦一些。<br> 不用怀疑,Vuex就是为了提供这样一个在多个组件间共享状态的插件,用它就可以了。</p> <p><strong>管理什么状态呢?</strong></p> <p>但是,有什么状态时需要我们在多个组件间共享的呢?<br> 如果你做过大型开放,你一定遇到过多个状态,在多个界面间的共享问题。<br> 比如用户的登录状态、用户名称、头像、地理位置信息等等。<br> 比如商品的收藏、购物车中的物品等等。<br> 这些状态信息,我们都可以放在统一的地方,对它进行保存和管理,而且它们还是响应式的(待会儿我们就可以看到代码了,莫着急)。</p> <p>OK,从理论上理解了状态管理之后,让我们从实际的代码再来看看状态管理。<br> 毕竟,Talk is cheap, Show me the code.(来自Linus)</p> <p>我们先来看看但界面的状态管理吧.</p> <p><strong>单界面的状态管理</strong></p> <p>我们知道,要在单个组件中进行状态管理是一件非常简单的事情<br> 什么意思呢?我们来看下面的图片。<br> 这图片中的三种东西,怎么理解呢?<br> State:不用多说,就是我们的状态。(你姑且可以当做就是data中的属性)<br> View:视图层,可以针对State的变化,显示不同的信息。(这个好理解吧?)<br> Actions:这里的Actions主要是用户的各种操作:点击、输入等等,会导致状态的改变。</p> <p>写点代码,加深理解:<br> 看下右边的代码效果, 肯定会实现吧?</p> <p><a href="http://img.e-com-net.com/image/info8/7d2b5efa4dda4f28beb18404ee61ba31.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/7d2b5efa4dda4f28beb18404ee61ba31.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第86张图片" width="401" height="350" style="border:1px solid black;"></a></p> <p><strong>单界面状态管理的实现</strong></p> <p><a href="http://img.e-com-net.com/image/info8/3b59ed490a674cd0891a243d926bbe61.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/3b59ed490a674cd0891a243d926bbe61.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第87张图片" width="546" height="574" style="border:1px solid black;"></a></p> <p>在这个案例中,我们有木有状态需要管理呢?没错,就是个数counter。<br> counter需要某种方式被记录下来,也就是我们的State。<br> counter目前的值需要被显示在界面中,也就是我们的View部分。<br> 界面发生某些操作时(我们这里是用户的点击,也可以是用户的input),需要去更新状态,也就是我们的Actions<br> 这不就是上面的流程图了吗?</p> <p><strong>多界面状态管理</strong></p> <p>Vue已经帮我们做好了单个界面的状态管理,但是如果是多个界面呢?<br> 多个试图都依赖同一个状态(一个状态改了,多个界面需要进行更新)<br> 不同界面的Actions都想修改同一个状态(Home.vue需要修改,Profile.vue也需要修改这个状态)</p> <p>也就是说对于某些状态(状态1/状态2/状态3)来说只属于我们某一个试图,但是也有一些状态(状态a/状态b/状态c)属于多个试图共同想要维护的<br> 状态1/状态2/状态3你放在自己的房间中,你自己管理自己用,没问题。<br> 但是状态a/状态b/状态c我们希望交给一个大管家来统一帮助我们管理!!!<br> 没错,Vuex就是为我们提供这个大管家的工具。</p> <p>全局单例模式(大管家)<br> 我们现在要做的就是将共享的状态抽取出来,交给我们的大管家,统一进行管理。<br> 之后,你们每个试图,按照我规定好的规定,进行访问和修改等操作。<br> 这就是Vuex背后的基本思想。</p> <p><strong>Vuex状态管理图例</strong></p> <p><a href="http://img.e-com-net.com/image/info8/9e96cee78904486490d1742c4db32c61.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/9e96cee78904486490d1742c4db32c61.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第88张图片" width="596" height="450" style="border:1px solid black;"></a></p> <h4>Vuex的基本使用</h4> <p><strong>简单的案例</strong></p> <p>我们还是实现一下之前简单的案例</p> <p><a href="http://img.e-com-net.com/image/info8/9d2441cd3a954136b928c76d8b2aa5c2.png" target="_blank"><img src="http://img.e-com-net.com/image/info8/9d2441cd3a954136b928c76d8b2aa5c2.png" alt="在这里插入图片描述" width="172" height="83"></a></p> <p>首先,我们需要在某个地方存放我们的Vuex代码:<br> 这里,我们先创建一个文件夹store,并且在其中创建一个index.js文件<br> 在index.js文件中写入如下代码:</p> <p><a href="http://img.e-com-net.com/image/info8/a9f75eed96354fa09e94b44cfc782701.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/a9f75eed96354fa09e94b44cfc782701.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第89张图片" width="518" height="529" style="border:1px solid black;"></a></p> <p><strong>挂载到Vue实例中</strong></p> <p>其次,我们让所有的Vue组件都可以使用这个store对象<br> 来到main.js文件,导入store对象,并且放在new Vue中<br> 这样,在其他Vue组件中,我们就可以通过this.$store的方式,获取到这个store对象了</p> <p><a href="http://img.e-com-net.com/image/info8/fa862b88d5bb4f81a0c5a4c52e3bbeeb.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/fa862b88d5bb4f81a0c5a4c52e3bbeeb.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第90张图片" width="619" height="310" style="border:1px solid black;"></a></p> <p><strong>使用Vuex的count</strong></p> <p><a href="http://img.e-com-net.com/image/info8/ff2fefdcc5a84c7dbb232a4928ef4cf3.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/ff2fefdcc5a84c7dbb232a4928ef4cf3.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第91张图片" width="445" height="553" style="border:1px solid black;"></a></p> <p>好的,这就是使用Vuex最简单的方式了。<br> 我们来对使用步骤,做一个简单的小节:<br> 1.提取出一个公共的store对象,用于保存在多个组件中共享的状态<br> 2.将store对象放置在new Vue对象中,这样可以保证在所有的组件中都可以使用到<br> 3.在其他组件中使用store对象中保存的状态即可</p> <ul> <li>通过this.$store.state.属性的方式来访问状态</li> <li>通过this.$store.commit(‘mutation中方法’)来修改状态</li> </ul> <p>注意事项:<br> 我们通过提交mutation的方式,而非直接改变store.state.count。<br> 这是因为Vuex可以更明确的追踪状态的变化,所以不要直接改变store.state.count的值。</p> <h4>Vuex核心概念</h4> <p><strong>State单一状态树</strong></p> <p>Vuex提出使用单一状态树, 什么是单一状态树呢?<br> 英文名称是Single Source of Truth,也可以翻译成单一数据源。</p> <p>’但是,它是什么呢?我们来看一个生活中的例子。<br> OK,我用一个生活中的例子做一个简单的类比。<br> 我们知道,在国内我们有很多的信息需要被记录,比如上学时的个人档案,工作后的社保记录,公积金记录,结婚后的婚姻信息,以及其他相关的户口、医疗、文凭、房产记录等等(还有很多信息)。<br> 这些信息被分散在很多地方进行管理,有一天你需要办某个业务时(比如入户某个城市),你会发现你需要到各个对应的工作地点去打印、盖章各种资料信息,最后到一个地方提交证明你的信息无误。<br> 这种保存信息的方案,不仅仅低效,而且不方便管理,以及日后的维护也是一个庞大的工作(需要大量的各个部门的人力来维护,当然国家目前已经在完善我们的这个系统了)。</p> <p>这个和我们在应用开发中比较类似:<br> 如果你的状态信息是保存到多个Store对象中的,那么之后的管理和维护等等都会变得特别困难。<br> 所以Vuex也使用了单一状态树来管理应用层级的全部状态。<br> 单一状态树能够让我们最直接的方式找到某个状态的片段,而且在之后的维护和调试过程中,也可以非常方便的管理和维护。</p> <p><strong>Getters</strong></p> <p>有时候,我们需要从store中获取一些state变异后的状态,比如下面的Store中:<br> 获取学生年龄大于20的个数。</p> <p><a href="http://img.e-com-net.com/image/info8/a7f7656674d94eee8f3e52c0be0b6a0e.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/a7f7656674d94eee8f3e52c0be0b6a0e.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第92张图片" width="550" height="248" style="border:1px solid black;"></a><br> 我们可以在Store中定义getters</p> <p><a href="http://img.e-com-net.com/image/info8/18664b890dc140a382aa1339f167ab77.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/18664b890dc140a382aa1339f167ab77.jpg" alt="在这里插入图片描述" width="650" height="73"></a></p> <p><strong>Getters作为参数和传递参数</strong></p> <p>如果我们已经有了一个获取所有年龄大于20岁学生列表的getters, 那么代码可以这样来写<br> <a href="http://img.e-com-net.com/image/info8/def1912c03634a74bda2cd898a3ec1ad.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/def1912c03634a74bda2cd898a3ec1ad.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第93张图片" width="560" height="205" style="border:1px solid black;"></a></p> <p>getters默认是不能传递参数的, 如果希望传递参数, 那么只能让getters本身返回另一个函数.<br> 比如上面的案例中,我们希望根据ID获取用户的信息</p> <p><a href="http://img.e-com-net.com/image/info8/f3468258c5f44cd480f64eb68929e825.png" target="_blank"><img src="http://img.e-com-net.com/image/info8/f3468258c5f44cd480f64eb68929e825.png" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第94张图片" width="521" height="166" style="border:1px solid black;"></a></p> <p><strong>Mutation状态更新</strong></p> <p>Vuex的store状态的更新唯一方式:提交Mutation<br> Mutation主要包括两部分:<br> 字符串的事件类型(type)<br> 一个回调函数(handler),该回调函数的第一个参数就是state。<br> mutation的定义方式:</p> <p><a href="http://img.e-com-net.com/image/info8/ba81ad15a75c4ada92ae198e92f13ccf.png" target="_blank"><img src="http://img.e-com-net.com/image/info8/ba81ad15a75c4ada92ae198e92f13ccf.png" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第95张图片" width="333" height="110" style="border:1px solid black;"></a></p> <p>通过mutation更新</p> <p><a href="http://img.e-com-net.com/image/info8/f1a40d2df306439bb387677ef9ecf4b7.png" target="_blank"><img src="http://img.e-com-net.com/image/info8/f1a40d2df306439bb387677ef9ecf4b7.png" alt="在这里插入图片描述" width="340" height="78"></a></p> <p>Mutation传递参数</p> <p>在通过mutation更新数据的时候, 有可能我们希望携带一些额外的参数<br> 参数被称为是mutation的载荷(Payload)<br> Mutation中的代码:</p> <p><a href="http://img.e-com-net.com/image/info8/c84cab8d40534431b82e729541ea0685.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/c84cab8d40534431b82e729541ea0685.jpg" alt="在这里插入图片描述" width="650" height="85"></a><br> 但是如果参数不是一个呢?<br> 比如我们有很多参数需要传递.<br> 这个时候, 我们通常会以对象的形式传递, 也就是payload是一个对象.<br> 这个时候可以再从对象中取出相关的信息.</p> <p><a href="http://img.e-com-net.com/image/info8/f2fef0e64bd14fce84d02e5400d73bf5.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/f2fef0e64bd14fce84d02e5400d73bf5.jpg" alt="在这里插入图片描述" width="650" height="87"></a><br> <strong>Mutation提交风格</strong></p> <p>上面的通过commit进行提交是一种普通的方式<br> Vue还提供了另外一种风格, 它是一个包含type属性的对象</p> <p><a href="http://img.e-com-net.com/image/info8/a2a13014bbcf4ca993976e3d3c03af17.png" target="_blank"><img src="http://img.e-com-net.com/image/info8/a2a13014bbcf4ca993976e3d3c03af17.png" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第96张图片" width="341" height="103" style="border:1px solid black;"></a></p> <p>Mutation中的处理方式是将整个commit的对象作为payload使用, 所以代码没有改变, 依然如下:</p> <p><a href="http://img.e-com-net.com/image/info8/d81ab52e8b3e45e787903e404a29500c.png" target="_blank"><img src="http://img.e-com-net.com/image/info8/d81ab52e8b3e45e787903e404a29500c.png" alt="在这里插入图片描述" width="338" height="78"></a></p> <p><strong>Mutation响应规则</strong></p> <p>Vuex的store中的state是响应式的, 当state中的数据发生改变时, Vue组件会自动更新.<br> 这就要求我们必须遵守一些Vuex对应的规则:</p> <ul> <li>提前在store中初始化好所需的属性.</li> <li>当给state中的对象添加新属性时, 使用下面的方式: <ul> <li>方式一: 使用Vue.set(obj, ‘newProp’, 123)</li> <li>方式二: 用心对象给旧对象重新赋值</li> </ul> </li> </ul> <p>我们来看一个例子:<br> 当我们点击更新信息时, 界面并没有发生对应改变.</p> <p>如何才能让它改变呢?<br> 查看下面代码的方式一和方式二<br> 都可以让state中的属性是响应式的.</p> <p><a href="http://img.e-com-net.com/image/info8/6f62f198c3924efd9cec8452f0704c97.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/6f62f198c3924efd9cec8452f0704c97.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第97张图片" width="600" height="520" style="border:1px solid black;"></a></p> <p><strong>Mutation常量类型 – 概念</strong></p> <p>我们来考虑下面的问题:<br> 在mutation中, 我们定义了很多事件类型(也就是其中的方法名称).<br> 当我们的项目增大时, Vuex管理的状态越来越多, 需要更新状态的情况越来越多, 那么意味着Mutation中的方法越来越多.<br> 方法过多, 使用者需要花费大量的经历去记住这些方法, 甚至是多个文件间来回切换, 查看方法名称, 甚至如果不是复制的时候, 可能还会出现写错的情况.</p> <p>如何避免上述的问题呢?<br> 在各种Flux实现中, 一种很常见的方案就是使用常量替代Mutation事件的类型.<br> 我们可以将这些常量放在一个单独的文件中, 方便管理以及让整个app所有的事件类型一目了然.</p> <p>具体怎么做呢?<br> 我们可以创建一个文件: mutation-types.js, 并且在其中定义我们的常量.<br> 定义常量时, 我们可以使用ES2015中的风格, 使用一个常量来作为函数的名称.</p> <p><strong>Mutation常量类型 – 代码</strong></p> <p><a href="http://img.e-com-net.com/image/info8/76de2a1ec15a4e0eba29951b25fb6843.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/76de2a1ec15a4e0eba29951b25fb6843.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第98张图片" width="650" height="291" style="border:1px solid black;"></a></p> <p><strong>Mutation同步函数</strong></p> <p>通常情况下, Vuex要求我们Mutation中的方法必须是同步方法.<br> 主要的原因是当我们使用devtools时, 可以devtools可以帮助我们捕捉mutation的快照.<br> 但是如果是异步操作, 那么devtools将不能很好的追踪这个操作什么时候会被完成.<br> 比如我们之前的代码, 当执行更新时, devtools中会有如下信息: 图1</p> <p><a href="http://img.e-com-net.com/image/info8/b697d38ee1414a8794914cfdae8dbb08.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/b697d38ee1414a8794914cfdae8dbb08.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第99张图片" width="650" height="305" style="border:1px solid black;"></a><br> 但是, 如果Vuex中的代码, 我们使用了异步函数: 图2</p> <p><a href="http://img.e-com-net.com/image/info8/fff472186d2b4a4397e79a9fd6670c3b.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/fff472186d2b4a4397e79a9fd6670c3b.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第100张图片" width="650" height="387" style="border:1px solid black;"></a><br> 你会发现state中的info数据一直没有被改变, 因为他无法追踪到.<br> So, 通常情况下, 不要再mutation中进行异步的操作</p> <p><strong>Actions</strong></p> <p>我们强调, 不要再Mutation中进行异步操作.<br> 但是某些情况, 我们确实希望在Vuex中进行一些异步操作, 比如网络请求, 必然是异步的. 这个时候怎么处理呢?<br> Action类似于Mutation, 但是是用来代替Mutation进行异步操作的.</p> <p>Action的基本使用代码如下:<br> context是什么?<br> context是和store对象具有相同方法和属性的对象.<br> 也就是说, 我们可以通过context去进行commit相关的操作, 也可以获取context.state等.<br> 但是注意, 这里它们并不是同一个对象, 为什么呢? 我们后面学习Modules的时候, 再具体说.</p> <p>这样的代码是否多此一举呢?<br> 我们定义了actions, 然后又在actions中去进行commit, 这不是脱裤放屁吗?<br> 事实上并不是这样, 如果在Vuex中有异步操作, 那么我们就可以在actions中完成了.</p> <p><a href="http://img.e-com-net.com/image/info8/5032646ec79c4719bf6bd3d602721dd8.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/5032646ec79c4719bf6bd3d602721dd8.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第101张图片" width="490" height="383" style="border:1px solid black;"></a></p> <p><strong>Action的分发</strong></p> <p><a href="http://img.e-com-net.com/image/info8/a0ad8318024c462a8a689c82ca61c538.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/a0ad8318024c462a8a689c82ca61c538.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第102张图片" width="650" height="296" style="border:1px solid black;"></a></p> <p><strong>Action返回的Promise</strong></p> <p>前面我们学习ES6语法的时候说过, Promise经常用于异步操作.<br> 在Action中, 我们可以将异步操作放在一个Promise中, 并且在成功或者失败后, 调用对应的resolve或reject.<br> OK, 我们来看下面的代码:</p> <p><a href="http://img.e-com-net.com/image/info8/3216885b43c24a479511a46af7278dc0.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/3216885b43c24a479511a46af7278dc0.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第103张图片" width="609" height="432" style="border:1px solid black;"></a><br> <strong>Module</strong></p> <p>Module是模块的意思, 为什么在Vuex中我们要使用模块呢?<br> Vue使用单一状态树,那么也意味着很多状态都会交给Vuex来管理.<br> 当应用变得非常复杂时,store对象就有可能变得相当臃肿.<br> 为了解决这个问题, Vuex允许我们将store分割成模块(Module), 而每个模块拥有自己的state、mutation、action、getters等</p> <p>我们按照什么样的方式来组织模块呢?<br> 我们来看下边的代码</p> <p><a href="http://img.e-com-net.com/image/info8/5c3b9adbb6f64c1593082091de42b88e.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/5c3b9adbb6f64c1593082091de42b88e.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第104张图片" width="497" height="521" style="border:1px solid black;"></a></p> <p><strong>Module局部状态</strong></p> <p>上面的代码中, 我们已经有了整体的组织结构, 下面我们来看看具体的局部模块中的代码如何书写.<br> 我们在moduleA中添加state、mutations、getters<br> mutation和getters接收的第一个参数是局部状态对象</p> <p><a href="http://img.e-com-net.com/image/info8/c39aa01b26e64a849acb99c8af978354.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/c39aa01b26e64a849acb99c8af978354.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第105张图片" width="650" height="324" style="border:1px solid black;"></a></p> <p>注意:<br> 虽然, 我们的doubleCount和increment都是定义在对象内部的.<br> 但是在调用的时候, 依然是通过this.$store来直接调用的.</p> <p><strong>Actions的写法</strong></p> <p>actions的写法呢? 接收一个context参数对象<br> 局部状态通过 context.state 暴露出来,根节点状态则为 context.rootState</p> <p><a href="http://img.e-com-net.com/image/info8/8750010553f748b79f3731d552a057e2.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/8750010553f748b79f3731d552a057e2.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第106张图片" width="632" height="232" style="border:1px solid black;"></a><br> 如果getters中也需要使用全局的状态, 可以接受更多的参数</p> <p><a href="http://img.e-com-net.com/image/info8/d019a35efc9649ac8cf08182df682170.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/d019a35efc9649ac8cf08182df682170.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第107张图片" width="467" height="184" style="border:1px solid black;"></a></p> <h4>项目结构</h4> <p>当我们的Vuex帮助我们管理过多的内容时, 好的项目结构可以让我们的代码更加清晰.</p> <p><a href="http://img.e-com-net.com/image/info8/47d8b75a0e9f4441b316a3b8f96ecb0a.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/47d8b75a0e9f4441b316a3b8f96ecb0a.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第108张图片" width="650" height="318" style="border:1px solid black;"></a></p> <h3>6、网络模块封装</h3> <h4>网络模块的选择</h4> <p>选择一: 传统的Ajax是基于XMLHttpRequest(XHR)<br> 为什么不用它呢?<br> 非常好解释, 配置和调用方式等非常混乱.<br> 编码起来看起来就非常蛋疼.<br> 所以真实开发中很少直接使用, 而是使用jQuery-Ajax</p> <p>选择二: 在前面的学习中, 我们经常会使用jQuery-Ajax<br> 相对于传统的Ajax非常好用.<br> 为什么不选择它呢?<br> 首先, 我们先明确一点: 在Vue的整个开发中都是不需要使用jQuery了.<br> 那么, 就意味着为了方便我们进行一个网络请求, 特意引用一个jQuery, 你觉得合理吗?<br> jQuery的代码1w+行.<br> Vue的代码才1w+行.<br> 完全没有必要为了用网络请求就引用这个重量级的框架.</p> <p>选择三: 官方在Vue1.x的时候, 推出了Vue-resource.<br> Vue-resource的体积相对于jQuery小很多.<br> 另外Vue-resource是官方推出的.<br> 为什么不选择它呢?<br> 在Vue2.0退出后, Vue作者就在GitHub的Issues中说明了去掉vue-resource, 并且以后也不会再更新.<br> 那么意味着以后vue-reource不再支持新的版本时, 也不会再继续更新和维护.<br> 对以后的项目开发和维护都存在很大的隐患.</p> <p>选择四: 在说明不再继续更新和维护vue-resource的同时, 作者还推荐了一个框架: axios为什么不用它呢?<br> axios有非常多的优点, 并且用起来也非常方便.<br> 稍后, 我们对他详细学习.</p> <h4>jsonp</h4> <p>在前端开发中, 我们一种常见的网络请求方式就是JSONP<br> 使用JSONP最主要的原因往往是为了解决跨域访问的问题.<br> JSONP的原理是什么呢?<br> JSONP的核心在于通过<code><script></code>标签的src来帮助我们请求数据.<br> 原因是我们的项目部署在domain1.com服务器上时, 是不能直接访问domain2.com服务器上的资料的.<br> 这个时候, 我们利用<code><script></code>标签的src帮助我们去服务器请求到数据, 将数据当做一个javascript的函数来执行, 并且执行的过程中传入我们需要的json.<br> 所以, 封装jsonp的核心就在于我们监听window上的jsonp进行回调时的名称.<br> JSONP如何封装呢?<br> 我们一起自己来封装一个处理JSONP的代码吧.</p> <p><a href="http://img.e-com-net.com/image/info8/8c1b62734d7c494f915be0b1f30d0783.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/8c1b62734d7c494f915be0b1f30d0783.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第109张图片" width="468" height="578" style="border:1px solid black;"></a></p> <p><strong>JSONP封装</strong></p> <p><a href="http://img.e-com-net.com/image/info8/73c7b77d48c240ec9d5186dca3ebc113.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/73c7b77d48c240ec9d5186dca3ebc113.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第110张图片" width="650" height="305" style="border:1px solid black;"></a></p> <h4><strong>axios</strong></h4> <p>功能特点:<br> 在浏览器中发送 XMLHttpRequests 请求<br> 在 node.js 中发送 http请求<br> 支持 Promise API<br> 拦截请求和响应<br> 转换请求和响应数据<br> 等等</p> <p><strong>axiox请求方式</strong></p> <p>支持多种请求方式:<br> axios(config)<br> axios.request(config)<br> axios.get(url[, config])<br> axios.delete(url[, config])<br> axios.head(url[, config])<br> axios.post(url[, data[, config]])<br> axios.put(url[, data[, config]])<br> axios.patch(url[, data[, config]])<br> 如何发送请求呢?<br> 我们看一下下边的案例</p> <p><strong>发送get请求演示</strong></p> <p><a href="http://img.e-com-net.com/image/info8/671f92efe5f14ca388bafcf1c797bf4f.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/671f92efe5f14ca388bafcf1c797bf4f.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第111张图片" width="650" height="635" style="border:1px solid black;"></a></p> <p><strong>发送并发请求</strong></p> <p>有时候, 我们可能需求同时发送两个请求<br> 使用axios.all, 可以放入多个请求的数组.<br> axios.all([]) 返回的结果是一个数组,使用 axios.spread 可将数组 [res1,res2] 展开为 res1, res2</p> <p><a href="http://img.e-com-net.com/image/info8/57ad23a3fc884850b3dc743004d25878.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/57ad23a3fc884850b3dc743004d25878.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第112张图片" width="650" height="316" style="border:1px solid black;"></a></p> <p><strong>全局配置</strong></p> <p>在上面的示例中, 我们的BaseURL是固定的<br> 事实上, 在开发中可能很多参数都是固定的.<br> 这个时候我们可以进行一些抽取, 也可以利用axiox的全局配置</p> <pre><code>axios.defaults.baseURL = '123.207.32.32:8000' axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'; </code></pre> <p><a href="http://img.e-com-net.com/image/info8/298855f064724432a80f50afa624cbed.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/298855f064724432a80f50afa624cbed.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第113张图片" width="650" height="323" style="border:1px solid black;"></a></p> <p><strong>常见的配置选项</strong></p> <p>请求地址<br> url: ‘/user’,<br> 请求类型<br> method: ‘get’,<br> 请根路径<br> baseURL: ‘http://www.mt.com/api’,<br> 请求前的数据处理<br> transformRequest:[function(data){}],<br> 请求后的数据处理<br> transformResponse: [function(data){}],<br> 自定义的请求头<br> headers:{‘x-Requested-With’:‘XMLHttpRequest’},<br> URL查询对象<br> params:{ id: 12 },</p> <p>查询对象序列化函数<br> paramsSerializer: function(params){ }<br> request body<br> data: { key: ‘aa’},<br> 超时设置s<br> timeout: 1000,<br> 跨域是否带Token<br> withCredentials: false,<br> 自定义请求处理<br> adapter: function(resolve, reject, config){},<br> 身份验证信息<br> auth: { uname: ‘’, pwd: ‘12’},<br> 响应的数据格式 json / blob /document /arraybuffer / text / stream<br> responseType: ‘json’,</p> <h4>axios的实例</h4> <p>为什么要创建axios的实例呢?</p> <ul> <li>当我们从axios模块中导入对象时, 使用的实例是默认的实例.</li> <li>当给该实例设置一些默认配置时, 这些配置就被固定下来了.</li> <li>但是后续开发中, 某些配置可能会不太一样.</li> <li>比如某些请求需要使用特定的baseURL或者timeout或者content-Type等.</li> <li>这个时候, 我们就可以创建新的实例, 并且传入属于该实例的配置信息.</li> </ul> <p><a href="http://img.e-com-net.com/image/info8/124fc4dc17e345efa0bbc968b04686d1.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/124fc4dc17e345efa0bbc968b04686d1.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第114张图片" width="650" height="128" style="border:1px solid black;"></a></p> <p><strong>axios封装</strong></p> <p><a href="http://img.e-com-net.com/image/info8/ece261030019486398ecdeb41fb5c65f.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/ece261030019486398ecdeb41fb5c65f.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第115张图片" width="650" height="563" style="border:1px solid black;"></a></p> <h4>拦截器</h4> <p>axios提供了拦截器,用于我们在发送每次请求或者得到相应后,进行对应的处理。<br> 如何使用拦截器呢?</p> <p><a href="http://img.e-com-net.com/image/info8/5156531707714a3883b6f7929e851751.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/5156531707714a3883b6f7929e851751.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第116张图片" width="650" height="217" style="border:1px solid black;"></a></p> <p><strong>拦截器中都做什么呢?</strong></p> <p>请求拦截可以做到的事情:</p> <p><a href="http://img.e-com-net.com/image/info8/4c5bf8ec310445f6a3665e97ea055704.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/4c5bf8ec310445f6a3665e97ea055704.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第117张图片" width="650" height="230" style="border:1px solid black;"></a></p> <p>请求拦截中错误拦截较少,通常都是配置相关的拦截<br> 可能的错误比如请求超时,可以将页面跳转到一个错误页面中。</p> <p>响应拦截中完成的事情:<br> 响应的成功拦截中,主要是对数据进行过滤。</p> <p><a href="http://img.e-com-net.com/image/info8/683daa4be5b44ef8b1f44a013447273e.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/683daa4be5b44ef8b1f44a013447273e.jpg" alt="在这里插入图片描述" width="650" height="74"></a></p> <p>响应的失败拦截中,可以根据status判断报错的错误码,跳转到不同的错误提示页面。</p> <p><a href="http://img.e-com-net.com/image/info8/064b38be991b4beda5575a84cfbbc4a2.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/064b38be991b4beda5575a84cfbbc4a2.jpg" alt="Vue 知识点汇总(下)--附案例代码及项目地址_第118张图片" width="466" height="295" style="border:1px solid black;"></a></p> <h2>四、案例</h2> <h3>1、<span id="TabBar">TabBar</span></h3> <p>TabBar.vue</p> <pre><code><template> <div class="tab-bar"> <slot></slot> </div> </template> <script> export default { name: 'TabBar', data() { return { } } } </script> <style scoped> .tab-bar{ display: flex; background-color: #f6f6f6; position: fixed; left: 0; right: 0; bottom: 0; box-shadow: 0 -3px 1px rgba(100, 100, 100, 0.1); } </style> </code></pre> <p>TabBarItem.vue</p> <pre><code><template> <div class="tab-bar-item" @click="itemClick()"> <div v-if = "!isActive"><slot name = "item-icon"></slot></div> <div v-else><slot name = "item-icon-active"></slot></div> <div :style="activeStyle"><slot name = "item-text"></slot></div> <!-- <img src = "../../assets/img/tabbar/home.svg" alt=""> <div>首页</div> --> </div> </template> <script> export default { name: 'TabBarItem', props: { path: String, activeColor:{ type: String, default: 'red', } }, data() { return { // isActive: false } }, computed:{ isActive(){ return this.$route.path.indexOf(this.path) !== -1 }, activeStyle(){ return this.isActive ? {color:this.activeColor}:{} } }, methods:{ itemClick(){ if(this.$route.path != this.path) { this.$router.replace(this.path)} } } } </script> <style scoped> .tab-bar-item{ flex: 1; text-align: center; height: 49px; } .tab-bar-item img{ width:24px; height: 24px; margin-top: 3px; vertical-align: middle; } .active{ color: blueviolet; } </style> </code></pre> </div> </div> </div> </div> </div> <!--PC和WAP自适应版--> <div id="SOHUCS" sid="1274339474595135488"></div> <script type="text/javascript" src="/views/front/js/chanyan.js"></script> <!-- 文章页-底部 动态广告位 --> <div class="youdao-fixed-ad" id="detail_ad_bottom"></div> </div> <div class="col-md-3"> <div class="row" id="ad"> <!-- 文章页-右侧1 动态广告位 --> <div id="right-1" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_1"> </div> </div> <!-- 文章页-右侧2 动态广告位 --> <div id="right-2" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_2"></div> </div> <!-- 文章页-右侧3 动态广告位 --> <div id="right-3" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_3"></div> </div> </div> </div> </div> </div> </div> <div class="container"> <h4 class="pt20 mb15 mt0 border-top">你可能感兴趣的:(Vue,笔记)</h4> <div id="paradigm-article-related"> <div class="recommend-post mb30"> <ul class="widget-links"> <li><a href="/article/1773583062202908672.htm" title="新网师的精神肤色(幕布笔记)" target="_blank">新网师的精神肤色(幕布笔记)</a> <span class="text-muted">悦读书香</span> <div>王子老师的《极简100小妙招》收到已经几天了,之前大概的浏览了全书,今天起给自己定了一个计划,必须每天学习极简小妙招里面的一个妙招,并加以运用。一、今天要打卡什么内容因有完成每天学习极简小妙招的计划,所以今天晚饭吃的比较简单,草草吃完以后带着小宝到广场溜达一圈,急忙赶回来学习极简小妙招。再重看的时候不知道自己要学点什么,打卡哪一招,感觉哪个都简单,就看这一环节像王子老师说的“一看就会”,但做这一环</div> </li> <li><a href="/article/1773545802220765184.htm" title="C++学习笔记(lambda函数)" target="_blank">C++学习笔记(lambda函数)</a> <span class="text-muted">__TAT__</span> <a class="tag" taget="_blank" href="/search/C%26amp%3BC%2B%2B/1.htm">C&C++</a><a class="tag" taget="_blank" href="/search/c%2B%2B/1.htm">c++</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a><a class="tag" taget="_blank" href="/search/%E7%AC%94%E8%AE%B0/1.htm">笔记</a> <div>C++learningnote1、lambda函数的语法2、lambda函数的几种用法1、lambda函数的语法lambda函数的一般语法如下:[capture_clause](parameters)->return_type{function_body}capture_clause:需要捕获的变量,但要求该变量必须在这个作用域中。通常的捕获方式有以下几种:[]:不捕获任何变量[&]:按引用捕获变</div> </li> <li><a href="/article/1773528105273589760.htm" title="v-for 实例" target="_blank">v-for 实例</a> <span class="text-muted">琪33</span> <div>v-for实例v-for实例{{item}}{{index+1}}:{{student.name}}-{{student.age}}varapp=newVue({el:'#app',data:{items:[53,23,76,14,54,36,28],students:[{name:'jspang',age:32},{name:'Panda',age:30},{name:'PanPaN',age:</div> </li> <li><a href="/article/1773515340869861376.htm" title="npm 搭建 Vite 项目" target="_blank">npm 搭建 Vite 项目</a> <span class="text-muted">渺小的虫子</span> <a class="tag" taget="_blank" href="/search/viter/1.htm">viter</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a> <div>兼容性注意Vite需要Node.js版本>=12.0.0。1、使用npm安装Viter$npminitvite@latest使用npm初始化项目#npm6.xnpminitvite@latestmy-vue-app--templatevue#npm7+,需要额外的双横线:npminitvite@latestmy-vue-app----templatevue2、配置路由:npminstallvue-</div> </li> <li><a href="/article/1773499853914046464.htm" title="vue 通信方式" target="_blank">vue 通信方式</a> <span class="text-muted">hx_1199</span> <a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a> <div>1、props和$emit父组件向子组件传递数据是通过props传递的,子组件传递给父组件是通过$emit触发事件来做到的。父组件this.$emit("update:page",newVal)-->importChildfrom'./child'exportdefault{name:"Father",components:{Child,},data(){return{articleList:['</div> </li> <li><a href="/article/1773499616306724864.htm" title="读书笔记《穿越寒冬》" target="_blank">读书笔记《穿越寒冬》</a> <span class="text-muted">如雪般飞舞</span> <div>各位好,我们今天来讲一本书,名字叫作《穿越寒冬》。看起来特别应景,大家觉得现在创业的状况不景气,大家都在忍受着寒冬的煎熬。但实际上,这本书的英文名字并不是这个意思,它的英文名叫作“如何创立一家新公司,并且能够活下来”。我在整个读完了以后,我发现这本书真正要翻译得好,它的名字应该叫作《创业生存手册》。这个书的作者,来自硅谷的霍夫曼船长。霍夫曼船长写过一本让创业者觉得特别贴心的书,叫作《让大象飞》它和</div> </li> <li><a href="/article/1773475780618158080.htm" title="2018-11-18成长小组学习笔记" target="_blank">2018-11-18成长小组学习笔记</a> <span class="text-muted">实验中学45</span> <div>因为嗓子“罢工”,我面对众人只能借“微笑”代言。在开始授课前,绣霞老师先反馈上次作业的情况,提到“接纳”需是真正发自内心的完全接纳,而不是口头上的接纳,内心却是排斥的。提到一个“问题”孩子恰恰对家爱的更加“深沉”,夫妻间的问题不能影响到孩子,对孩子更好的爱不是你为他做的更多,而是给他自由、健康成长的空间。图片发自App一、孩子:家庭的一面镜子夫妻成了彼此的“投射”,婚姻便“吵的不可开交”,婚姻便成</div> </li> <li><a href="/article/1773458565772673024.htm" title="【鸿蒙HarmonyOS开发笔记】ArkUI常用组件介绍汇总(更新中)" target="_blank">【鸿蒙HarmonyOS开发笔记】ArkUI常用组件介绍汇总(更新中)</a> <span class="text-muted">温、</span> <a class="tag" taget="_blank" href="/search/%E9%B8%BF%E8%92%99HarmonyOS%E5%BC%80%E5%8F%91%E7%AC%94%E8%AE%B0/1.htm">鸿蒙HarmonyOS开发笔记</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95/1.htm">学习记录</a><a class="tag" taget="_blank" href="/search/harmonyos/1.htm">harmonyos</a><a class="tag" taget="_blank" href="/search/%E7%AC%94%E8%AE%B0/1.htm">笔记</a><a class="tag" taget="_blank" href="/search/%E5%8D%8E%E4%B8%BA/1.htm">华为</a> <div>概述此文总结开发中用到的一些常用组件,便于查阅,此文持续更新,闲的没事就更线性布局(Row/Column)不多介绍了,最常用的布局组件,两者除了方向不一样,别的都一样方便起见下面只写Column常用属性排列方向上的间距:spaceColumn({space:20}){Row().width('90%').height(50).backgroundColor(0xF5DEB3)Row().width</div> </li> <li><a href="/article/1773437213028188160.htm" title="安卓笔记本 - Handler Message MessageQueue Looper" target="_blank">安卓笔记本 - Handler Message MessageQueue Looper</a> <span class="text-muted">SocialException</span> <div>不爱写字,一张图解决。Handler,Message,MessageQueue,Looper工作原理</div> </li> <li><a href="/article/1773436409693143040.htm" title="枚举使用笔记" target="_blank">枚举使用笔记</a> <span class="text-muted">万变不离其宗_8</span> <a class="tag" taget="_blank" href="/search/%E9%A1%B9%E7%9B%AE%E7%AC%94%E8%AE%B0/1.htm">项目笔记</a><a class="tag" taget="_blank" href="/search/%E7%AC%94%E8%AE%B0/1.htm">笔记</a> <div>1.java枚举怎么放在方法上面的注释里面/***保存*@paramuserId用户id*@paramtype见枚举{@linkcom.common.enums.TypeEnum}*@return*/voidsave(LonguserId,Stringtype);</div> </li> <li><a href="/article/1773420547133210624.htm" title="ruoyi使用笔记" target="_blank">ruoyi使用笔记</a> <span class="text-muted">万变不离其宗_8</span> <a class="tag" taget="_blank" href="/search/%E9%A1%B9%E7%9B%AE%E7%AC%94%E8%AE%B0/1.htm">项目笔记</a><a class="tag" taget="_blank" href="/search/%E4%BB%A3%E7%A0%81%E5%8F%82%E8%80%83%E7%AC%94%E8%AE%B0/1.htm">代码参考笔记</a><a class="tag" taget="_blank" href="/search/%E7%AC%94%E8%AE%B0/1.htm">笔记</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a> <div>1.限流处理@RateLimiter@PostMapping("/createOrder")@ApiOperation("创建充值订单")@RateLimiter(key=CacheConstants.REPEAT_SUBMIT_KEY,time=10,count=1,limitType=LimitType.IP)publicRcreateOrder(@RequestBodyFormform){/</div> </li> <li><a href="/article/1773411736095883264.htm" title="数据管理知识体系指南(第二版)-第五章——数据建模和设计-学习笔记" target="_blank">数据管理知识体系指南(第二版)-第五章——数据建模和设计-学习笔记</a> <span class="text-muted">键盘上的五花肉</span> <a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E6%B2%BB%E7%90%86/1.htm">数据治理</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">数据库</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E4%BB%93%E5%BA%93/1.htm">数据仓库</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E6%B2%BB%E7%90%86/1.htm">数据治理</a> <div>目录5.1引言5.1.1业务驱动因素5.1.2目标和原则5.1.3基本概念5.2活动5.2.1规划数据建模5.2.2建立数据模型5.2.3审核数据模型5.2.4维护数据模型5.3工具5.3.1数据建模工具5.3.2数据血缘工具5.3.3数据分析工具5.3.4元数据资料库5.3.5数据模型模式5.3.6行业数据模型5.4方法5.4.1命名约定的最佳实践5.4.2数据库设计中的最佳实践5.5数据建模和</div> </li> <li><a href="/article/1773389331080216576.htm" title="VUE 页面禁止缩放(华为平板浏览器可能失效)" target="_blank">VUE 页面禁止缩放(华为平板浏览器可能失效)</a> <span class="text-muted">唐屁屁儿</span> <a class="tag" taget="_blank" href="/search/JS/1.htm">JS</a><a class="tag" taget="_blank" href="/search/vue/1.htm">vue</a><a class="tag" taget="_blank" href="/search/webview/1.htm">webview</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a> <div>h5页面移动端禁止缩放、web页面禁止浏览器缩放移动端优先,可禁止用户缩放和双击放大;在App.vue中的script内的方法里加入以下代码:window.onload=function(){document.addEventListener('touchstart',function(event){if(event.touches.length>1){event.preventDefault()</div> </li> <li><a href="/article/1773351821931249664.htm" title="Java学习笔记01" target="_blank">Java学习笔记01</a> <span class="text-muted">.wsy.</span> <a class="tag" taget="_blank" href="/search/%E6%97%A5%E5%B8%B8/1.htm">日常</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a><a class="tag" taget="_blank" href="/search/%E7%AC%94%E8%AE%B0/1.htm">笔记</a> <div>1.1Java简介Java的前身是Oak,詹姆斯·高斯林是java之父。1.2Java体系Java是一种与平台无关的语言,其源代码可以被编译成一种结构中立的中间文件(.class,字节码文件)于Java虚拟机上运行。1.2.3专有名词JDK提供编译、运行Java程序所需要的种种工具及资源。JRE是运行Java所依赖的环境的集合。JVM是一个虚构出来的计算机,通过在实际的计算机上仿真模拟各种计算机功</div> </li> <li><a href="/article/1773347920293199872.htm" title="Vue 常见面试题(一)" target="_blank">Vue 常见面试题(一)</a> <span class="text-muted">安生生申</span> <a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95%E9%A2%98/1.htm">面试题</a><a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a> <div>目录1、Vue的最大的优势是什么?(必会)2、Vue和jQuery两者之间的区别是什么?(必会)3、MVVM和MVC区别是什么?哪些场景适合?(必会)1、基本定义2、使用场景3、两者之间的区别4、Vue数据双向绑定的原理是什么?(必会)5、Object.defineProperty和Proxy的区别(必会)6、Vue生命周期总共分为几个阶段?(必会)7、第一次加载页面会触发哪几个钩子函数?(必会)</div> </li> <li><a href="/article/1773340139582455808.htm" title="《老子》笔记19 2018-10-28" target="_blank">《老子》笔记19 2018-10-28</a> <span class="text-muted">海上明月共</span> <div>第二十二章[原文]曲则全,枉则直,洼则盈,敝则新,少则得,多则惑。是以圣人抱一为天下式。不自见,故明;不自是,故彰,不自伐,故有功;不自矜,故长。夫唯不争,故天下莫能与之争。古之所谓"曲则全"者,岂虚言哉?诚全而归之。[译文]委曲便会保全,屈枉便会直伸;低洼便会充盈,陈旧便会更新;少取便会获得,贪多便会迷惑。所以有道的人坚守这一原则作为天下事理的范式,不自我表扬,反能显明;不自以为是,反能是非彰明</div> </li> <li><a href="/article/1773321618093834240.htm" title="以客户为中心的企业设计(咨询执业笔记)" target="_blank">以客户为中心的企业设计(咨询执业笔记)</a> <span class="text-muted">觉者看世界</span> <div>以客户为中心的企业设计(咨询执业笔记)——何伏全案咨询知名专家数字经济大行其道,过剩的风险资本自由流动,股权市场日益强势,这些力量综合在一起,产生出诸多不合理的企业设计。这些事实使得企业设计的再创造越来越需要一种约束力,许多公司和投资者未能熟谙这种约束力,或者未能将其基本原理运用于具体的商业行为中,因此付出了沉重的代价。无利润区的确存在,并且已在全球蔓延,有愈演愈烈之势。它席卷了数以千计的公司,涉</div> </li> <li><a href="/article/1773240552423227392.htm" title="react native 总结" target="_blank">react native 总结</a> <span class="text-muted">一切顺势而行</span> <a class="tag" taget="_blank" href="/search/react/1.htm">react</a><a class="tag" taget="_blank" href="/search/native/1.htm">native</a><a class="tag" taget="_blank" href="/search/react.js/1.htm">react.js</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a> <div>reactapp.js相当与vueapp.vueimportReactfrom'react';import'./App.css';importReactRoutefrom'./router'import{HashRouterasRouter,Link}from'react-router-dom'classAppextendsReact.Component{constructor(props){su</div> </li> <li><a href="/article/1773230859613175808.htm" title="Vue 模版编译原理" target="_blank">Vue 模版编译原理</a> <span class="text-muted">I will.874</span> <a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a> <div>当我们使用Vue编写完一个组件以后,Vue会根据模版编译一个render函数,调用render函数生成虚拟DOM,然后将虚拟DOM映射成真实DOM当数据发生变化时,Vue会触发更新视图,调用render函数返回新的虚拟DOM,对比新旧虚拟DOM,修改真实DOM,从而更新页面在此期间,有以下4个关键步骤:模版编译。生成渲染函数render执行render函数生成虚拟DOM首次渲染,根据虚拟DOM生成</div> </li> <li><a href="/article/1773229599585533952.htm" title="【Git安装及使用学习笔记】" target="_blank">【Git安装及使用学习笔记】</a> <span class="text-muted">可可西里啊</span> <a class="tag" taget="_blank" href="/search/%E9%9B%B6%E9%9B%B6%E6%95%A3%E6%95%A3%E7%9A%84%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/1.htm">零零散散的学习笔记</a><a class="tag" taget="_blank" href="/search/git/1.htm">git</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a><a class="tag" taget="_blank" href="/search/%E7%AC%94%E8%AE%B0/1.htm">笔记</a><a class="tag" taget="_blank" href="/search/c%2B%2B/1.htm">c++</a><a class="tag" taget="_blank" href="/search/qt5/1.htm">qt5</a> <div>Git学习笔记Git安装Git创建本地版本库以及提交文件使用Git提交代码到码云使用Git从码云拉取代码参考博客Git安装这里参考Git详细安装教程(详解Git安装过程的每一个步骤)Git创建本地版本库以及提交文件1.查看git版本信息:git--version2.设置对应用户名与邮箱地址gitconfig--globaluser.name"your_usernamegitconfig--glob</div> </li> <li><a href="/article/1773212227294265344.htm" title="reactive和ref的异同、toRef和toRefs的使用" target="_blank">reactive和ref的异同、toRef和toRefs的使用</a> <span class="text-muted">Niucode</span> <a class="tag" taget="_blank" href="/search/vue3/1.htm">vue3</a><a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a> <div>一、reactive和ref有了reactive为什么还要ref?ref处理起基本数据类型来更加的方便快捷,性能要更好。ref内部值的变化只会触发订阅它的副作用函数(effect)更新,而reactive(Proxy)内部对象的任何属性变化都会触发整个对象的重新渲染。相同点:都是Vue3提供的用于创建响应式数据的函数;在组件中都能够触发视图更新,实现数据的双向绑定。不同点:数据类型:reactiv</div> </li> <li><a href="/article/1772795036136701952.htm" title="程序员开发技术整理" target="_blank">程序员开发技术整理</a> <span class="text-muted">laizhixue</span> <a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6/1.htm">前端框架</a> <div>前端技术:vue-前端框架element-前端框架bootstrap-前端框架echarts-图标组件C#后端技术:webservice:soap架构:简单的通信协议,用于服务通信ORM框架:对象关系映射,如EF:对象实体模型,是ado.net中的应用技术soap服务通讯:xml通讯ado.net:OAuth2:登录授权认证:Token认证:JWT:jsonwebtokenJava后端技术:便捷工</div> </li> <li><a href="/article/1772793810569461760.htm" title="读书笔记|《穆斯林的葬礼》" target="_blank">读书笔记|《穆斯林的葬礼》</a> <span class="text-muted">飞舞的微辰</span> <div>她从来也没有打算对过去的恩怨进行报偿或是惩罚,只是想把该记住的都记住,该忘却的都忘却。事业的追求,并不一定要什么头衔和称号来满足,你爱上了一种东西,愿意用全部心血去研究它,掌握它,从中得到乐趣,并且永远也不舍得丢其它,这是事业心,是比什么都重要的......人生在世,谁也管不了谁;生儿育女,不是为了父母,是为了儿女自己,各人的路,让他们自己去闯吧。七尺之躯,一抔黄土,穆斯林们一个个都离去了,什么都</div> </li> <li><a href="/article/1772787481222119424.htm" title="C#学习笔记" target="_blank">C#学习笔记</a> <span class="text-muted">2301_79022588</span> <a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a><a class="tag" taget="_blank" href="/search/%E7%AC%94%E8%AE%B0/1.htm">笔记</a> <div>一、事件派发器在C#中,事件派发器通常是指事件委托和事件处理程序的组合,用于实现一种观察者设计模式。它允许对象在状态发生变化时通知其他对象,从而实现对象之间的解耦。事件派发器的基本组成部分:事件委托(EventDelegate):事件委托是一种特殊的委托,用于封装可以被调用的方法。它定义了事件的签名,即指定了事件处理程序方法的参数和返回类型。通常,事件委托声明在事件派发器类的外部,并且使用dele</div> </li> <li><a href="/article/1772736200734474240.htm" title="遇见美好|期待越来越好的自己|复盘日记Day137" target="_blank">遇见美好|期待越来越好的自己|复盘日记Day137</a> <span class="text-muted">沫ma的1001页</span> <div>遇见美好|期待越来越好的自己|复盘日记Day1372021年7月21日星期三晴喜马拉雅(沫沫成长记)亲子共读:Day42阅读学习践行Day.17/21晨间日记Day.17/21昨日晚安:23:02今日早安:05:00早起:Day806❥今日运动|跑步0Km(未完成)❥今日自我成长|学习新知识1.听书+书写笔记,小花生阅读打卡2..阅读学习,听音频+写作业3.时间管理2.0线上践行,听课+写作业4.</div> </li> <li><a href="/article/1772700920866471936.htm" title="D43+1组棉布+《一个人的朝圣》读书笔记" target="_blank">D43+1组棉布+《一个人的朝圣》读书笔记</a> <span class="text-muted">棉布家的小橘子</span> <div>前几天读了《一个人的朝圣》,感受到信念、目标对一个人是多么重要。哈罗德因为奎妮的一封告别信,步行横跨英格兰去探望她。因为有了目标和信念他才能坚持下去。而奎妮也一直在等他。一路哈罗德回忆儿子戴维,回忆自己小时候的遭遇,回忆与妻子莫琳的种种。想通了许多事情,与其说他要去拯救奎妮不如说在拯救自己。哈罗德与父母哈罗德的童年是不幸的,爸爸妈妈根本没有想当父母却生下了他。妈妈离家出走,爸爸开始找不同的阿姨,在</div> </li> <li><a href="/article/1772681873261133824.htm" title="Java学习笔记04:Java_数组" target="_blank">Java学习笔记04:Java_数组</a> <span class="text-muted">JasonYangQ</span> <a class="tag" taget="_blank" href="/search/Java/1.htm">Java</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>文章目录1.数组1.1数组介绍1.2数组的定义格式1.2.1第一种格式1.2.2第二种格式1.3数组的动态初始化1.3.1什么是动态初始化1.3.2动态初始化格式1.3.3动态初始化格式详解1.4数组元素访问1.4.1什么是索引1.4.2访问数组元素格式1.4.3示例代码1.5内存分配1.5.1内存概述1.5.2java中的内存分配1.9数组的静态初始化1.9.1什么是静态初始化1.9.2静态初始</div> </li> <li><a href="/article/1772654174425645056.htm" title="基于SSM+Vue企业销售培训系统 企业人才培训系统 企业课程培训管理系统 企业文化培训班系统Java" target="_blank">基于SSM+Vue企业销售培训系统 企业人才培训系统 企业课程培训管理系统 企业文化培训班系统Java</a> <span class="text-muted">计算机程序老哥</span> <div>作者主页:计算机毕业设计老哥有问题可以主页问我一、开发介绍1.1开发环境开发语言:Java数据库:MySQL系统架构:B/S后端:SSM(Spring+SpringMVC+Mybatis)前端:Vue工具:IDEA或者Eclipse,JDK1.8,Maven二、系统介绍2.1图片展示注册登录页面:登陆.png前端页面功能:首页、培训班、在线学习、企业文化、交流论坛、试卷列表、系统公告、留言反馈、个</div> </li> <li><a href="/article/1772634413142704128.htm" title="vue 在style标签中引入js变量控制样式" target="_blank">vue 在style标签中引入js变量控制样式</a> <span class="text-muted">古迪红尘</span> <a class="tag" taget="_blank" href="/search/VUE/1.htm">VUE</a><a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a> <div>1.基本的绑定样式示例data(){return{colorData:'blue',}}详细用法可参考下面的博客:https://www.jianshu.com/p/2b82ee1e6199</div> </li> <li><a href="/article/1772618299398488064.htm" title="Vue:为什么要使用v-cloak" target="_blank">Vue:为什么要使用v-cloak</a> <span class="text-muted">刻刻帝的海角</span> <a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a> <div>Vue.js是一种流行的JavaScript框架,它使我们能够构建交互性强大的用户界面。在Vue.js中,v-cloak是一个指令,用于解决在页面加载时出现的闪烁问题。本文将介绍如何使用v-cloak及代码来优化Vue.js应用程序的渲染效果。引言当我们使用Vue.js构建应用程序时,有时会遇到一个问题:在页面加载时,由于Vue.js需要一定的时间来解析和渲染模板,会导致页面上显示出未经处理的Mu</div> </li> <li><a href="/article/55.htm" title="多线程编程之卫生间" target="_blank">多线程编程之卫生间</a> <span class="text-muted">周凡杨</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%B9%B6%E5%8F%91/1.htm">并发</a><a class="tag" taget="_blank" href="/search/%E5%8D%AB%E7%94%9F%E9%97%B4/1.htm">卫生间</a><a class="tag" taget="_blank" href="/search/%E7%BA%BF%E7%A8%8B/1.htm">线程</a><a class="tag" taget="_blank" href="/search/%E5%8E%95%E6%89%80/1.htm">厕所</a> <div>如大家所知,火车上车厢的卫生间很小,每次只能容纳一个人,一个车厢只有一个卫生间,这个卫生间会被多个人同时使用,在实际使用时,当一个人进入卫生间时则会把卫生间锁上,等出来时打开门,下一个人进去把门锁上,如果有一个人在卫生间内部则别人的人发现门是锁的则只能在外面等待。问题分析:首先问题中有两个实体,一个是人,一个是厕所,所以设计程序时就可以设计两个类。人是多数的,厕所只有一个(暂且模拟的是一个车厢)。</div> </li> <li><a href="/article/182.htm" title="How to Install GUI to Centos Minimal" target="_blank">How to Install GUI to Centos Minimal</a> <span class="text-muted">sunjing</span> <a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a><a class="tag" taget="_blank" href="/search/Install/1.htm">Install</a><a class="tag" taget="_blank" href="/search/Desktop/1.htm">Desktop</a><a class="tag" taget="_blank" href="/search/GUI/1.htm">GUI</a> <div>http://www.namhuy.net/475/how-to-install-gui-to-centos-minimal.html   I have centos 6.3 minimal running as web server. I’m looking to install gui to my server to vnc to my server. You can insta</div> </li> <li><a href="/article/309.htm" title="Shell 函数" target="_blank">Shell 函数</a> <span class="text-muted">daizj</span> <a class="tag" taget="_blank" href="/search/shell/1.htm">shell</a><a class="tag" taget="_blank" href="/search/%E5%87%BD%E6%95%B0/1.htm">函数</a> <div>Shell 函数 linux shell 可以用户定义函数,然后在shell脚本中可以随便调用。 shell中函数的定义格式如下: [function] funname [()]{ action; [return int;] } 说明: 1、可以带function fun() 定义,也可以直接fun() 定义,不带任何参数。 2、参数返回</div> </li> <li><a href="/article/436.htm" title="Linux服务器新手操作之一" target="_blank">Linux服务器新手操作之一</a> <span class="text-muted">周凡杨</span> <a class="tag" taget="_blank" href="/search/Linux+%E7%AE%80%E5%8D%95+%E6%93%8D%E4%BD%9C/1.htm">Linux 简单 操作</a> <div>1.whoami      当一个用户登录Linux系统之后,也许他想知道自己是发哪个用户登录的。      此时可以使用whoami命令。      [ecuser@HA5-DZ05 ~]$ whoami       e</div> </li> <li><a href="/article/563.htm" title="浅谈Socket通信(一)" target="_blank">浅谈Socket通信(一)</a> <span class="text-muted">朱辉辉33</span> <a class="tag" taget="_blank" href="/search/socket/1.htm">socket</a> <div>在java中ServerSocket用于服务器端,用来监听端口。通过服务器监听,客户端发送请求,双方建立链接后才能通信。当服务器和客户端建立链接后,两边都会产生一个Socket实例,我们可以通过操作Socket来建立通信。    首先我建立一个ServerSocket对象。当然要导入java.net.ServerSocket包    ServerSock</div> </li> <li><a href="/article/690.htm" title="关于框架的简单认识" target="_blank">关于框架的简单认识</a> <span class="text-muted">西蜀石兰</span> <a class="tag" taget="_blank" href="/search/%E6%A1%86%E6%9E%B6/1.htm">框架</a> <div>入职两个月多,依然是一个不会写代码的小白,每天的工作就是看代码,写wiki。 前端接触CSS、HTML、JS等语言,一直在用的CS模型,自然免不了数据库的链接及使用,真心涉及框架,项目中用到的BootStrap算一个吧,哦,JQuery只能算半个框架吧,我更觉得它是另外一种语言。 后台一直是纯Java代码,涉及的框架是Quzrtz和log4j。 都说学前端的要知道三大框架,目前node.</div> </li> <li><a href="/article/817.htm" title="You have an error in your SQL syntax; check the manual that corresponds to your" target="_blank">You have an error in your SQL syntax; check the manual that corresponds to your</a> <span class="text-muted">林鹤霄</span> <div>You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'option,changed_ids  ) values('0ac91f167f754c8cbac00e9e3dc372</div> </li> <li><a href="/article/944.htm" title="MySQL5.6的my.ini配置" target="_blank">MySQL5.6的my.ini配置</a> <span class="text-muted">aigo</span> <a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a> <div>注意:以下配置的服务器硬件是:8核16G内存    [client]   port=3306   [mysql]   default-character-set=utf8     [mysqld]   port=3306   basedir=D:/mysql-5.6.21-win</div> </li> <li><a href="/article/1071.htm" title="mysql 全文模糊查找 便捷解决方案" target="_blank">mysql 全文模糊查找 便捷解决方案</a> <span class="text-muted">alxw4616</span> <a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a> <div>mysql 全文模糊查找 便捷解决方案 2013/6/14 by 半仙 alxw4616@Msn.com 目的: 项目需求实现模糊查找. 原则: 查询不能超过 1秒. 问题: 目标表中有超过1千万条记录. 使用like '%str%' 进行模糊查询无法达到性能需求. 解决方案: 使用mysql全文索引. 1.全文索引 : MySQL支持全文索引和搜索功能。MySQL中的全文索</div> </li> <li><a href="/article/1198.htm" title="自定义数据结构 链表(单项 ,双向,环形)" target="_blank">自定义数据结构 链表(单项 ,双向,环形)</a> <span class="text-muted">百合不是茶</span> <a class="tag" taget="_blank" href="/search/%E5%8D%95%E9%A1%B9%E9%93%BE%E8%A1%A8/1.htm">单项链表</a><a class="tag" taget="_blank" href="/search/%E5%8F%8C%E5%90%91%E9%93%BE%E8%A1%A8/1.htm">双向链表</a> <div>     链表与动态数组的实现方式差不多,    数组适合快速删除某个元素    链表则可以快速的保存数组并且可以是不连续的       单项链表;数据从第一个指向最后一个   实现代码:        //定义动态链表 clas</div> </li> <li><a href="/article/1325.htm" title="threadLocal实例" target="_blank">threadLocal实例</a> <span class="text-muted">bijian1013</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/thread/1.htm">thread</a><a class="tag" taget="_blank" href="/search/java%E5%A4%9A%E7%BA%BF%E7%A8%8B/1.htm">java多线程</a><a class="tag" taget="_blank" href="/search/threadLocal/1.htm">threadLocal</a> <div>实例1: package com.bijian.thread; public class MyThread extends Thread { private static ThreadLocal tl = new ThreadLocal() { protected synchronized Object initialValue() { return new Inte</div> </li> <li><a href="/article/1452.htm" title="activemq安全设置—设置admin的用户名和密码" target="_blank">activemq安全设置—设置admin的用户名和密码</a> <span class="text-muted">bijian1013</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/activemq/1.htm">activemq</a> <div>        ActiveMQ使用的是jetty服务器, 打开conf/jetty.xml文件,找到 <bean id="adminSecurityConstraint" class="org.eclipse.jetty.util.security.Constraint"> <p</div> </li> <li><a href="/article/1579.htm" title="【Java范型一】Java范型详解之范型集合和自定义范型类" target="_blank">【Java范型一】Java范型详解之范型集合和自定义范型类</a> <span class="text-muted">bit1129</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>本文详细介绍Java的范型,写一篇关于范型的博客原因有两个,前几天要写个范型方法(返回值根据传入的类型而定),竟然想了半天,最后还是从网上找了个范型方法的写法;再者,前一段时间在看Gson, Gson这个JSON包的精华就在于对范型的优雅简单的处理,看它的源代码就比较迷糊,只其然不知其所以然。所以,还是花点时间系统的整理总结下范型吧。   范型内容 范型集合类 范型类 </div> </li> <li><a href="/article/1706.htm" title="【HBase十二】HFile存储的是一个列族的数据" target="_blank">【HBase十二】HFile存储的是一个列族的数据</a> <span class="text-muted">bit1129</span> <a class="tag" taget="_blank" href="/search/hbase/1.htm">hbase</a> <div>在HBase中,每个HFile存储的是一个表中一个列族的数据,也就是说,当一个表中有多个列簇时,针对每个列簇插入数据,最后产生的数据是多个HFile,每个对应一个列族,通过如下操作验证   1. 建立一个有两个列族的表   create 'members','colfam1','colfam2'   2. 在members表中的colfam1中插入50*5</div> </li> <li><a href="/article/1833.htm" title="Nginx 官方一个配置实例" target="_blank">Nginx 官方一个配置实例</a> <span class="text-muted">ronin47</span> <a class="tag" taget="_blank" href="/search/nginx+%E9%85%8D%E7%BD%AE%E5%AE%9E%E4%BE%8B/1.htm">nginx 配置实例</a> <div>user www www; worker_processes 5; error_log logs/error.log; pid logs/nginx.pid; worker_rlimit_nofile 8192; events { worker_connections 4096;} http { include conf/mim</div> </li> <li><a href="/article/1960.htm" title="java-15.输入一颗二元查找树,将该树转换为它的镜像, 即在转换后的二元查找树中,左子树的结点都大于右子树的结点。 用递归和循环" target="_blank">java-15.输入一颗二元查找树,将该树转换为它的镜像, 即在转换后的二元查找树中,左子树的结点都大于右子树的结点。 用递归和循环</a> <span class="text-muted">bylijinnan</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div> //use recursion public static void mirrorHelp1(Node node){ if(node==null)return; swapChild(node); mirrorHelp1(node.getLeft()); mirrorHelp1(node.getRight()); } //use no recursion bu</div> </li> <li><a href="/article/2087.htm" title="返回null还是empty" target="_blank">返回null还是empty</a> <span class="text-muted">bylijinnan</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/apache/1.htm">apache</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/%E7%BC%96%E7%A8%8B/1.htm">编程</a> <div>第一个问题,函数是应当返回null还是长度为0的数组(或集合)? 第二个问题,函数输入参数不当时,是异常还是返回null? 先看第一个问题 有两个约定我觉得应当遵守: 1.返回零长度的数组或集合而不是null(详见《Effective Java》) 理由就是,如果返回empty,就可以少了很多not-null判断: List<Person> list</div> </li> <li><a href="/article/2214.htm" title="[科技与项目]工作流厂商的战略机遇期" target="_blank">[科技与项目]工作流厂商的战略机遇期</a> <span class="text-muted">comsci</span> <a class="tag" taget="_blank" href="/search/%E5%B7%A5%E4%BD%9C%E6%B5%81/1.htm">工作流</a> <div>       在新的战略平衡形成之前,这里有一个短暂的战略机遇期,只有大概最短6年,最长14年的时间,这段时间就好像我们森林里面的小动物,在秋天中,必须抓紧一切时间存储坚果一样,否则无法熬过漫长的冬季。。。。         在微软,甲骨文,谷歌,IBM,SONY</div> </li> <li><a href="/article/2341.htm" title="过度设计-举例" target="_blank">过度设计-举例</a> <span class="text-muted">cuityang</span> <a class="tag" taget="_blank" href="/search/%E8%BF%87%E5%BA%A6%E8%AE%BE%E8%AE%A1/1.htm">过度设计</a> <div>过度设计,需要更多设计时间和测试成本,如无必要,还是尽量简洁一些好。 未来的事情,比如 访问量,比如数据库的容量,比如是否需要改成分布式  都是无法预料的 再举一个例子,对闰年的判断逻辑:   1、 if($Year%4==0) return True; else return Fasle;   2、if (   ($Year%4==0  &am</div> </li> <li><a href="/article/2468.htm" title="java进阶,《Java性能优化权威指南》试读" target="_blank">java进阶,《Java性能优化权威指南》试读</a> <span class="text-muted">darkblue086</span> <a class="tag" taget="_blank" href="/search/java%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/1.htm">java性能优化</a> <div>记得当年随意读了微软出版社的.NET 2.0应用程序调试,才发现调试器如此强大,应用程序开发调试其实真的简单了很多,不仅仅是因为里面介绍了很多调试器工具的使用,更是因为里面寻找问题并重现问题的思想让我震撼,时隔多年,Java已经如日中天,成为许多大型企业应用的首选,而今天,这本《Java性能优化权威指南》让我再次找到了这种感觉,从不经意的开发过程让我刮目相看,原来性能调优不是简单地看看热点在哪里,</div> </li> <li><a href="/article/2595.htm" title="网络学习笔记初识OSI七层模型与TCP协议" target="_blank">网络学习笔记初识OSI七层模型与TCP协议</a> <span class="text-muted">dcj3sjt126com</span> <a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/1.htm">学习笔记</a> <div>  协议:在计算机网络中通信各方面所达成的、共同遵守和执行的一系列约定   计算机网络的体系结构:计算机网络的层次结构和各层协议的集合。   两类服务:   面向连接的服务通信双方在通信之前先建立某种状态,并在通信过程中维持这种状态的变化,同时为服务对象预先分配一定的资源。这种服务叫做面向连接的服务。   面向无连接的服务通信双方在通信前后不建立和维持状态,不为服务对象</div> </li> <li><a href="/article/2722.htm" title="mac中用命令行运行mysql" target="_blank">mac中用命令行运行mysql</a> <span class="text-muted">dcj3sjt126com</span> <a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a><a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a><a class="tag" taget="_blank" href="/search/mac/1.htm">mac</a> <div>参考这篇博客:http://www.cnblogs.com/macro-cheng/archive/2011/10/25/mysql-001.html  感觉workbench不好用(有点先入为主了)。 1,安装mysql 在mysql的官方网站下载 mysql 5.5.23 http://www.mysql.com/downloads/mysql/,根据我的机器的配置情况选择了64</div> </li> <li><a href="/article/2849.htm" title="MongDB查询(1)——基本查询[五]" target="_blank">MongDB查询(1)——基本查询[五]</a> <span class="text-muted">eksliang</span> <a class="tag" taget="_blank" href="/search/mongodb/1.htm">mongodb</a><a class="tag" taget="_blank" href="/search/mongodb+%E6%9F%A5%E8%AF%A2/1.htm">mongodb 查询</a><a class="tag" taget="_blank" href="/search/mongodb+find/1.htm">mongodb find</a> <div>MongDB查询 转载请出自出处:http://eksliang.iteye.com/blog/2174452 一、find简介 MongoDB中使用find来进行查询。 API:如下 function ( query , fields , limit , skip, batchSize, options ){.....}  参数含义: query:查询参数 fie</div> </li> <li><a href="/article/2976.htm" title="base64,加密解密 经融加密,对接" target="_blank">base64,加密解密 经融加密,对接</a> <span class="text-muted">y806839048</span> <a class="tag" taget="_blank" href="/search/%E7%BB%8F%E8%9E%8D%E5%8A%A0%E5%AF%86/1.htm">经融加密</a><a class="tag" taget="_blank" href="/search/%E5%AF%B9%E6%8E%A5/1.htm">对接</a> <div>String data0 = new String(Base64.encode(bo.getPaymentResult().getBytes(("GBK")))); String data1 = new String(Base64.decode(data0.toCharArray()),"GBK"); // 注意编码格式,注意用于加密,解密的要是同</div> </li> <li><a href="/article/3103.htm" title="JavaWeb之JSP概述" target="_blank">JavaWeb之JSP概述</a> <span class="text-muted">ihuning</span> <a class="tag" taget="_blank" href="/search/javaweb/1.htm">javaweb</a> <div>  什么是JSP?为什么使用JSP? JSP表示Java Server Page,即嵌有Java代码的HTML页面。使用JSP是因为在HTML中嵌入Java代码比在Java代码中拼接字符串更容易、更方便和更高效。   JSP起源    在很多动态网页中,绝大部分内容都是固定不变的,只有局部内容需要动态产生和改变。  如果使用Servl</div> </li> <li><a href="/article/3230.htm" title="apple watch 指南" target="_blank">apple watch 指南</a> <span class="text-muted">啸笑天</span> <a class="tag" taget="_blank" href="/search/apple/1.htm">apple</a> <div>1. 文档 WatchKit Programming Guide(中译在线版 By @CocoaChina) 译文 译者 原文 概览 - 开始为 Apple Watch 进行开发 @星夜暮晨 Overview - Developing for Apple Watch 概览 - 配置 Xcode 项目 - Overview - Configuring Yo</div> </li> <li><a href="/article/3357.htm" title="java经典的基础题目" target="_blank">java经典的基础题目</a> <span class="text-muted">macroli</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E7%BC%96%E7%A8%8B/1.htm">编程</a> <div>1.列举出 10个JAVA语言的优势 a:免费,开源,跨平台(平台独立性),简单易用,功能完善,面向对象,健壮性,多线程,结构中立,企业应用的成熟平台, 无线应用 2.列举出JAVA中10个面向对象编程的术语 a:包,类,接口,对象,属性,方法,构造器,继承,封装,多态,抽象,范型 3.列举出JAVA中6个比较常用的包 Java.lang;java.util;java.io;java.sql;ja</div> </li> <li><a href="/article/3484.htm" title="你所不知道神奇的js replace正则表达式" target="_blank">你所不知道神奇的js replace正则表达式</a> <span class="text-muted">qiaolevip</span> <a class="tag" taget="_blank" href="/search/%E6%AF%8F%E5%A4%A9%E8%BF%9B%E6%AD%A5%E4%B8%80%E7%82%B9%E7%82%B9/1.htm">每天进步一点点</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0%E6%B0%B8%E6%97%A0%E6%AD%A2%E5%A2%83/1.htm">学习永无止境</a><a class="tag" taget="_blank" href="/search/%E7%BA%B5%E8%A7%82%E5%8D%83%E8%B1%A1/1.htm">纵观千象</a><a class="tag" taget="_blank" href="/search/regex/1.htm">regex</a> <div>var v = 'C9CFBAA3CAD0'; console.log(v); var arr = v.split(''); for (var i = 0; i < arr.length; i ++) { if (i % 2 == 0) arr[i] = '%' + arr[i]; } console.log(arr.join('')); console.log(v.r</div> </li> <li><a href="/article/3611.htm" title="[一起学Hive]之十五-分析Hive表和分区的统计信息(Statistics)" target="_blank">[一起学Hive]之十五-分析Hive表和分区的统计信息(Statistics)</a> <span class="text-muted">superlxw1234</span> <a class="tag" taget="_blank" href="/search/hive/1.htm">hive</a><a class="tag" taget="_blank" href="/search/hive%E5%88%86%E6%9E%90%E8%A1%A8/1.htm">hive分析表</a><a class="tag" taget="_blank" href="/search/hive%E7%BB%9F%E8%AE%A1%E4%BF%A1%E6%81%AF/1.htm">hive统计信息</a><a class="tag" taget="_blank" href="/search/hive+Statistics/1.htm">hive Statistics</a> <div>关键字:Hive统计信息、分析Hive表、Hive Statistics   类似于Oracle的分析表,Hive中也提供了分析表和分区的功能,通过自动和手动分析Hive表,将Hive表的一些统计信息存储到元数据中。   表和分区的统计信息主要包括:行数、文件数、原始数据大小、所占存储大小、最后一次操作时间等;   14.1 新表的统计信息 对于一个新创建</div> </li> <li><a href="/article/3738.htm" title="Spring Boot 1.2.5 发布" target="_blank">Spring Boot 1.2.5 发布</a> <span class="text-muted">wiselyman</span> <a class="tag" taget="_blank" href="/search/spring+boot/1.htm">spring boot</a> <div>    Spring Boot 1.2.5已在7月2日发布,现在可以从spring的maven库和maven中心库下载。   这个版本是一个维护的发布版,主要是一些修复以及将Spring的依赖提升至4.1.7(包含重要的安全修复)。   官方建议所有的Spring Boot用户升级这个版本。   项目首页 | 源</div> </li> </ul> </div> </div> </div> <div> <div class="container"> <div class="indexes"> <strong>按字母分类:</strong> <a href="/tags/A/1.htm" target="_blank">A</a><a href="/tags/B/1.htm" target="_blank">B</a><a href="/tags/C/1.htm" target="_blank">C</a><a href="/tags/D/1.htm" target="_blank">D</a><a href="/tags/E/1.htm" target="_blank">E</a><a href="/tags/F/1.htm" target="_blank">F</a><a href="/tags/G/1.htm" target="_blank">G</a><a href="/tags/H/1.htm" target="_blank">H</a><a href="/tags/I/1.htm" target="_blank">I</a><a href="/tags/J/1.htm" target="_blank">J</a><a href="/tags/K/1.htm" target="_blank">K</a><a href="/tags/L/1.htm" target="_blank">L</a><a href="/tags/M/1.htm" target="_blank">M</a><a href="/tags/N/1.htm" target="_blank">N</a><a href="/tags/O/1.htm" target="_blank">O</a><a href="/tags/P/1.htm" target="_blank">P</a><a href="/tags/Q/1.htm" target="_blank">Q</a><a href="/tags/R/1.htm" target="_blank">R</a><a href="/tags/S/1.htm" target="_blank">S</a><a href="/tags/T/1.htm" target="_blank">T</a><a href="/tags/U/1.htm" target="_blank">U</a><a href="/tags/V/1.htm" target="_blank">V</a><a href="/tags/W/1.htm" target="_blank">W</a><a href="/tags/X/1.htm" target="_blank">X</a><a href="/tags/Y/1.htm" target="_blank">Y</a><a href="/tags/Z/1.htm" target="_blank">Z</a><a href="/tags/0/1.htm" target="_blank">其他</a> </div> </div> </div> <footer id="footer" class="mb30 mt30"> <div class="container"> <div class="footBglm"> <a target="_blank" href="/">首页</a> - <a target="_blank" href="/custom/about.htm">关于我们</a> - <a target="_blank" href="/search/Java/1.htm">站内搜索</a> - <a target="_blank" href="/sitemap.txt">Sitemap</a> - <a target="_blank" href="/custom/delete.htm">侵权投诉</a> </div> <div class="copyright">版权所有 IT知识库 CopyRight © 2000-2050 E-COM-NET.COM , All Rights Reserved. <!-- <a href="https://beian.miit.gov.cn/" rel="nofollow" target="_blank">京ICP备09083238号</a><br>--> </div> </div> </footer> <!-- 代码高亮 --> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shCore.js"></script> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shLegacy.js"></script> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shAutoloader.js"></script> <link type="text/css" rel="stylesheet" href="/static/syntaxhighlighter/styles/shCoreDefault.css"/> <script type="text/javascript" src="/static/syntaxhighlighter/src/my_start_1.js"></script> </body> </html><script data-cfasync="false" src="/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js"></script>