Vue入門到關門之Vue專案工程化

Xiao0101發表於2024-05-02

一、建立Vue專案

1、安裝node環境

  • 官網下載,無腦下一步,注意別放c盤就行
    • Node.js — Run JavaScript Everywhere (nodejs.org)
  • 需要兩個命令
    • npm---->pip
    • node--->python
  • 裝完檢查一下,hello world檢測,退出crtl+c

image

2、搭建vue專案環境

  • 裝cnpm 這個包,下載東西會快很多,裝模組 cnpm替代npm,其他命令還是使用npm
npm install -g cnpm --registry=https://registry.npmmirror.com

image

  • 如果卡頓,或者一直失敗,可以嘗試以下兩個解決方案
### 解決方案1:
// 1. 清空快取
npm cache clean --force
// 2. 關閉SSL驗證
npm config set strict-ssl false
// 3. 安裝
到這裡就可以正常使用npm命令安裝需要的工具了。如(npm install -g cnpm   )

### 解決方案2:
// 1. 清空快取
npm cache clean --force
// 2. 切換新源
npm config set registry https://registry.npmmirror.com
// 3. 檢視源是否設定成功
npm config get registry
// 4. 安裝
到這裡就可以正常使用npm命令安裝需要的工具了。如(npm install -g cnpm   )
  • 檢測是否安裝成功

image

3、安裝vue腳手架

cnpm install -g @vue/cli

image

4、建立專案

(1) 裝完腳手架,就會有個vue命令,透過vue命令建立vue專案

vue create myfirstvue # 按下面步驟
  • 選y

image

  • 選第三個,enter進入

image

  • 選下面三個,空格是選擇或者取消,方向鍵控制上下
    image
    image
    image
    image

  • 建立成功

image

(2)命令列輸入vue ui也可以建立專案

image
image
image
image
image
image
image
image

5、使用webstorm開啟專案

image

6、執行專案

(1)在命令列中輸入命令執行

  • 注意命令列的路徑得是專案根路徑,使用:
npm run serve
  • 預設terminal使用的是powershell,我們可以改成cmd來使用

image
image

  • 如果有下面這個啟動錯誤

image

  • 解決方案

這個錯是因為資料夾許可權不夠,不要將建立的Vue專案放到任意盤的program files資料夾裡,不然永遠是這個錯誤,因為那個資料夾不能設定為完全控制,所有肯定會報許可權不夠的錯誤。

解決方案就是將專案放入一個自定義資料夾即可

(2)配置webstorm,點綠色箭頭執行

  • 新建一個npm命令用來執行執行 serve指令碼

image
image
image

  • 啟動成功的介面

image
image

二、vue專案目錄結構

myfirstvue            # 專案名
	-node_modules     # 等同於python的venv--》虛擬環境-->裡面有很多js,專案的依賴-》可以刪除---》專案就不能執行了--》在你本地--》cnpm install--》根據package.json專案的依賴,再重新安裝--》又可以執行了
    -public           # 資料夾,一般不動
        -favicon.ico  # 小圖示
        -index.html   # spa--》單頁面應用--》整個vue專案,就只有這一個html-如果禁用了js--》整個vue都用不了
     -src             # 資料夾---》核心程式碼
        -assets       #資料夾,都放靜態檔案--》圖片,css,js。。。
        	-logo.png # 靜態圖片
        -components   # 小元件,給頁面元件使用
            HelloWorld.vue # HelloWorld 元件
        -views        # 頁面元件,頁面跳轉,實現像 html跳轉一樣的效果
            AboutView.vue # 關於頁面
            HomeView.vue  # 首頁
        -store            # vuex--》狀態管理器
            index.js
        -router           # vue-router---》路由配置檔案
            index.js
        -App.vue          # 根元件
		-main.js          # 整個專案入口

   -.gitignore      # git忽略檔案,學了git就會了
   -babel.config.js # 裝了bable配置檔案--》把高版本es語法轉成es5
   -jsconfig.json   # 不用管
   -package.json    # 專案依賴檔案--》專案依賴--》npm install--》根據他裝
   -package-lock.json # 鎖定檔案,之前專案中使用模組版本
   -README.md       # 專案介紹
   -vue.config.js   # vue整體配置檔案   

