前端工程化

2 前端工程化

2.1 支持环境 Node

1
2
3
4
node.js JavaScript的解释器

用于后端开发
作为前端工具的支持环境

1554218423001

2.2 NPM 包管理工具

1554218780692

1554218854247

1
2
3
4
包管理工具
集成在node.js中,不需要单独下载

前端的一切资源都可以都过npm下载 包括 各种前端工具(webpack\grunt...) 各种前端资源(jquery\bootstrap...)
1
2
3
4
npm install 包名        本地安装(本项目目录) (资源类)
npm install -g 包名 全局安装(命令行工具)
npm uninstall 包名 删掉本地的包
npm uninstall 包名 -g 删除全局安装的包
1
2
3
#项目初始化
npm init
创建一个package.json 里面是对项目的描述,指定依赖
1
2
项目中的node_moudules 目录 不需要上传
运行 npm install 自动安装项目所有的依赖(存在package.json
1
2
npm install 包 --save 下载包的同时,加入到package.json中的 `dependencies`
npm install 包 --save-dev 下载包的同时,加入到package.json中的 `devDependencies` 开发阶段的依赖

1554218921391

1554219511727

安装依赖

1554219661526

开发和正式

1554219728681

2.3 模块化工具

  • webpack
  • Browserify

把前端所有的资源当做模块,向引入模块一样去使用

1554219935181

2.4 自动化工具

集成各种应用:代码压缩、图片压缩、编译sass….

  • grunt
  • gulp
  • webpack

element

1554273819879

1554273891994

vuex

1554274224152

3 Vue生成器

集成了webpack、以及其他各种需要的工具

3.1 安装

1
2
npm install -g @vue/cli   安装3.x
npm install -g vue/cli 安装的2.x

3.2 使用

可视化vue ui

1
vue create 项目名称   自动生成项目的目录

创建create vue 项目名

选择自定义

img

编译器

img

img

TypeScript语言超级

pwa项目优化,架构师

img

Router路由器

Vuex状态管理器

css Pre-processors预编译器

img

单独的和集成到一个文件中

img

3

img

img

1554221204905

3.3 包含的东西

1
2
3
4
5
6
7
8
9
10
webpack  
babel 把ES6编译成ES5
eslint 代码语法规范
TypeScript 负责把TypeScript编译成JavaScript
Router(vue-router Vue全家桶成员) 路由
Vuex(Vue全家桶成员) vue状态管理
CSS Pre-processors CSS预处理 会让你再次选择器(SASS、LESS、Stylus...)
Linter / Formatter 语法检查
Unit Testing 单元测试
E2E Testing 端到端测试

2.4 命令打包

1
2
npm run serve  临时编译,创建临时服务器  loacalhost:8080
npm run build 编译,生成dist目录

4. 前端的集成环境 WebStorm

5 项目目录结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
dist: 打包的项目目录(打包后会生成)
|- node_modules

|- public
|- index.html
|- assets 静态文件 图片、字体
|- src
|- assets 资源
|- components 普通组件(局部)个体
|- HelloWorld.vue
|- views 页面组件 页面
|- Home.vue
|- About.vue
|- main.js 入口
|- App.vue 总体结构组件(根组件)
|- router.js 路由设置
|- store.js 状态管理
|- pageage.json
|-vue.config.js 改端口

main.js

1554277133323

3.*.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<template>
<!-- 模板区域 -->
router-link渲染为a标签
</template>
<script>
// 逻辑代码区域
// export default {} 与 script标签 绑定出现
export default {
导出该组件的数据,方法,计算,监听,生命周期构造等
}
</script>
<style scoped>
/* 样式区域 */
/* scoped表示这里的样式只适用于组件内部, scoped与style绑定出现 */
</style>

router.js

router-link替换router-view

router提供了2个标签一个是router-link一个是router-view

img

替换

img

router-link样式

img

路由别名(一级路由)

1
2
3
4
5
6
7
8
<router-link :to="{name: 'one'}">One</router-link>

{
// 一级路由, 在根组件中被渲染, 替换根组件的<router-view/>标签
path: '/one-view',
name: 'one', //别名
component: () => import('./views/OneView.vue')
},

二级路由

1
2
3
4
5
6
7
8
9
10
{
// 二级路由, 在根组件中被渲染, 替换根组件的<router-view/>标签
path: '/one-view/one-detail',
component: () => import('./views/OneDetail.vue'),
// 子路由, 在所属路由指向的组件中被渲染, 替换该组件(OneDetail)的<router-view/>标签
children: [{
path: 'show',
component: () => import('./components/OneShow.vue')
}]
},
$router.push
1
2
3
4
5
6
7
8
export default {
methods: {
// 完成router的逻辑转跳
detail() {
this.$router.push("/one-view/one-detail")
}
}
}

子路由children

父组件层 $router.go(-1)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<template>
<div id="one-detail">
<div @click="back">返回</div>
<div @click="show">显示</div>
<div class="box">
<!-- 会被替换为该路由下的子路由指向的组件 -->
<router-view />
</div>
</div>
</template>
<script>
export default {
methods: {
back() {
// router采用history方式访问上一级
this.$router.go(-1)
},
show() {
// router的逻辑转跳
this.$router.push('/one-view/one-detail/show')
}
}
}
</script>
路由层
1
2
3
4
5
6
7
8
9
10
{
// 二级路由, 在根组件中被渲染, 替换根组件的<router-view/>标签
path: '/one-view/one-detail',
component: () => import('./views/OneDetail.vue'),
// 子路由, 在所属路由指向的组件中被渲染, 替换该组件(OneDetail)的<router-view/>标签
children: [{
path: 'show',
component: () => import('./components/OneShow.vue')
}]
},
子路由
1
2
3
4
5
<template>
<div id="one-show">
one show one show one show one show one show one show one show one show one show one show one show one show one show one show one show
</div>
</template>

1554283980982

状态管理器vuex

img

state,mutations,actions

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 状态管理
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
// 在任何一个组件中,均可以通过this.$store.state.msg访问msg的数据
// state永远只能拥有一种状态值
state: {
msg: "状态管理器"
},
// 让state拥有多个状态值
mutations: {
// 在一个一个组件纵,均可以通过this.$store.commit('setMsg', new_msg)来修改state中的msg
setMsg(state, new_msg) {
state.msg = new_msg
}
},
// 让mutations拥有多个状态值
actions: {

}
})

