Vue框架:7、Node环境搭建,Vue-cli,es6导出、导入语法,跨域问题解决方法,小练习
前端开发之Vue框架
一、Node环境搭建
什么是Node或NodeJS:
- node js是一门后端语言
- JavaScript只能运行在浏览器中,因为浏览器中有他的解释器环境
- 基于谷歌浏览器的v8引擎(js解释器),使它能够运行在操作系统上
- npm -随着node的安装自动安装的
安装Node:
-官方地址:
-http://nodejs.cn/ # 下载对应平台的nodejs解释器
-安装完成会有两个可执行文件
node # 类似python 进入node环境
npm # 类似与pip npm install 安装模块
创建Vue项目使用什么:
创建Vue项目可以使用的工具有两种:
- vue-cli:
- 官网:https://cli.vuejs.org/zh/
- 支持Vue2.x版本和Vue3.x版本
- vite:
- 仅支持Vue3.x及以上版本
- 效率非常高
二、Vue-cli
简介:
vue-cli 就是快速搭建一个 vue 项目的脚手架工具。
使用 vue-cli 可以快速搭建 Vue 开发环境以及对应的 webpack 配置。
# 前端做成项目----》使用工具(vue-cli),创建出vue项目,单页面应用(spa),组件化开发, 把 xx.vue,ts,saas,less-----》编译---》在浏览器中执行
# vue-cli创建项目开发,在项目中开发,最后上线,一定要编译--->纯粹的html,js,css
# 浏览器只能识别 js html css
# vue-cli 工具,使用nodejs写的,要运行,需要node环境
1、Vue-cli创建项目
安装Vue-cli:
方式一:
# cmd 终端运行
npm install -g @vue/cli
方式二:
# 使用cnpm替换npm(淘宝出的工具,下载速度快)
# -g 表示装全局
# --registry=https://registry.npm.taobao.org 指定淘宝镜像
npm install -g cnpm --registry=https://registry.npm.taobao.org
# 以后使用cnpm 代替npm
cnpm install -g @vue/cli
创建项目:
1、cmd控制台就可以输入vue命令
2、使用vue-cli创建项目(提前创建一个目录,用于存放vue项目)
# 速度很慢,等,可以ctrl+c停止 执行npm cache clean --force
# vue ui 使用图形化界面创建项目 ,自己点击即可
vue create 项目名
3、按图操作
2、项目目录介绍
运行项目:
- 使用pycharm找到刚才创建的项目,打开(运行的方式有两种)
- 第一种:下方Terminal输入指令
- npm run serve
- 第二种:使用 pycharm ,点击绿色箭头执行
- 第一种:下方Terminal输入指令
目录介绍:
# vue 项目目录介绍
vue_chi01 # 项目名
node_modules # 非常多第三方模块,以后把项目复制给别人时【上传git要忽略掉】,这个文件夹删掉,很多小文件,项目的依赖,项目要运行,没有它不行 如果没有只需要执行 cnpm install,根据package.json的依赖包,按装好依赖、
public # 文件夹
-favicon.ico # 网站小图标
-index.html # spa 单页面应用,以后整个vue项目都是用这一个html,但你不用动他
src # 文件夹--以后咱们都动这里面的
-assets # 静态资源,以后前端用的图片,js,css。。都放在这里
logo.png # 图片
-components # 以后在这里放组件, xx.vue, 小组件
HelloWorld.vue # 提供的展示组件
-router # 安装了Router,就会有这个文件夹,下面有个index.js
index.js
-store # 安装了Vuex,就会有这个文件夹,下面有个index.js
-index.js
-views # 页面组件
-AboutView.vue
-HomeView.vue
-App.vue # 根组件,new Vue实例管理了 div,以后原来写在div中的东西,现在都写在App.vue
-main.js # 项目的启动入口
.gitignore # git的忽略文件,后面学了git就会了
babel.config.js # bable配置文件,不用动
jsconfig.json # 配置文件,不用动
package.json #不用动,安装了第三方模块,它自动增加
package-lock.json # 锁定文件,忽略掉
README.md # 用户手册
vue.config.js # vue的配置文件
三、es6导入、导出语法
xxx.vue文件:
- 新建xxx.vue项目
- 发现xxx.vue中有三块内容
- template:以后内容都写这里
- style:控制标签的样式
- script:编写JS代码的地方
main.js文件:
- import '别名' from '包的位置'
- 用于导入包(页面组件)
- new Vue({xxx})
- 用于注册页面组件和包
- Vue.'xxx'
- 用于导入各种配置
- 用于导入各种配置
1、导入、导出语法
简介:
从es6开始,js也支持包的导入和导出,类似于python一样导入各种模块
默认导入、导出语法:
# 导出语法:(一般是个对象)
export default {'xxx':'bbb','zzz':'ccc'}
# 导入语法:
import 别名 from '路径' # 导入以后就使用别名
命名导入、导出语法:
# 导出语法:(可导出多个)
export const name = '彭于晏' # 属性
export const add = (a, b) => {
console.log(name)
return a + b
} # 函数(方法)
# 导入语法:
import {name, add} from './aaa/bbb.vue' # 后缀名可以省略
console.log(name)
console.log(add(33, 44))
四、Vue项目编写步骤
1、创建组件
views文件下创建xxx.vue(页面组件),components文件下创建的为小组件(给页面组件用的)
2、导出组件
在script标签中有一个export default配置,用于导出当前组件
<script>
export default {
// 这个可以不写
name: '组件名字',
// 组件内的属性
data() {
return {
xx: '彭于晏'
}
},
// 后面还有很多(函数或其他配置)。。。
}
</script>
3、注册组件
编写的页面组件、小组件需要在别的地方用到(例如小组件要在页面组件中使用)就需要在页面组件的script标签中导入小组件
<script>
//导入 import后面为别名
import index from '组件地址'
// 注册
export default {
components: {
index # 这里填写组件的别名
}
}
</script>
4、使用
注册以后,被导入的组件就可以在当前页面(组件)中使用,写在template标签内
<template>
<index msg='自定义属性'>
</index>
</template>
六、小练习
0、axios的使用(准备工作)
# 1、安装
cnpm install axios -S # 带着-S会自动把当前依赖加入到package.json中
# 2、导入
import axios from 'axios'
# 3、导入模块后即可在script标签内中使用
1、登录功能
页面组件
<template>
<div class="home">
<login></login>
</div>
</template>
<script>
import login from '../components/login.vue'
export default {
name: 'HomeView',
data() {
return {
user: '',
token: ''
}
},
watch: {},
components: {
login
}
}
</script>
登录组件(局部组件)
<template>
<div>
<h1 class="text-center">登录</h1>
<div class="form-group">username:
<p>
<input type="text" v-model="username" class="form-control">
</p>
</div>
<div class="form-group">password:
<p>
<input type="text" v-model="password" class="form-control">
</p>
</div>
<div>
<span class="errorData">{{ error }}</span>
</div>
<div class="form-group">
<button class="btn btn-block btn-info" @click="handleLogin">提交</button>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'user_login',
data() {
return {
username: '',
password: '',
token: '',
error: ''
}
},
methods: {
handleLogin() {
axios.post('http://127.0.0.1:8000/user/login/', {username: this.username, password: this.password}).then(res => {
if (res.data.code == "100") {
this.token = res.data.result
location.href = 'http://192.168.1.187:8080/about'
} else {
this.error = res.data.msg
}
})
}
},
watch: {},
props: {}
}
</script>
<style scoped>
.errorData {
color: red;
}
</style>
2、车的增删查
页面组件
<template>
<div class="about">
<h2>==========汽车汽车管理中心=========</h2>
<div >
==========
<button @click="handleViewPage('car')">车型相关</button>
----
<button @click="handleViewPage('car_factory')">车厂相关</button>
----
<button @click="handleViewPage('distributor')">经销商相关</button>
==========
</div>
<br>
<div>
<component :is="who"></component>
</div>
</div>
</template>
<script>
import car from '../components/car.vue'
import car_factory from '../components/car_factory.vue'
import distributor from '../components/distributor.vue'
export default {
data() {
return {
who: 'car',
}
},
methods: {
handleViewPage(type) {
this.who = type
}
},
components: {
car_factory, distributor, car
}
}
</script>
局部组件(车型信息的增删查)
<template>
<div>
<div v-if="add_car_page">
<p>
<a href="#" @click="handle_add_car">添加新的车型</a>
</p>
<table border="1">
<thead>
<tr class="my_center">
<th class="my_center">编号</th>
<th class="my_center">车名</th>
<th class="my_center">价格</th>
<th class="my_center">生产厂家</th>
<th class="my_center">经销商</th>
<th class="my_center">编辑</th>
</tr>
</thead>
<tbody>
<tr v-for="(car_query,index) in carQuerysetList" class="my_center">
<th>{{ index + 1 }}</th>
<td>{{ car_query.name }}</td>
<td>{{ car_query.price }}</td>
<td>{{ car_query.get_car_factory_detail.name }}</td>
<td>
<span v-for="(item,index) in car_query.get_distributor_list">
<span v-if="index+1 < car_query.get_distributor_list.length">
{{ item.name }},
</span>
<span v-else>
{{ item.name }}
</span>
</span>
</td>
<td>
<a href="#" @click="handle_delete(car_query.pk)">删除</a>
</td>
</tr>
</tbody>
</table>
-------------------------
<button @click="handle_previous_page">上一页</button>
-------
<button @click="handle_next_pag">下一页</button>
-------------------------
</div>
<div v-else>
<add_car @add_car_page_bool="handle_add_car_page_bool"></add_car>
</div>
</div>
</template>
<script>
import axios from "axios";
import add_car from "@/components/add_car";
export default {
name: "car",
data() {
return {
next_pag: '',
previous_page: '',
carQuerysetList: [],
add_car_page: true
}
},
created() {
axios.get('http://127.0.0.1:8000/car/').then(res => {
this.carQuerysetList = res.data.results
this.next_pag = res.data.next
this.previous_page = res.data.previous
})
},
methods: {
handle_up_data() {
axios.get('http://127.0.0.1:8000/car/').then(res => {
this.carQuerysetList = res.data.results
this.next_pag = res.data.next
this.previous_page = res.data.previous
})
},
handle_next_pag() {
if (this.next_pag) {
axios.get(this.next_pag).then(res => {
this.carQuerysetList = res.data.results
this.next_pag = res.data.next
this.previous_page = res.data.previous
})
} else {
alert('已经是最后一页了,不能在翻啦')
}
},
handle_previous_page() {
if (this.previous_page) {
axios.get(this.previous_page).then(res => {
this.carQuerysetList = res.data.results
this.next_pag = res.data.next
this.previous_page = res.data.previous
})
} else {
alert('当前第一页哦,不能在往前啦~~')
}
},
handle_delete(pk) {
let url = 'http://127.0.0.1:8000/car/' + pk + '/'
axios.delete(url).then(res => {
this.handle_up_data()
})
},
handle_add_car() {
this.add_car_page = false
},
handle_add_car_page_bool(bool) {
this.add_car_page = bool
handle_up_data()
}
},
components: {
add_car
}
}
</script>
<style scoped>
.my_center {
text-align: center
}
table {
border-collapse: collapse;
}
</style>
添加车型组件(嵌套车组件内部)
<template>
<div>
<h2 id="h_color">添加新的车型</h2>
<div>车名:
<input type="text" v-model="car_name">
</div>
<div>价格:
<input type="text" v-model="price">
</div>
<div>生产厂家:
<span v-for="factory_queryset in for_car_factory">
<p>
<input type="radio" v-model="car_factory_id" :value="factory_queryset.id">{{ factory_queryset.name }}
</p>
</span>
</div>
<div>销售门店:
<span v-for="distributor_queryset in for_distributor">
<p>
<input type="checkbox" v-model="distributor_id_list"
:value="distributor_queryset.id">{{ distributor_queryset.name }}
</p>
</span>
</div>
<div id="add_car_error_ele">
<span>{{ add_car_error }}</span>
</div>
<button @click="click_add_car">提交</button>
</div>
</template>
<script>
import axios from "axios";
import login from "@/components/login";
export default {
name: "add_car",
data() {
return {
car_name: '',
price: '',
car_factory_id: '',
distributor_id_list: [],
add_car_error: '',
// 循环数据
for_car_factory: [],
for_distributor: []
}
},
created() {
axios.get('http://127.0.0.1:8000/car_factory/').then(res => {
this.for_car_factory = res.data
})
axios.get('http://127.0.0.1:8000/distributor/').then(res => {
this.for_distributor = res.data
})
},
methods: {
click_add_car() {
axios.post('http://127.0.0.1:8000/car/', {
name: this.car_name,
price: this.price,
car_factory: this.car_factory_id,
distributor: this.distributor_id_list
}).then(res => {
if (res.data.msg) {
this.add_car_error = res.data.msg
} else {
alert('车型添加成功!')
this.$emit("add_car_page_bool", true)
}
})
}
}
}
</script>
<style scoped>
#h_color {
color: #8a6d3b;
}
#add_car_error_ele {
color: red;
}
</style>
七、跨域问题的解决
安装模块
pip3.8 install django-cors-headers -i https://pypi.tuna.tsinghua.edu.cn/simple/
注册app
'corsheaders'
注册中间件
'corsheaders.middleware.CorsMiddleware',
添加配置文件
CORS_ORIGIN_ALLOW_ALL = True
# 请求方式
CORS_ALLOW_METHODS = (
'DELETE',
'GET',
'OPTIONS',
'PATCH',
'POST',
'PUT',
'VIEW',
)
# 请求头
CORS_ALLOW_HEADERS = (
'XMLHttpRequest',
'X_FILENAME',
'accept-encoding',
'authorization',
'content-type',
'dnt',
'origin',
'user-agent',
'x-csrftoken',
'x-requested-with',
'Pragma',
'token'
)