三、vue專案執行機制

  • main.js是整個專案入口檔案
// main.js---> 指定了index.html---> id為app的div---> 根App.vue 這個元件做了關聯

//es6 模組匯入規範,等同於python導包
//commonJs的匯入規範:var Vue=require('vue')
import Vue from 'vue'
import App from './App.vue'  //根元件
import router from './router'
import store from './store'

Vue.config.productionTip = false

new Vue({
  router,
  store,
  render: h => h(App)  // 代指 el
}).$mount('#app')


/*
new Vue({
	el:'#app' //原來是用el:'#app',現在是new出Vue物件,掛載到#app上---》.$mount('#app')
  render: h => h(App) //原來是在頁面上div中寫樣式,現在元件化開發 把根元件(import App from './App.vue'),透過render渲染上,渲染元件的方式
}).$mount('#app')
*/
  • vue檔案大致模版(template、script、style)
<template>
    <!-- 模板區域 -->
</template>
<script>
    // 邏輯程式碼區域
    // 該語法和script繫結出現
  	//export default-->es6的預設匯出(匯出一個物件),模擬commonJS的匯出方式制定的
    export default {

    }
</script>
<style scoped>
    /* 樣式區域 */
    /* scoped表示這裡的樣式只適用於元件內部, scoped與style繫結出現 */
</style>

  • 元件寫法
# template 寫之前我們方在template標籤的模版字串
<template>
  <div id="app">
    <h1>我是根元件</h1>
    <button @click="haneldShow">點我彈alert</button>
  </div>
</template>

# script標籤--》原來js程式碼都寫在這裡、
<script>
export default {
  name: 'HelloWorld', // 元件名字
  data() {
    return {}
  },
  methods: {
    haneldShow() {
      alert('111')
    }
  }
}
</script>


#style
<style>

button{
  background-color: aqua;
}
</style>
  • 定義元件
//1 新建xx.vue
components-->HelloWorld.vue
//2 引入使用
<script>
	// es6的引入import from 
  import HelloWorld from '@/components/HelloWorld.vue'
  import Vue from 'vue'
  Vue.component('HelloWorld',HelloWorld)  // 全域性元件
  export default {
     components: {  // 區域性元件
   		 HelloWorld:HelloWorld
  		},
}
</script>

四、es6語法總結

1、let、const、var

在JavaScript中,letconstvar是用於宣告變數的關鍵字,它們在作用域、可變性和提升等方面有一些重要的區別。 在ES6之前,我們都是用var來宣告變數,而且JS只有函式作用域和全域性作用域,沒有塊級作用域,所以{}限定不了var宣告變數的訪問範圍。

ES6 新增了let命令,用來宣告區域性變數。它的用法類似於var,但是所宣告的變數,只在let命令所在的程式碼塊內有效,而且有暫時性死區的約束。

(1)var

  • var是ES5及之前版本中用於宣告變數的關鍵字。
  • 使用var宣告的變數存在函式作用域或全域性作用域,而不存在塊級作用域。
  • var宣告的變數可以被重新賦值,並且可以在同一作用域內多次宣告同一個變數。
  • var宣告的變數會被提升(hoisting),即變數的宣告會被提升到作用域的頂部,但賦值不會被提升。
  • 例如:
    var x = 10;
    if (true) {
      var y = 20;
      console.log(x); // 可以訪問 x
      console.log(y); // 可以訪問 y
    }
    console.log(x); // 可以訪問 x
    console.log(y); // 可以訪問 y,因為 var 變數會被提升
    

(2)let

  • let是ES6中引入的關鍵字,用於宣告塊級作用域的變數。
  • 使用let宣告的變數可以被重新賦值,但不能在同一作用域內重新宣告。
  • let宣告的變數不會被提升,只有在宣告後才能訪問。
  • 例如:
    let x = 10;
    if (true) {
      let y = 20;
      console.log(x); // 可以訪問 x
      console.log(y); // 可以訪問 y
    }
    console.log(x); // 可以訪問 x
    console.log(y); // 會報錯,y 在塊級作用域外不可訪問
    