mutations修改

1554345368124

选择器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<template>
<div id="two-Detail">
<h1>two-Detail</h1>
{{ msg }}
<div @click='divClick' :class="{active: isAble}" ref='div_box'>vue选择器</div>
</div>
</template>
<script>
export default {
data() {
return {
msg: "",
isAble: false
}
},
methods: {
divClick() {
this.isAble = !this.isAble;
// 在vue逻辑中,通过$refs可以获取页面标签(vue的选择器)
let div = this.$refs.div_box;
div.style.height = "200px"
}
},
// 生命周期钩子
mounted() {
this.msg = this.$store.state.msg
}
}
</script>
<style scoped>
.active {
background-color: orange
}
</style>

动画

子元素动画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<template>
<div id="three-box" :class="{move: isMove}" @mouseover="moving" @mouseout="moved">
<h3>{{ val.title }}</h3>
<p>{{ val.info }}</p>
</div>
</template>
<script>
export default {
props: ['val'],
data() {
return {
isMove: false
}
},
methods: {
moving() {
this.isMove = true;
},
moved() {
this.isMove = false;
}
}
}
</script>
<style scoped>
#three-box {
width: 120px;
height: 200px;
border: 3px solid red;
float: left;
transition: .3s;
}

.move {
transform: translateY(-10px);
}
</style>

父元素动画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
<template>
<div id="three-view">
<div class="boxs">
<ThreeBox v-for="(v, i) in box_list" :key='i' :val='v'></ThreeBox>
</div>
<div>
<button @click="isShow = !isShow">切换</button>
</div>
<!-- 将要做动画的标签用transition标签嵌套 -->
<!-- transition标签结合v-show|v-if条件指令完成动画 -->
<transition name="p_show">
<p v-show='isShow'>你是p</p>
</transition>
</div>
</template>
<script>
import ThreeBox from '../components/ThreeBox.vue'
export default {
data() {
return {
isShow: false,
box_list: [{
title: "苹果",
info: "美国公司"
},
{
title: "华为",
info: "中国公司"
},
{
title: "诺基亚",
info: "洛基亚"
},
{
title: "苹果",
info: "美国公司"
},
{
title: "华为",
info: "中国公司"
},
{
title: "诺基亚",
info: "洛基亚"
}
]
}
},
components: {
ThreeBox,
},
methods: {

},
mounted: {
// ajax请求数据
// this.box_list = ?
}
}
</script>
<style scoped>
#three-view {
width: 100%;
height: 500px;
background-color: brown
}

.boxs:after {
content: "";
display: block;
clear: both;
}

