Vue Cli項目搭建
vue項目需要自建服務器:node
什么是node:
- 用C++語言編寫,用來運行JavaScript語言
- node可以為前端項目提供server (包含了socket)
一、環境搭建
1、官網下載安裝包,傻瓜式安裝:https://nodejs.org/zh-cn/
2、裝完了后在cmd輸入node即可啟動一個命令行交互環境,運行javascript代碼
3、可以更換國內源,加速下載:npm install -g cnpm --registry=https://registry.npm.taobao.org
在更換源后,所有的npm命令都可以替換為cnpm。
改完后npm的源還是國外的源,cnpm的源是淘寶的源。
4、安裝vue cli環境:腳手架,命令行快速創建項目
cnpm install -g @vue/cli
5、安裝腳手架報錯的時候,需要清空緩存處理
npm cache clean --force
二、項目創建
以管理員的身份運行cmd ,否則可能出現一些不必要的麻煩
- 首先cd切換到目標目錄
- 執行:vue create 項目名
- 選擇自定義方式創建項目,選取Router, Vuex插件
- 選擇第二個進入自定義配置:
5. 執行時,會提示下載源,選擇淘寶鏡像即可。(有大寫的選大寫,大寫是建議的選項)
6. 具體配置:上下鍵切換,空格鍵選擇,回車鍵進入下一步
勾選Babel、Router、Vuex、Formatter
Babel :jsES6語法轉換ES5
Router:路由
Vuex:組件數據交互
Formatter:格式化代碼
下一步選Y,接下來的配置都是提示選項有大寫選大寫,沒有默認選第一個配置就行
安裝完后的目錄如下:
三、終端啟動項目
- cd到你的項目:cd vue_proj
- npm run serve
- 訪問:http://localhost:8080/
四、pycharm配置
- 在使用pycharm開發時,打開后,vue文件會有提示需要安裝插件,直接點擊下載即可。
- 如果沒有提示,那么就要在settings的plugins里面搜索vue.js插件,然后安裝。
- 安裝完后需要重啟ide。
- 如果命令行啟動的,在你更改一些代碼后,頁面沒有刷新,這時候在命令行按ctrl+c就可以刷新。但是連續在命令行按兩次ctrl+c就會提示你是否退出,選擇退出或不退就行。
- 需要在pycharm配置npm啟動項:先點擊下拉菜單的Edit,然后點擊小+號,選擇npm
接着需要指定json文件,運行的腳本等。項目名可以起也可以不起。
![]()
上面配置完成后,即可在pycharm啟動項目。
我們把上面的項目可以當作一個模板,以后有需要,直接就把除了node_modules的其他文件夾及文件全部復制到新項目

然后再到相應的目錄下執行:cnpm install

這樣,就會根據電腦環境,項目需求重新下載依賴(node_modules)了。
五、項目目錄

來看一下main.js主腳本文件:
import App from './App.vue' //我可以把它改成下面的形式,@就代表src的絕對路徑 //@后就可以采用相對於src的相對路徑 import App from '@/App.vue' import router from './router' import store from './store' //這個是禁用提示,比如你第一次下載某個app,剛進去會有操作指南 Vue.config.productionTip = false; //下面是ES6的寫法 // new Vue({ // router, // store, // render: h => h(App) // }).$mount('#app'); //改成ES5的看看 new Vue({ el: '#app', router: router, store: store, render: function (h) { return h(App) } });
.vue文件

