前端开发之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:
  • 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、按图操作

Vue框架:7、Node环境搭建,Vue-cli,es6导出、导入语法,跨域问题解决方法,小练习-小白菜博客
Vue框架:7、Node环境搭建,Vue-cli,es6导出、导入语法,跨域问题解决方法,小练习-小白菜博客
Vue框架:7、Node环境搭建,Vue-cli,es6导出、导入语法,跨域问题解决方法,小练习-小白菜博客
Vue框架:7、Node环境搭建,Vue-cli,es6导出、导入语法,跨域问题解决方法,小练习-小白菜博客

2、项目目录介绍

运行项目:

  • 使用pycharm找到刚才创建的项目,打开(运行的方式有两种)
    • 第一种:下方Terminal输入指令
      • npm run serve
    • 第二种:使用 pycharm ,点击绿色箭头执行

目录介绍:

# 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'
)