(3)const

  • const也是ES6中引入的關鍵字,用於宣告常量,常量的值一旦賦值就不能再改變。
  • 常量必須在宣告時進行初始化,且常量的值不可被重新賦值,但如果常量是物件或陣列,物件或陣列的屬性或元素可以被修改。
  • const宣告的變數也具有塊級作用域。
  • 例如:
    const PI = 3.14;
    // PI = 3.14159; // 這裡會報錯,常量不可重新賦值
    
    const person = {
      name: 'Alice',
      age: 30
    };
    person.age = 31; // 這是允許的,因為物件的屬性可以修改
    

(4)總結

  • 在現代JavaScript中,推薦優先使用const,如果變數的值需要變化,則使用let,避免使用var
  • letconst提供了更好的變數宣告方式,有助於程式碼的可讀性和可維護性,同時避免了var可能導致的一些問題。
  • 使用let宣告變數時,如果變數的值會發生變化,但不需要重新宣告變數,可以使用let
  • 使用const宣告常量時,如果變數的值不會改變,可以使用const,這有助於提高程式碼的可讀性和可維護性。

(5)補充

"暫時性死區"(Temporal Dead Zone,簡稱 TDZ)是指在 ES6 中使用 let 或 const 宣告變數時,變數存在但無法訪問的區域。這種行為是為了在 JavaScript 中引入塊級作用域而設計的。

在 JavaScript 中,使用 var 宣告的變數在其宣告語句之前就可以被訪問,這種行為稱為"變數提升"。而在使用 let 或 const 宣告變數時,變數雖然存在於作用域中,但是在宣告語句之前訪問這些變數會導致引發 ReferenceError 異常。

暫時性死區的產生原因是,let 和 const 宣告的變數在進入作用域時就已經被建立,並且被繫結到了該作用域中,但是在變數的宣告語句之前,訪問這些變數會進入暫時性死區,因為此時變數尚未初始化

2、 箭頭函式

(1)簡化程式碼,使程式碼更簡潔

(2)箭頭函式內部,沒有自己的this,它會使用上一級的this,解決了函式內部的this指向問題

(3)this指向問題:

  • 在全域性上下文中,this 指向全域性物件,在瀏覽器環境中通常是 window 物件,在 Node.js 中是 global 物件
console.log(this) # window 物件
  • 函式呼叫

    • 如果函式作為普通函式呼叫,this 指向全域性物件(在嚴格模式下為 undefined)

    • 如果函式作為物件的方法呼叫,this 指向呼叫該方法的物件。

  • 建構函式

    • 在建構函式中,this 指向的是新建立的例項物件。
  • 箭頭函式

    • 箭頭函式的 this 指向定義時所在的作用域的 this 值,而不是呼叫時的 this 值。換句話說,箭頭函式的 this 是詞法作用域,而不是動態作用域。在傳統的函式中,this的值是在函式被呼叫時確定的,根據呼叫方式不同可能指向不同的物件。但是在箭頭函式中,this的值是在定義函式時確定的,它會捕獲所在上下文的this值,而不是在執行時改變。這種行為可以避免在回撥函式中出現意外的this指向問題,使得程式碼更加簡潔和可讀。
  • DOM 事件處理函式:

    • 在 DOM 事件處理函式中,this 指向觸發事件的 DOM 元素
  • ES6 類方法:

    • 在 ES6 類方法中,this 指向呼叫該方法的物件例項

3、模版字串