router.js的路由配置部分:
{ path: '/', name: 'home', // 路由的重定向 redirect: '/home' } { // 一級路由, 在根組件中被渲染, 替換根組件的<router-view/>標簽 path: '/one-view', name: 'one', component: () => import('./views/OneView.vue') } { // 多級路由, 在根組件中被渲染, 替換根組件的<router-view/>標簽 path: '/one-view/one-detail', component: () => import('./views/OneDetail.vue'), // 子路由, 在所屬路由指向的組件中被渲染, 替換該組件(OneDetail)的<router-view/>標簽 children: [{ path: 'show', component: () => import('./components/OneShow.vue') }] }
<router-link to="/">Home</router-link> router-link渲染為a標簽
store.js:vuex
// 在任何一個組件中,均可以通過this.$store.state.msg訪問msg的數據
state: { msg: "狀態管理器" }, // 讓state擁有多個狀態值 mutations: { // 在一個一個組件中,均可以通過this.$store.commit('setMsg', new_msg)來修改state中的msg setMsg(state, new_msg) { state.msg = new_msg } }, // 讓mutations擁有多個狀態值 actions: { }
六、案例
6.1、在根組件中渲染頁面組件
我們要在views中創建一個Main.vue,用來作為主頁:
<template> <div class="main"> <h1>{{ title }}</h1> </div> </template> <script> export default { name: "Main", data:function () { return{ title:'主頁' } } } </script> <!-- 局部的要寫scoped--> <style scoped> .main { /*vh:相對於視窗的高度,那么vw:則是相對於視窗的寬度*/ height: 100vh; /*100vh代表網頁撐滿一個屏*/ background-color: orange; } h1 { margin: 0; /*去除h1標簽自帶的margin邊距*/ color: red; } </style>
接下來我們要考慮的就是如何在頁面中顯示它,怎么現實呢?這時候就要到App.vue文件中去注冊渲染。
<template> <div id="app"> <!--3:注冊完的組件就可以在這里用了--> <Main></Main> </div> </template> <script> // 1:要渲染主頁的內容,首先要在邏輯中導入 import Main from '@/views/Main' export default { //2:導入的是局部組件,需要注冊 components:{ Main:Main } } </script> <!-- 根組件這里不用寫scoped--> <style> html, body { margin: 0; } </style>
先來准備三個文件(局部組件):
Main.vue
<template> <div class="main"> <h1>{{ title }}</h1> </div> </template> <script> export default { name: "Main", data:function () { return{ title:'主頁' } } } </script> <!-- 局部組件要寫scoped--> <style scoped> .main { /*vh:相對於視窗的高度,那么vw:則是相對於視窗的寬度*/ height: 100vh; /*100vh代表網頁撐滿一個屏*/ background-color: orange; } h1 { margin: 0; /*去除h1標簽自帶的margin邊距*/ color: red; } </style>
User.vue
<template> <!--類名一般就是文件名小寫--> <div class="user"> <h1>個人頁</h1> </div> </template> <script> export default { name: "User" } </script> <style scoped> </style>
Goods.vue
<template> <div class="goods"> <h1>商品頁</h1> </div> </template> <script> export default { name: "Goods" } </script> <style scoped> .goods { height: 100vh; background-color: blue; } </style>
接下來要到router.js中注冊
import Vue from 'vue' import Router from 'vue-router' //導入 import Goods from './views/Goods' import User from './views/User' import Main from './views/Main' Vue.use(Router); export default new Router({ mode: 'history', base: process.env.BASE_URL, routes: [ //注冊 { path: '/', name: 'main', component: Main }, { path: '/goods', name: 'goods', component: Goods }, { path: '/user', name: 'user', component: User }, ] })
最后到App.vue中調用:<router-view /> <!--相當於每個頁面要渲染的內容-->
<template> <div id="app"> <!--注冊完的組件就可以在這里用了--> <ul class="nav"> <li> <router-link to="/">主頁</router-link> </li> <li> <router-link to="/goods">商品頁</router-link> </li> <li> <router-link to="/user">個人頁</router-link> </li> </ul> <router-view /> </div> </template> <script> export default { } </script> <!-- 根組件這里不用寫scoped--> <style> html, body,ul,h1 { margin: 0; } .nav { height: 60px; background-color: #d2a1ab; } .nav li{ list-style: none; float: left; /*垂直居中*/ line-height: 60px; width: 120px; /*水平居中*/ text-align: center; } .nav li:hover{ background-color: aqua; } .nav li a{ /*去掉a標簽的下划線*/ text-decoration: none; /*字體大小及樣式*/ font: bold 20px/60px 'STSong'; } ul { list-style: none; } </style>



至此就實現了單頁面的局部組件切換了。
上面我們已經實現了單頁面的切換,那么我們肯定每個頁面都要到后台拿數據,比如我點擊商品頁后就要動態從數據庫獲取信息,然后展示到前端頁面,這就涉及到了前后台的交互問題。
我們以Goods為例來看一下生命周期鈎子
- 鈎子表示一個vue實例從創建到銷毀的這個過程,將這個過程的一些時間節點賦予了對應的鈎子函數
- 鈎子函數: 滿足特點條件被回調的方法
我們在Goods.vue的script中加入鈎子

當點擊商品頁時,會觸發鈎子:

了解了這個,下面我們以django作為后台,來實現以下交互
因為交互是vue自己完成的,我們拿不到csrf的認證字符串,所以直接去配置文件中把這個中間件注釋掉。
然后我們通過axios向后台發請求。
注意,在前后台交互的時候,會產生跨域的問題
通常情況下,A網頁訪問B服務器資源時,不滿足以下三個條件其一就是跨域訪問
1. 協議不同
2. 端口不同
3. 主機不同
安裝django-cors-headers模塊
在settings.py中配置
# 注冊app
INSTALLED_APPS = [
...
'corsheaders'
]
# 添加中間件
MIDDLEWARE = [
...
'corsheaders.middleware.CorsMiddleware'
]
# 允許跨域源
CORS_ORIGIN_ALLOW_ALL = True
然后前端vue這邊需要安裝axios(ajax):
cnpm install axios --save
接着要去main.js里對axios進行全局配置:
import Axios from 'axios'
Vue.prototype.$ajax = Axios;
//配置完后在任何地方都能通過this.$ajax拿到它
具體的Goods的代碼如下:
<template> <div class="goods"> <h1>商品頁</h1> <h2>{{ msg }}</h2> </div> </template> <script> export default { name: "Goods", data:function(){ return { msg: '123' } }, beforeCreate () { window.console.log("開始創建Goods組件"); }, created () { window.console.log("Goods組件創建成功, data, methods已擁有"); }, mounted () { window.console.log("頁面已被vue實例渲染, data, methods已更新"); //我們選擇渲染完成后拿數據 //請求后台 let _this = this; this.$ajax({ url:'http://127.0.0.1:8000/goods/', method:'post', params:{ info:'前台數據' } }).then(function (result) { //then就是回調函數,相當於ajax的success // this代表的是回調then這個方法的調用者(axios插件),也就是發生了this的重指向 // 要更新頁面的title變量,title屬於vue實例 // res為回調的對象,該對象的data屬性就是后台返回的數據 let data = result.data; //this指向的是then的function,我們前面定義的_this才是全局 _this.msg = data; }) } } </script> <style scoped> .goods { height: 100vh; background-color: blue; } </style>

后台的視圖函數:
def goods(request): print(request.method) # axios的請求,原生Django都在GET字典中拿前台數據 print(request.GET) print(request.POST) return HttpResponse('后台數據')

閱讀目錄
1.用C++語言編寫,用來運行JavaScript語言
2.node可以為前端項目提供server (包含了socket)
node下載安裝:https://nodejs.org/zh-cn/

一路點擊下一步就可以。
# 換國內源,加速下載,通過命令行換源:
# 管理員命令行:npm install -g cnpm --registry=https://registry.npm.taobao.org
# MacOS: sudo npm install -g cnpm --registry=https://registry.npm.taobao.org
# 索引npm的指令都可以換成cnpm
# npm install vuex => cnpm install vuex
# cnpm install -g @vue/cli
# 如果報錯:npm cache clean --force
起步
1.cd 到目標目錄
2.創建項目:vue create 目錄名
創建項目的過程
提示下載原:選擇淘寶鏡像
具體配置:上下鍵切換,空格鍵選擇,回車鍵進入下一步
1.第二個選項進入自定義配置

2.Babel jsES6語法轉換ES5,Router路由 Vuex組件數據交互 Formatter格式化代碼

3...有提示選擇大寫,沒提示默認第一個即可
選y




開始下載:


①終端啟動
1.進入項目:cd到項目目錄
2.啟動項目:npm run serve


②pycharm配置啟動
1.安裝vue.js插件,重啟
2.配置項目的npm啟動項
3.啟動node搭建的socket





如果項目環境搭建失敗,可以將搭建成功的項目中的相關文件及文件夾:


然后打開管理員打開cmd命令
cd e:\vue-proj進入項目文件目錄下
cnpm install 對自己電腦的當前環境進行重新安裝依賴,重構項目環境,這樣就可以用了,使用pycharm打開該文件夾就行了
該方法可以用於快速創建和搭建項目環境使用,這樣就不用每次vue create進行下一步下一步了

打開main.js

修改后按ctrl+s保存后頁面會實時刷新,且文件后綴都可以省略不寫

頁面組件開發
組件創建:

創建新組件之后的基本頁面情況:
<template> <!-- 只能有一個根標簽 --> </template> <script> export default { name: "Main", data: function() { return { } }, ... } </script> <style scoped> /* scoped 可以讓樣式實現局部化*/ /* 如果讓樣式實現全局化,則應該寫在根組件樣式中*/ </style>
組件渲染
<!-- Main.vue 主頁組件 --> <template> <div class="main"> <h1>{{ title }}</h1> </div> </template> <script> export default { name: "Main", data:function () { return { title:'主頁' } } } </script> <style scoped> .main { height: 100vh; background-color: beige; } h1 { margin: 0; color: darkred; } </style>
<!-- App.vue根組件 --> <template> <div id="app"> <Main></Main> </div> </template> <script> import Main from '@/views/Main' export default { components:{ Main:Main } } </script> <style> html, body { margin: 0; } </style>
說明:



在根組件中設計轉跳頁面的導航欄
<template> <div id="app"> <ul class="nav"> <li>主頁</li> <li>商品頁</li> <li>個人頁</li> </ul> </div> </template> <script> import Main from '@/views/Main' export default { components:{ Main:Main } } </script> <style> .nav { height: 60px; background-color: silver; } .nav li { float: left; height: 60px; width: 123px; text-align: center; line-height: 60px; } .nav li:hover { background-color: aquamarine; } html, body, ul { margin: 0; } ul { list-style: none; } </style>
創建三個頁面組件
<!--Main.vue--> <template> <div class="main"> <h1>{{ title }}</h1> </div> </template> <script> export default { name: "Main", data:function () { return { title:'主頁' } } } </script> <style scoped> .main { height: 100vh; background-color: beige; } h1 { margin: 0; color: darkred; } </style>
<!--Goods.vue--> <template> <div class="goods"> <h1>商品頁</h1> </div> </template> <script> export default { name: "Goods" } </script> <style scoped> </style>
<!--User.vue--> <template> <div class="user"> <h1>個人頁</h1> </div> </template> <script> export default { name: "User" } </script> <style scoped> </style>
配置路由(router.js中)
import Vue from 'vue'
import Router from 'vue-router'
import Main from '@/views/Main.vue'
import Goods from '@/views/Goods.vue'
import User from '@/views/User.vue'
Vue.use(Router)
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/',
name: 'main',
component: Main
},
{
path: '/goods',
name: 'goods',
component: Goods
},
{
path: '/user',
name: 'user',
component: User
},
//第二種方式
// {
// path: '/about',
// name: 'about',
// // route level code-splitting
// // this generates a separate chunk (about.[hash].js) for this route
// // which is lazy-loaded when the route is visited.
// component: () => import(/* webpackChunkName: "about" */ './views/About.vue')
// }
]
})


