抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

1.vue-cli3.0+的创建

vue-create文档: https://cli.vuejs.org/zh/guide/creating-a-project.html#vue-create

​ 由于官网Vue教程是2.x,且很多地方教你创建第一个项目的时候使用的是vue init webpack my-project命令。而最新的包括现在项目组里正在用的,已经是vue-cli3.0+版本,创建有所不同,所以开头先提以下。

安装(假设已经安装好node)

1
npm install -g @vue/cli

-g 的意思是全局安装,否则就会在当前目录给你新建node_modules 的目录和package-lock.json文件

创建项目

1
vue create ProjectName

本地调试启动(不在是npm run dev了)

1
npm run serve

2. 创建.eslintrc.js文件

eslint中文文档: http://eslint.cn/docs/user-guide/configuring

如果你不想被规则逼疯的话,先创建一个吧。(禁用了依然还是报错,没办法,只有给他加个规则了)

不然肯定会疯掉的,例如不允许写alert,不允许写console.log!行尾要加’;’等等。很麻烦,先创建一个基本规则,使用默认的配置表。

使用vue create ProjectName默认是没有这个文件,需要自己创建一个。

先引用(如果 package.json已有就忽略这一步)

1
npm install eslint --save-dev

在项目的根目录下

1
cd node_modules/.bin

创建默认规则

1
eslint --init  # 如命令不识别就./eslint --init

除了eslint,其他都默认即可

将node_modules/.bin目录下生成的 .eslintrc.js 拷贝到项目根目录下

1
cp .eslintrc.js ../../ 

如果是windows直接复制粘贴就好,注意 . 开头文件是隐藏文件。

image.png

3.vue.config.js的使用

vue.conf.js官方文档: https://cli.vuejs.org/zh/config/#vue-config-js

使用vue create创建,在根目录下只有babel.conf.js目录,也就没有conf目录和vue.conf.js文件。不要慌,手动在根目录下新建一个vue.conf.js文件。

添加下常用配置,例如本地开发通常会使用的代理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
module.exports = {
devServer: {
host: '127.0.0.1',/*只用来本地开发,实际部署也是,使用nginx代理,组内想访问可以设成0.0.0.0*/
port: '8080', /*监听端口*/
https: false, /*是否使用https*/
hotOnly: false, /*热更新,webpack已经实现热更新,这个关掉*/
proxy: {
'/api': { /*匹配到 /api 路径的时候走这个代理*/
target: 'http://127.0.0.1:8000', /*转发地址*/
ws: true,
changeOrigin: true,
pathRewrite: {'^/api':'/api/vue'} /*路径替换*/
},
}
},
};

pathRewrite: {'^/api':'/api/vue'} 这条规则带上, /api/xxx请求,最后请求实际变成 /api/vue/xxx

因为使用vue+django,想让vue所有接口都是 /api/xxx 格式,凡是带api的请求都转发到本地另一个端口号--django监听的端口,并且django内部已有很多规则,/api/vue, /api/vue2这样,因此在vue配置加路径替换。

3.*.Vue文件解读

html

html语句都写在了<template></template>中,

在templae里编写有一些注意点

  • 只能写一个最顶层,其余内容都在他下面

✅正确用法

1
2
3
<template>
<div></div>
</template>

❌错误用法

1
2
3
4
<template>
<div></div>
<div></div>
</template>
  • 不能使用<a href="/xx">

❌错误用法

1
2
3
4
5
<template>
<div>
<a href="/aaa">aaa</a>
</div>
</template>

✅正确用法(具体用法看第5小结)

1
2
3
4
5
6
7
8
<template>
<div>
<div>
<router-link to="/login" class="top_menu" v-if="isLogin">登出</router-link>
</div>
<router-view/>
</div>
</template>
  • 不能在template引用js,css文件。

js

<script></script> 中,关于js的用法,必定会有一个默认执行的方法。

1
2
3
4
5
<script>
export default {
name: 'App'
}
</script>

以上,name属性是必须要有的,需要在router/index.js中引用。

其他内容看下一小结。

css

<style></style>中,关于css的用法,没什么好说的,基本和平常使用一样。

4.methods,mounted,created等的纠葛

<script>下的方法里呢,name是必须的,然后data是初始返回一些vue变量的。

除了这些会看到很多其他属性如methodsmounted 等等,这里面,methodsvue绑定的方法,没调用,就不会执行。