p {
background-color: orange
}

/*此动画针对于显隐切换*/
.p_show-enter-active,
.p_show-leave-active {
transition: 1s
}

.p_show-enter,
.p_show-leave-active {
opacity: 0
}
</style>

插槽

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<template>
<div id="four-view">
<!-- 被FourBox包裹的均属于子组件 -->
<FourBox>
<!-- 子组件只是需要渲染父组件的内容,可以通过插槽失去数据的传递 -->
<!-- 父组件写在子组件标签内部,用全局属性slot与子组件内部插槽name属性一一对应 -->
<div slot='st' @click="divClick">
<span>{{ msg }}</span>
<span>{{ msg }}</span>
</div>
</FourBox>
</div>
</template>
<script>
import FourBox from '../components/FourBox.vue'
export default {
data() {
return {
msg: "four 信息"
}
},
components: {
FourBox
},
methods: {
// 子组件的事件可以在父组件中实现
divClick() {
this.msg = "插槽 信息"
}
}
}
</script>
<style scoped>
</style>

数据持久化

1554348317971

在main.js里面创建VueCookie(全局)

1554348576794

局部

1554348606379

拿到cooke值和修改 生命周期mounted()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<template>
<div id="five-view">
{{ str }}
<div>
<input type="text" v-model="val">
<button @click="btnClick">修改数据</button>
</div>
</div>
</template>
<script>
// 局部使用vue-cookie
import Vue from 'vue'
import VueCookie from 'vue-cookie'
Vue.use(VueCookie)

export default {
data() {
return {
// cookie中有val字段值,将该值赋值给str,否则将abc赋值str
str: this.$cookie.get('val') ? this.$cookie.get('val') : 'abc',
val: ""
}
},
methods: {
// 修改完数据后,重新刷新页面数据为上一次修改的结果
// 数据的持久化
btnClick() {
if (this.val) {
this.str = this.val;
// 持久化存储val的值到cookie中
this.$cookie.set('val', this.val)
}
}
},
mounted() {
// 通过局部设置的VueCookie可以设置和访问cookie中的值
// var res = VueCookie.get('name');

// 通过全局设置的原型属性$cookie也可以设置和访问cookie中的值
// var res = this.$cookie.get('name');
// console.log(res);
// this.$cookie.set('name', 'hehe');
// console.log(this.$cookie.get('name'));
// set('key', 'value')对cookie进行设置
// get('key')来去key对应的value值(value永远是字符串形式)

// cookie默认字段的生命周期同浏览器窗口(不是标签页被关闭,是浏览器大退)
}
}
</script>
<style scoped>
</style>

前后台ajax请求

1554349380041

配置全局

1
2
3
4
5
// 安装 axios(ajax)的命令
// npm install axios--save
// 为项目配置全局axios
import Axios from 'axios'
Vue.prototype.$ajax = Axios

举列子flask后台

1554349654116

前台ajxa

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<template>
<div id="six-view">
<h1>{{ title }}</h1>
<div>
<input type="text" v-model='usr'>
</div>
<div>
<input type="password" v-model='ps'>
</div>
<button @click="loginAction">登录</button>
</div>
</template>
<script>
export default {
data() {
return {
title: "登录",
usr: "",
ps: ""
}
},
methods: {
// 通过ajax请求后台数据
loginAction() {
// 将vue对象this保留到_this中,那么在this发生重指向后,还可以拿到vue实例
let _this = this
this.$ajax({
method: 'post',
url: 'http://127.0.0.1:5000/loginAction',
params: {
usr: this.usr,
ps: this.ps
}
}).then(function(res) {
// this代表的是回调then这个方法的调用者(axios插件),也就是发生了this的重指向
// 要更新页面的title变量,title属于vue实例
// res为回调的对象,该对象的data属性就是后台返回的数据
_this.title = res.data
}).catch(function(err) {
console.log(err)
})
}
}
}
</script>
<style scoped>
</style>

6 Vue全家桶

1
2
3
4
5
6
7
8
vue 本身
vue-router 路由 路径和组件一一对应
vuex 状态管理 兄弟组件跟全局的单例相似(再任何一个类里面拿到这个对象都是同一个)
vue-ssr 服务端渲染
element-ui vue样式组件库
vue-cookie 持续化存储
ajax: axios 前后台交互
插吵 把父级里面的动西传递给子集

pycharm启动wue项目

1554278364913

图灵python大海老师 wechat
python分享公众号
坚持原创技术分享,您的支持将鼓励我继续创作!