模板字串是 JavaScript 中的一種特殊字串,用反引號 ` (也稱為反引號、重音符號或反引號字元)括起來。模板字串可以包含多行文字和嵌入表示式,使用${}語法插入表示式。這使得在字串中嵌入變數、表示式或函式呼叫變得更加方便。舉個例子:

const name = 'Alice';
const greeting = `Hello, ${name}!`;

console.log(greeting); // 輸出: Hello, Alice!

在上面的例子中,${name}是一個嵌入的表示式,它會被變數name的值替換掉。模板字串的這種特性使得動態生成字串變得更加簡單和直觀。

4、解構賦值

解構賦值是一種在 JavaScript 中方便地從陣列或物件中提取資料並賦值給變數的語法。它可以讓你快速地將陣列或物件中的值解構到單獨的變數中。

  • 解構賦值允許從陣列或物件中提取資料,並將其賦值給變數。
  • 解構賦值可以方便地交換變數的值,同時還支援預設值。

(1)物件解構賦值

在物件解構賦值中,花括號{}裡面放置的是要提取的屬性名,而變數名則是接收對應屬性值的變數名。

let user = {name: 'lqz', age: 19, hobby: '燙頭'}
// 平常寫法
let name=user.name
let age=user.age
// 解構賦值寫法
let {name,age,hobby,a=10} = user

console.log(name,age,hobby,a)

(2)陣列解構賦值

在陣列解構賦值中,方括號[]裡面放置的是要提取的元素位置,而變數名則是接收對應位置元素的變數名。同時...rest的語法表示將剩餘的元素賦值給rest變數,這在需要獲取陣列中剩餘元素時非常有用。

const numbers = [1, 2, 3, 4, 5];
const [first, second, ...rest] = numbers;

console.log(first); // 輸出: 1
console.log(second); // 輸出: 2
console.log(rest); // 輸出: [3, 4, 5]

(3)解構函式返回值

function getuserInfo() {
    return {name: 'xiao', age: 19, hobby: ['燙頭', '喝酒']}
}

let {name='1', hobby} = getuserInfo()
console.log(name, hobby)  // 如果內部修改,優先返回值中的值

5、預設引數

ES6 允許在函式引數中設定預設值,當呼叫函式時未提供引數時,將使用預設值

# 案例
function demo01(name,age=19) {
    console.log(name,age)
}
demo01('xiao')

6、展開運算

展開運算子 ... 可以將可迭代物件(如陣列、字串、物件)展開為多個引數或元素。也可以用於函式引數。

# 案例1:物件
let a={age:19,hobby:'打球'}
let user={name:'xiao',age:20,...a}
console.log(user)
'''
Object
    age: 19    # 以後面值為主
    hobby: "打球"
    name: "xiao"
'''

# 案例2:陣列
let l=[1,2,3]
let l1=[44,55,66,...l]
console.log(l1)
# [44, 55, 66, 1, 2, 3]

# 案例3
function demo01(a,...b){
    console.log(a)
    console.log(b)
}
demo01(1,2,34,4)
'''
1
[2, 34, 4]
'''
let l=[44,5,66,7]
demo01(...l)
'''
44
[5, 66, 7]
'''

7、模組化

在以後,做專案開發的時候,肯定要匯入某些模組使用:

  • 之前的前端是使用<script src=""></script>
  • 以後在專案中:import App from './App.vue' 語法引入

(1)預設匯出和匯入

預設匯出 (Default Export)

預設匯出允許一個模組只匯出一個預設值。在一個模組中,你可以使用 export default 來匯出預設值,然後在另一個模組中使用 import 語句來引入這個預設值。

示例:

// xiao/utils.js
var name = 'xiao'

function add(a, b) {
    console.log(name)
    return a + b
}

export default name  // 只匯出變數
export default add   // 只匯出函式
export default {name,add}  // 匯出物件

export default {
    name:"彭于晏",
    add: (a,b)=>{
        return a+b
    }
}

匯入預設匯出

在匯入預設匯出時,你可以選擇給匯入的變數起一個名字,這個名字不必和匯出時的名稱相同。

<script type="module">
    // 相對匯入,相對於當前檔案
    import xiao from './xiao/utils'  

	// 絕對匯入--》開始匯入的路徑  src路徑,但是需要寫個 @
    import xiao from '@/xiao/utils'

	console.log(utils.name)
    let res=utils.add(3,4)
    console.log(res)
</script>

注意事項

  • 一個模組只能有一個預設匯出。
  • 在匯入預設匯出時,你可以選擇使用任何合法的變數名。

預設匯出適用於匯出一個單一的值、物件、函式等,使得匯入時更加簡潔。

(2)命名匯出和匯入

在 JavaScript 中,除了預設匯出之外,還有一種常用的匯出方式是命名匯出(Named Export)。命名匯出允許一個模組匯出多個變數、函式或物件,這些匯出的內容可以在匯入時透過名稱引用。

命名匯出 (Named Export)

使用命名匯出時,你可以在一個模組中透過 export 關鍵字匯出多個變數、函式或物件,然後在另一個模組中透過名稱引入這些匯出。

示例:

// xiao/utils.js
// 可以匯出多個
export const age = 99
export const add = (a, b) => a + b
export const showName = name => {
    console.log(name)
}

export const obj={
    name:'xiao',
    show(){
        alert('show')
    }
}

匯入命名匯出

在匯入命名匯出時,需要使用花括號 {} 來指定要匯入的內容,同時這些名稱必須與匯出時使用的名稱相匹配。

// 第一種方式:花括號匯入
import {age, add, showName} from '@/xiao/common'
import {showName, obj} from '@/xiao/common'
// 以後可以使用showName裡面函式
// 以後可以使用obj的物件,又可以點obj.xx

// 第二種方式:*全部匯入然後取別名
<script type="module">
    import * as xx from './xiao/utils.js'
    console.log(xx.add(8,9))
    console.log(xx.age)
</script>

注意事項

  • 一個模組可以有多個命名匯出。
  • 在匯入命名匯出時,必須使用與匯出時相同的名稱。

命名匯出適用於匯出多個變數、函式或物件,使得模組的功能更加靈活和可擴充套件。

(3)如果在資料夾下有個index.js,只要導到資料夾一層即可

  • index.js就相當於python中的__init__,匯入的時候可以不用帶index.js
// 匯出的是index.js
export default {
    name:'xiao',
    showAge:function (){
        console.log('age',this.name)
    },
    showName:()=>{
        console.log(this.name)
    },
    showHobby(){
        console.log('hobby',this.name)
    }
}

// 匯入可以不用帶index
<script type="module">
    // 命名匯出的匯入
    import xiao from '@/xiao/index'
    或者可以直接寫成
    import xiao from '@/xiao'
    console.log('----',lqz.name)
    lqz.showAge()
    lqz.showHobby()
</script>

(4)vue專案中,元件的使用

  • 建立元件Child
<template>
  <div>
    <div class="top">
      <button>後退</button>
      <span @click="handleShow">{{ title }}</span>
      <button>前進</button>
    </div>
  </div>
</template>

<script>
export default {
  name: 'Child',
  data() {
    return {
      title: '首頁'
    }
  },
  methods: {
    handleShow() {
      alert('1111')
    }
  }
}
</script>


<style scoped>
.top {
  display: flex;
  justify-content: space-between;
}
</style>
  • 在其他元件中使用
<template>
  <div id="app">
    <h1>我是根元件</h1>
    <button>點我彈alert</button>
    <hr>
    <Child></Child>
  </div>
</template>
<script>
// @ 代指---》src資料夾
import Child from "@/components/Child.vue";
export default {
  name: 'HelloWorld',  // 元件名字
  components:{
    Child    // 註冊區域性元件
  }
}
</script>

<style>
button{
  background-color: aqua;
}
</style>

五、vue-router簡單使用

單頁面應用的字面意思就是隻需要一個html頁面就能實現頁面跳轉的效果,其本質就是元件的跳轉。

那元件如何跳轉?這就需要藉助於第三方:vue-router 了

1、安裝vue-router

(1)透過 npm 安裝

  • 這是最常用的安裝方式。安裝完成後,你可以在程式碼中引入並使用 Vue Router。
npm install vue-router

(2)透過 CDN 引入

  • 你也可以透過 CDN 的方式引入 Vue Router,在 HTML 檔案中新增以下程式碼:
  • 這種方式適合快速體驗或在簡單的專案中使用。
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>

(3)透過 Vue CLI 安裝

  • 如果你使用 Vue CLI 建立專案,在建立專案時可以選擇安裝 Vue Router。Vue CLI 會自動配置好 Vue Router 的基本設定。
vue create my-project
# 在建立專案時選擇安裝 Vue Router

但是如果你在建立vue專案的時候沒有勾選router項,在這裡可以按照第一種或者第二種方案進行安裝。一般情況下,推薦使用 npm 安裝的方式,因為這種方式可以更好地與構建工具(如 Webpack)整合,並且可以使用 ES6 語法。

2、App.vue寫個標籤

只需要在App.vue 寫個標籤,之後就不要再寫任何其他東西了

<template>
<div id="app">
    <router-view>

    </router-view>
    </div>
</template>

3、在views裡面建立頁面元件

根據你的需求來建立不同的頁面元件,為了下面的登入跳轉案例,我在這裡會建立IndexView LoginView兩個頁面元件,當登入成功時跳轉到首頁獲取電影列表。

4、註冊元件

接下來需要我們在在 router/index.js裡面註冊剛剛建立的頁面元件

# 1 匯入
    import LoginView from "@/views/LoginView";
    import IndexView from "@/views/IndexView";

    const routes = [
    # 2 註冊路由
    {
        path: '/',
        name: 'home',
        component: IndexView
    },
    {
        path: '/login',
        name: 'login',
        component: LoginView
    },
]

# 4 

5、完成

以後瀏覽器再次訪問不同路徑,就會根據不同的路由來切換相對應的頁面元件

六、登入跳轉案例

1、前期準備

(1)模組安裝

  • 專案中使用axios 需要安裝
cnpm install axios -S
  • 在要用的位置[注意匯入的位置],
# 匯入
import axios from 'axios'
# 使用
axios.get().then()

(2)跨域問題的解決

  • 使用pip安裝
pip3 install django-cors-headers
  • 新增到setting的app中
 INSTALLED_APPS = (
     ...
     'corsheaders',
     ...
 )
  • 新增中介軟體
MIDDLEWARE = [
    ...
    'corsheaders.middleware.CorsMiddleware',
    ...
]
  • setting下面新增下面的配置
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'
)

(3)前端頁面元件跳轉

  • 在登陸成功時跳轉到首頁時候使用
this.$router.push('router/index.js/在index.js中配置過的路徑')

2、後端

(1)models.py

from django.db import models
from django.contrib.auth.models import AbstractUser

class UserInfo(AbstractUser):
    # user表擴寫欄位需要加default或者null=True
    gender = models.IntegerField(choices=((1, 'Male'), (2, 'Female'), (3, 'Other')), default=1)
    age = models.IntegerField(default=18)
    phone = models.CharField(max_length=11, null=True, blank=True)

(2)serializer.py

from rest_framework_simplejwt.serializers import TokenObtainPairSerializer

class LoginSerializer(TokenObtainPairSerializer):
    def validate(self, attrs):
        response = super().validate(attrs)
        user = self.user
        data = {'code': 100, 'msg': '登入成功','username': user.username,'gender': user.get_gender_display()}
        data.update(response)
        return data

(3)views.py

import json
from django.shortcuts import render
from rest_framework.response import Response
from rest_framework.views import APIView

class FilmView(APIView):
    def get(self, request):
        with open('./film.json', 'rt', encoding='utf-8') as f:
            res = json.load(f)
        return Response(res)

(4)urls.py

from django.contrib import admin
from django.urls import path
from rest_framework_simplejwt.views import token_obtain_pair
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('login/', token_obtain_pair),
    path('film/',views.FilmView.as_view())
]

(5)settings.py

AUTH_USER_MODEL = 'app01.userinfo'

SIMPLE_JWT = {
    "TOKEN_OBTAIN_SERIALIZER": "app01.serializer.LoginSerializer",
}

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

REST_FRAMEWORK = {
    'EXCEPTION_HANDLER': 'app01.exceptions.common_exception_handler',
}

3、前端

(1)router/index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
// 匯入
import LoginView from "@/views/LoginView.vue";
import IndexView from "@/views/IndexView.vue";


Vue.use(VueRouter)

const routes = [
    // 註冊路由
    {
        path: '/',
        name: 'index',
        component: IndexView
    },
    {
        path: '/login',
        name: 'login',
        component: LoginView
    },
]

const router = new VueRouter({
    mode: 'history',
    base: process.env.BASE_URL,
    routes
})

export default router

(2)LoginView.vue

<template>
  <div>
    <h1>登入</h1>
    <p>使用者名稱:<input type="text" v-model="username"></p>
    <p>密碼:<input type="password" v-model="password"></p>
    <p>
      <button @click="handleSubmit">登入</button>
    </p>
  </div>
</template>
<script>
import http from "axios"

export default {
  name: "LoginView",
  data() {
    return {
      username: '',
      password: ''
    }
  },
  methods: {
    handleSubmit() {
      // 傳送ajax請求
      http.post('http://127.0.0.1:8000/login/', {
        username: this.username,
        password: this.password
      }).then(response => {
        if (response.data.code == 100) {
          // 跳轉  vue-router支援的(重點)
          this.$router.push('/')
        } else {
          alert(response.data.msg)
        }
      })
    }
  }
}
</script>
<style scoped>
</style>

(3)IndexView.vue

<script>
import axios from 'axios'

export default {
  name: "IndexView",
  data() {
    return {
      filmList: []
    }
  },
  created() {
    axios.get('http://127.0.0.1:8000/film/').then(res => {
      this.filmList = res.data.results
    }).catch(err => {
      alert('請聯絡系統管理員')
    })
  }
}
</script>
<template>
  <div>
    <h1>首頁</h1>
    <div v-for="film in filmList">
      <img :src="film.poster" alt="" height="200px" width="150px">
      <div>
        <h3>{{ film.name }}</h3>
        <p>主演:
          <span v-for="item in film.actors">
                {{ item.name }} &nbsp;&nbsp;
            </span>
        </p>
        <p>{{ film.nation }}|{{ film.runtime }}</p>
      </div>
    </div>
  </div>
</template>
<style scoped>
h1 {
  background-color: aquamarine;
}
</style>

七、scoped的使用

在 Vue.js 中,<style> 標籤中的 scoped 屬性用於將樣式限定在當前元件的作用域內,避免樣式汙染和衝突。這樣做可以確保樣式只適用於當前元件,而不會影響其他元件。以後專案中的css樣式,都會寫在vue元件的<style>標籤中。

以下是一個簡單的示例,演示瞭如何在 Vue 元件中使用 scoped 屬性:

<template>
  <div class="container">
    <h1>This is a scoped style example</h1>
    <p>This is a paragraph with scoped style.</p>
  </div>
</template>

<style scoped>
.container {
  background-color: lightblue;
  padding: 20px;
}

h1 {
  color: blue;
}

p {
  color: green;
}
</style>

在上面的示例中,<style scoped> 標籤中的樣式只會應用於當前元件內部的元素,而不會影響其他元件。這意味著即使你在其他元件中使用了相同的類名或標籤名,也不會受到當前元件樣式的影響。

八、問題

1、開啟檔案執行的流程

  • 在django的views.py 開啟檔案,開啟檔案的程式碼中寫的檔案路徑,這個檔案為什麼要放在專案根路徑?

因為真正執行的檔案是manage.py,如果要開啟檔案,就得從專案執行的路徑下開始找,而manage.py對應的正是專案根目錄下。

class FilmView(APIView):
    def get(self, request):
        with open('./film.json', 'rt', encoding='utf-8') as f:
            res = json.load(f)
        return Response(res)

2、跨域問題

只要按照上面的處理跨域的步驟來寫,以後不需要再響應頭中加了允許跨域的鍵值對了,不論是post,還是delete,所有請求都沒有跨域了

相關文章