(表格内容来自: https://blog.csdn.net/qq_22227087/article/details/87256833)

其他的,如created, mounted等都统称为生命周期一个页面从加载到渲染到完成,都有对应的属性。

beforecreate 一般使用场景是在加 loading事件 的时候
created 处于loading结束后,还做一些初始化,实现函数自执行(data数据已经初始化,但是DOM结构渲染完成,组件没有加载)
beforemount 处于组件创建完成,但未开始执行操作
mounted 处于发起后端请求,获取数据,配合路由钩子执行操作(DOM渲染完成,组件挂载完成 )
beforeupdate 处于数据更新的前
updated 处于数据更新的后
beforeDestroy 当前组件还在的时候,想删除组件
destroyed 当前组件已被销毁,清空相关内容

其他还有

computed 计算属性,也可以理解为一个方法。其中计算的结果如果不发生改变就不会触发,且必须返回一个值并在DOM中绑定的才能取得值。他可以自动获取数据的改变。
watched 手动定义的所需监听的值,不同的数据可以在其中多次定义监听值,这时会消耗一定性能,他并不能像computed那样自动改变。

5.如何做路径跳转

vue-router文档: https://router.vuejs.org/zh/installation.html

前面说了template标签内不允许使用带href的a标签。那怎么办?vue内部是使用的router-link标签做的路由跳转,只不过vue自动把他转换成了带href的a标签。

另外,router-link只能用作单页面的跳转,什么是单页面?我的理解就是基于一个App.vue

通常使用<router-link>就必定要定义</router-view>,后者决定了新的元素渲染的位置所在

光有<router-link>还不行,有了地址,但不知道该去找什么文件,还需要配合router/index.js来使用。

一个跳转的案例:

router/index.js

image.png

App.vue

image.png

components/HelloWorld.vue

image.png

效果

image.png

image.png

6. App.vue

相比components下的vue文件,app.vue比较特殊,姑且先看作是整体页面布局的根文件吧。

例如以下,在App.vue使用router-linke定义了跳转。

image.png

并且在idcontentdiv中添加了router-view标签,预示跳转内容将在此展示。

image.png

在A.vue中直接定义一个div

image.png

实际效果

image.png

可以看到开头菜单栏,左侧菜单,样式等我都未曾在A.vue定义,都是在App.vue中定义好的,而我在点击上面菜单URL发生变化,idcontentdiv中内容发生变化,其他内容不变。

7.引用第三方组件

安装其他模块,可以直接在package.json里添加,然后执行npm install

也可以直接在项目目录下安装同时让他自动写到package.json文件里去。

例如我想使用axios模块来发请求。

1
npm install axios --save

–save和–save-dev的区别:

​ –save安装后会添加到dependencies下。

​ –save-dev安装后会添加到devDependencies下。

通常都使用–save,除非是只是根本地调试以及构建相关的插件才–save-dev

然后可以通过import的方式来使用了

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
<template>
<div></div>
</template>

<script>
import axios from 'axios'

export default {
name: "Login",
data() {
return {}
},
methods: {
login() {
if (!this.userName) {
this.message = '请输入用户名';
}
if (!this.password) {
this.message = '请输入密码';
}
axios.get('/api/get_token')
.then((response) => {
this.csrf = response.data["token"];
console.log(this.csrf);
})
.catch((error) => {
console.log(error)
});

const post_data = {"username": this.userName, "password": this.BaseFunc.setMd5(this.password)};
axios.post('/api/login', post_data)
.then((response) => {
if (response.data["code"] === 0) {
this.message = '登录成功';
} else this.message = response.data['message']
})
.catch((error) => {
this.message = error
});
}
}
}
</script>

<style scoped>
</style>

8.使用自定义的class或function

前面说了第三方插件的使用,现在说下自定义的class或者function怎么使用。

这里以class为例,我在src下新建了一个common目录,打算把自定义的一些方法写在下面。

例如我新建一个 BaseFunc.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import crypto from "crypto";

export default class BaseFunc {

/*进行md5加密*/
static setMd5(password){
const md5 = crypto.createHash("md5");
md5.update(password);
return md5.digest('hex')
}
/*获取cookie*/
static getCookie(name){
const value = '; ' + document.cookie;
const parts = value.split('; ' + name + '=');
if (parts.length === 2) return parts.pop().split(';').shift();
else return null
}
}

然后在main.js中将它添加为原型属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
import Vue from 'vue'
import App from './App'
import router from './router/index.js'
import BaseFunc from './common/Basefunc' /*这行引入*/

Vue.config.productionTip = false;
// Vue.use(BaseFunc);
Vue.prototype.BaseFunc = BaseFunc; /*这行添加为原型属性*/

new Vue({
render: h => h(App),
router
}).$mount('#app');

这样在项目任何一个vue文件下,都可以使用了

1
this.BaseFunc.setMid() /*像这样*/

9.解决djaogn后台CSRF问题

Django后台为例子,为了防止跨站攻击,有一个CSRF 属性,get方法没有影响,如果是post方法

这里说下前端的解决方法,django为了防止跨站攻击,有一个csrf的属性,我们需要在发送post请求的时候带上csrf来解决访问问题,不然就会报403。

image.png

下面说下怎么结局,首先需要后台提供一个接口能往浏览器cookie传值,然后在发送post请求的时候header里带上X-CSRFToken,值就是本地cookie中的csrftoken

后台代码

1
2
3
4
5
from django.middleware.csrf import get_token

def first_get_token(request):
token = get_token(request)
return JsonResponse({'token': token})

cookie中获取这个值,然后我们在发送pos请求的时候,带到header中,传一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 预先获取csrf_token
axios.get('/api/get_token')
.then((response) => {
this.csrf = response.data["token"];
const post_data = {"username": this.userName, "password": this.BaseFunc.setMd5(this.password)};
const post_header = {headers: {'X-CSRFToken': this.csrf}};
axios.post('/api/login', post_data, post_header)
.then((response) => {
if (response.data["code"] === 0) {
this.message = '登录成功';
this.isLogin = true;
} else this.message = response.data['message']
})
.catch((error) => {
this.message = error
});
})
.catch((error) => {
console.log(error)
});

其中getCookie的代码如下:

1
2
3
4
5
6
getCookie(name){
const value = '; ' + document.cookie;
const parts = value.split('; ' + name + '=');
if (parts.length === 2) return parts.pop().split(';').shift();
else return null
}

评论