1. 程式人生 > 實用技巧 >VUE建立專案

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 ,否則可能出現一些不必要的麻煩

  1. 首先cd切換到目標目錄
  2. 執行:vue create 專案名
  3. 選擇自定義方式建立專案,選取Router, Vuex外掛
  4. 選擇第二個進入自定義配置:

5. 執行時,會提示下載源,選擇淘寶映象即可。(有大寫的選大寫,大寫是建議的選項)

6.具體配置:上下鍵切換,空格鍵選擇,回車鍵進入下一步

勾選Babel、Router、Vuex、Formatter

Babel :jsES6語法轉換ES5

Router:路由

Vuex:元件資料互動

Formatter:格式化程式碼

下一步選Y,接下來的配置都是提示選項有大寫選大寫,沒有預設選第一個配置就行

安裝完後的目錄如下:

三、終端啟動專案

  1. cd到你的專案:cd vue_proj
  2. npm run serve
  3. 訪問: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>

  1. 6.2、路由:單頁面實現頁面之間轉跳

先來準備三個檔案(區域性元件):

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>

至此就實現了單頁面的區域性元件切換了。

  1. 6.3、前後臺互動(基於6.2的頁面Goods)

上面我們已經實現了單頁面的切換,那麼我們肯定每個頁面都要到後臺拿資料,比如我點選商品頁後就要動態從資料庫獲取資訊,然後展示到前端頁面,這就涉及到了前後臺的互動問題。

我們以Goods為例來看一下生命週期鉤子

  1. 鉤子表示一個vue例項從建立到銷燬的這個過程,將這個過程的一些時間節點賦予了對應的鉤子函式
  2. 鉤子函式: 滿足特點條件被回撥的方法

我們在Goods.vue的script中加入鉤子

當點選商品頁時,會觸發鉤子:

瞭解了這個,下面我們以django作為後臺,來實現以下互動

因為互動是vue自己完成的,我們拿不到csrf的認證字串,所以直接去配置檔案中把這個中介軟體註釋掉。

然後我們通過axios向後臺發請求。

注意,在前後臺互動的時候,會產生跨域的問題

  1. 什麼是跨域問題?

通常情況下,A網頁訪問B伺服器資源時,不滿足以下三個條件其一就是跨域訪問
1. 協議不同
2. 埠不同
3. 主機不同

  1. django解決跨域問題:

安裝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專案環境:

回到頂部

Vue專案需要自建伺服器:node

node介紹:

1.用C++語言編寫,用來執行JavaScript語言
2.node可以為前端專案提供server (包含了socket)

node下載安裝:https://nodejs.org/zh-cn/

一路點選下一步就可以。

回到頂部

npm:包管理器 - 為node拓展功能的

# 換國內源,加速下載,通過命令列換源:
# 管理員命令列: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

回到頂部

vue cli環境:腳手架 - 命令列快速建立專案

# cnpm install -g @vue/cli

# 如果報錯:npm cache clean --force

回到頂部

建立Vue專案

起步
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>

說明:

回到頂部

路由:router.js

在根元件中設計轉跳頁面的導航欄

<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