根組件中:
<template> <div id="app"> <ul class="nav"> <li> <router-link to="/">主頁</router-link> </li> <li> <router-link to="/goods">商品頁</router-link> </li> <li> <router-link to="/user">個人頁</router-link> </li> </ul> <!--<router-view></router-view>--> <router-view/> </div> </template> <script> import Main from '@/views/Main' export default { components:{ Main:Main } } </script> <style> .nav { height: 60px; background-color: silver; } .nav li { float: left; height: 60px; width: 123px; text-align: center; line-height: 60px; } .nav li:hover { background-color: aquamarine; } html, body, ul, h1 { margin: 0; } ul { list-style: none; } a { text-decoration: none; font: bold 20px/60px 'STSong'; } </style>

前后台交互
axios
// 安裝 axios(ajax)的命令
// npm install axios --save
// 為項目配置全局axios(main.js中)
import Axios from 'axios'
Vue.prototype.$ajax = Axios
goods組件中設置ajax給后台發送數據(在組件渲染完畢時候發送)
<!--Goods.vue--> <template> <div class="goods"> <h1>商品頁</h1> </div> </template> <script> export default { name: "Goods", beforeCreate() { window.console.log("開始創建Goods組件"); }, created() { window.console.log("創建Goods組件完畢"); }, mounted() { window.console.log("Goods組件渲染完畢"); // 請求后台 this.$ajax({ method:'post', url:'http://127.0.0.1:8000/goods/', params:{ info:'前台數據' } }).then(function (res) { window.console.log(res) }) } } </script> <style scoped> </style>
新建一個Django項目,作為后台接收、返回數據
settings.py中手動將csrf中間件注釋掉(這里需要注意真正項目中前后端分離時,Django的csrf中間件時通過代碼層面禁用並手寫安全認證,這里注釋掉主要方便我們測試)
路由配置:
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^goods/', views.goods), ]
視圖函數
def goods(request): print(request.method) print(request.POST) print(request.GET) return HttpResponse('后台數據')
發現跨域問題:后台能收到前台發送的請求數據,但是由於跨域問題,只要前台端給后端發送數據,后端都會接收,來者不拒,但是由於跨域問題,導致Django不認識它,所以
不給它返回數據。
## Django跨域問題 #### 什么是跨域 ```python ''' 通常情況下,A網頁訪問B服務器資源時,不滿足以下三個條件其一就是跨域訪問 1. 協議不同 2. 端口不同 3. 主機不同 ''' ``` #### Django解決跨域 ```python ''' 安裝django-cors-headers模塊 在settings.py中配置 # 注冊app INSTALLED_APPS = [ ... 'corsheaders' ] # 添加中間件 MIDDLEWARE = [ ... 'corsheaders.middleware.CorsMiddleware' ] # 允許跨域源 CORS_ORIGIN_ALLOW_ALL = True ''' ```


解決跨域:
①在pycharm中安裝django-cors-headers
②在Django配置文件中:



然后前端進行處理數據:

這樣渲染msg后發現報錯:

發現msg沒有被定義,但是在data中明明已經定義了msg,所以錯誤不在data中,最后發現在then的回調函數中的this

問題解析:
① 在this.ajax上先聲明個變量_this=this將vue實例存起來,然后在then的回調函數中打印this和_this


從以上結果來看,在生命周期鈎子函數下的this指向的是當前創建的vue實例,而在這些函數內部使用例如axios與后台交互后回調函數的內部的this並非指向當前的vue實例;


箭頭函數相當於匿名函數,並且簡化了函數定義。看上去是匿名函數的一種簡寫,但實際上,箭頭函數和匿名函數有個明顯的區別:箭頭函數內部的this是詞法作用域,由上下文確定。此時this在箭頭函數中已經按照詞法作用域綁定了。很明顯,使用箭頭函數之后,箭頭函數指向的函數內部的this已經綁定了外部的vue實例了.
vue-cookie
// 安裝cookie的命令
// npm install vue-cookie --save
// 為項目配置全局vue-cookie(在main.js中)
import VueCookie from 'vue-cookie'
// 將插件設置給Vue原型,作為全局的屬性,在任何地方都可以通過this.$cookie進行訪問
Vue.prototype.$cookie = VueCookie
// 持久化存儲val的值到cookie中
this.$cookie.set('val', this.val)
// 獲取cookie中val字段值
this.$cookie.get('val')








