VUE建立專案
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主指令碼檔案:
importVuefrom'vue' //./代表的是相對路徑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永遠只能擁有一種狀態值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('後臺資料')
閱讀目錄
- Vue專案開發:
- Vue專案需要自建伺服器:node
- npm:包管理器 - 為node拓展功能的
- vue cli環境:腳手架 - 命令列快速建立專案
- 建立Vue專案
- 啟動專案
- 專案目錄
- 頁面元件開發
- 路由:router.js
- 前後臺互動
前後端完全分離
回到頂部
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例項;
若想拿到後臺回傳的資料更新data裡的資料,不能在回撥函式中直接使用this,而要用在外部函式定義的變數儲存的this,也就是當前vue的例項。 以上是一種解決方式,這裡再補充另一種解決方法:使用es6語法箭頭函式自動解決此類問題:箭頭函式相當於匿名函式,並且簡化了函式定義。看上去是匿名函式的一種簡寫,但實際上,箭頭函式和匿名函式有個明顯的區別:箭頭函式內部的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