# 1 計算屬性
-屬性放在data設定項中,方法放在methods中
-computed:{
方法名(){}
}
-把它當屬性用,快取:只有當該計算屬性使用的變數發生變化時,它才重新運算
# 2 重寫過濾案例
- 通過計算屬性,重寫過濾案例
-newDataList做成計算屬性,v-for直接回圈它
-newDataList使用的變數只要發生變化,它就會重新運算,使用了mytext,只要input輸入內容,它就會重新運算,不需要加事件了
# 3 監聽屬性
- data中定義的屬性,可以使用watch繫結一個方法,以後只要這個屬性發生變化,就會觸發方法的執行
- watch:{
page(){
}
}
# 4 元件:有自己的html,css,js,以後相用,直接註冊使用即可
-全域性,區域性
-var child={template:``,data(){return {}},methods:{}}
-元件中註冊:components:{child}
# 5 元件間通訊-元件間資料,方法都是隔離的
-父傳子:自定義屬性
<child :myname='lqz'></child>
-在子元件中:props:['myname']
-子傳父:自定義事件
-子元件中某種情況下把子元件的資料傳給父元件
<child @myevnet='handleClick'></child>
-點選事件函數內部:this.$emit('自定義事件名字',name)
-ref屬性:
-放在普通標籤上: this.$refs.標籤上的名字 原生dom物件
-放在元件上:this.$refs.元件上的名字 元件物件 它有變數,方法
# 6 動態元件
-不確定顯示的元件是什麼,動態變化的
<component :is='變數'></component>
-<keep-alive></keep-alive>
# 7 插槽
-寫了元件,元件內部,空一個位置 <slot></slot>
-<child > <div></div> </child>
-預設插槽
-具名插槽:挖多個坑,給每個坑命個名
<slot name="b"></slot>
<child > <div slot="b"></div> </child>
<child > <div v-slot:b></div> </child>
# 8 vue-cli
-對比djagno,建立djagno專案需要怎麼做?
-裝python直譯器,安裝模組django,django-admin建立專案
-nodejs,安裝模組vue-cli
-npm install @vue/cli -g
-vue 可執行檔案
-vue create專案名
-bable
-vuex
-vue-router
-編輯器選擇
-jetbrains公司:Pycharm,goland,phpstorm,IDEA,webstorm
-pycharm+vue外掛 開發前端
-vscode:微軟出的,輕量級,免費
-eclipse my eclipse
-谷歌買了jetbrains授權, AndroidStadio
-sublime Text
-vim+外掛
-vue專案執行的兩種方式
-命令列中執行:npm run serve
-pycharm的綠色箭頭執行
# 9 學過的設定項
- el(template)
- data :組建中 方法
- methods
- 8個生命週期勾點
- components
- watch
- computed
# 前端做成專案----》使用工具(vue-cli),建立出vue專案,單頁面應用(spa),元件化開發, 把 xx.vue,ts,saas,less-----》編譯---》在瀏覽器中執行
# vue-cli建立專案開發,在專案中開發,最後上線,一定要編譯--->純粹的html,js,css
# 瀏覽器只能識別 js html css
# vue-cli 工具,使用nodejs寫的,要執行,需要node環境
# 下載node直譯器
-一路下一步
-環境變數:可執行檔案路徑 就在環境變數
-兩個可執行檔案:
-node: python
-npm: pip
# nodejs 怎麼來的
-js只能執行在瀏覽器中,因為瀏覽器中有它的直譯器環境
-基於谷歌瀏覽器的v8引擎,使它可以執行在作業系統之上 網路包,檔案,資料庫。。。 用c寫的
-js語法 完成後端的編寫,全棧
-號稱效能高,大量使用協程
# 檔案防篡改校驗
-把檔案生成md5值
-以後被下載下來,再生成md5值肯定是一樣,如果不一樣說明被篡改了,不能用了
-1 百度網路硬碟
-秒傳
-傳到伺服器上---》生成md5---》存著
-本地生成md5---》傳送到伺服器端---》一查----》有---》不傳了
- 遮蔽
-2 王小云 破解md5
# 直譯語言和編譯型語言
-js,node,php,python 直譯語言 執行直譯器之上 pyinstaller
-c,go,c++ 編譯型語言 直接把原始碼編譯成不同平臺的可執行檔案
-cpython直譯器用c寫的----》編譯成不同平臺的可執行檔案---》在不同平臺雙擊執行即可
-win
-mac
-linux
-java:一處編碼處處執行
-java 虛擬機器器 ---》虛擬機器器跨平臺
-java位元組碼檔案執行在虛擬機器器之上
-java寫了程式碼----》編譯成位元組(區別與可執行檔案 jar,war,.class)
# 建立vue專案使用什麼?
-2.x 使用vue-cli :https://cli.vuejs.org/zh/
-3.x 使用vue-cli
-vite只能建立vue3 效率非常高
# 按裝vue-cli
npm install -g @vue/cli
# 使用cnpm替換npm cnpm淘寶出的工具,下載的時候,去淘寶映象下載,速度快
# -g 表示裝全域性
#--registry=https://registry.npm.taobao.org 指定淘寶映象
npm install -g cnpm --registry=https://registry.npm.taobao.org
# 以後使用cnpm 代替npm
cnpm install -g @vue/cli
# cmd控制檯就可以輸入 vue 命令(裝了djagno可以使用django-admin建立django專案)
-vue 建立vue專案
# 使用vue-cli建立專案(找個目錄)
vue create myfirstvue # 速度很慢,等,可以ctrl+c停止 執行npm cache clean --force
# 很慢的原因
-從github拉一個空專案
-按照該專案所有的依賴,npm裝
# 按下圖操作
vue ui # 使用圖形化介面建立專案 ,自己點選即可
myfirstvue # 專案名字
node_modules # 資料夾,內部有很多當前專案依賴的模組,可以刪除,npm install
public # 資料夾
-favicon.ico # 網站小圖示
-index.html # spa:單頁面應用
src # 以後咱們寫程式碼,都在這下面
-assets # 靜態資源,js,css,圖片 類似於static資料夾
logo.png # 靜態資源的圖片
-components # 元件:小元件,用在別的大(頁面元件)元件中
-HelloWorld.vue # 預設了一個hello world元件
-router # 裝了vue-router自動生成的,如果不裝就沒有
index.js # vue-router的設定
-store # 裝了vuex自動生成的,如果不裝就沒有
index.js # vuex的設定
-views # 放了一堆元件,頁面元件
AboutView.vue # 關於 頁面元件
HomeView.vue # 主頁 頁面元件
-App.vue # 根元件
-main.js # 整個專案啟動入口
.gitignore # git的忽略檔案 不用動
babel.config.js # babel的設定 不用動
jsconfig.json # 組態檔 不用動
package.json # 重要:類似於python專案的requirements.txt 當前專案所有依賴
package-lock.json # 鎖定檔案:package.json中寫了依賴的版本,這個檔案鎖定所有版本
README.md # 讀我,專案的介紹
vue.config.js # vue專案的組態檔
# node_modules是個資料夾,內部有很多當前專案依賴的模組(第三方模組)
# 沒有node_modules專案不能執行
# 傳送給別人的時候需要刪除【上傳git要忽略掉】,刪除了使用cnpm install可以重新安裝回來
比如建立python專案時,如果勾選了虛擬環境,會建立一個venv資料夾:
這個venv資料夾,放置了一個python直譯器的環境,如果你再下了第三方依賴,是安裝在這個venv資料夾下的python環境的。好處是,每一個專案都不會互相影響。相當於每一個python專案都有一個自己的直譯器。
而這個node_modules也是類似的效果,存放了很多專案的第三方依賴模組。node_modules是可以刪除的(這個檔案比較大),如果你要提交到倉庫、傳送給別人,需要把它刪除掉。但是你把node_modules刪除掉了,專案就無法啟動了(缺乏第三方依賴)。但是可以使用npm install命令,該命令會根據package.json檔案給你重新裝上這些依賴。
補充:webpack是程式碼編譯的工具 ---> 編譯成只有html、js、css
public # 資料夾
-favicon.ico # 網站小圖示
-index.html # spa:單頁面應用
-assets # 靜態資源,js,css,圖片 類似於static資料夾
現在我們寫的專案只有一個index.html頁面。
所有元件都在這個div內部切換,也就實現首頁、登入頁面、註冊頁面切換。這個div很重要,不要在這個標籤內寫東西。
通過<%= BASE_URL %>
可以找到在public資料夾下的小圖示。
網站名字是在package.json
裡面定義的:
noscript:
如果你的網站禁用了js:
就會顯示上面的提示語句:
# app.vue是根元件
根元件的內容會直接替換到index.html頁面下的這個div內。
# package.json當前專案的依賴項
如果刪除,npm install
就不知道裝什麼了。
package.json寫了一些專案依賴的版本。
這些依賴的版本新增了上箭頭^
,這表示安裝時會裝3版本里最新的3.6.2。但是總是安裝最新的版本,可能會出現版本不相容問題。
lock檔案可以對版本進行鎖定:
以後安裝就按照這個鎖定版本進行安裝,而不是按照package.json
檔案安裝,這樣不會出現問題。所以我們也不要動這個lock檔案。
總結:以後經常用的就兩個views (寫頁面),components(寫元件)。
# node.js中如果要匯入,必須先匯出
-預設匯出
-命名匯出
# python建立包,只需要在其他py檔案中匯入
# 預設匯出寫法
# 語法
-匯出語法
export default 一般是個物件
-匯入語法
import 別名 from '路徑'
以後 別名 就是 匯出的物件
# 範例
1.在js檔案中定義變數,函數,最後使用export defalut匯出
export default {
name: '彭于晏',
printName () {
console.log(this.name)
}
}
2 在想使用的js中,匯入
import 隨便起 from './lqz/utils'
# 命名匯出和匯入
-匯出語法 可以匯出多個
export const name = '劉亦菲'
export const printName = () => {
console.log('星象銜新寵')
}
-匯入語法
import {printName} from './lqz/utils'
# 在包下可以建立一個名為index.js 的檔案,以後匯入的時候,會預設找它
-對比python中得__init__.py
# 找到index.html 中的id為app的div,以後都在App.vue中寫
new Vue({
render: h => h(App)
}).$mount('#app')
main.js是專案的入口,程式執行的時候是從這裡開始執行的:
解釋main.js的程式碼含義:
Vue提供了一些開發過程中的提示,通過如上設定項可以選擇是否需要開啟這些提示。
這裡等同於el:'#app'
,但這是如何做到的呢?
$mount
這裡就是去public/index.html掛載了那個id='app'
的div。
注意public、index這兩個名字必須是固定的。
render後面對應的是一個箭頭函數,傳入了一個h,返回一個h(app)。
而這個app是匯入進來的:
也就是匯入了App.vue下的內容:
匯入這個app之後,用h(app)執行了一下,進行了掛載。
本質是在App.vue
中寫的程式碼,會原封不動的插入到index.html內的div:
在utils.js內寫程式碼:
我們想在main.js中引入utils.js檔案,並使用其中的變數和函數,那麼應該怎麼做?
需要先在util.js匯出,別的檔案才能匯入,這一點和python不一樣:
預設匯出用的最多,只能匯出一次。
這相當於匯出了一個物件。(還可以使用es6的語法將其簡寫)
只有在export default
匯出的,在別的檔案才能匯入。
使用預設匯出,沒有給匯出的物件取一個名字。
關於預設匯出,我們可以這樣匯入:
main.js匯入了之後這個xxx,xxx就是之前匯出的物件:
儘量使用包名作為匯入物件的名字:
執行專案:
f沒有匯出所以會報錯。
預設匯出的其他寫法:
這裡的this指代當前物件,this.name='彭于晏'
。
使用命名匯出,name相當於一個變數:
在main.js匯入:
使用命名匯出時,匯入的時候可以匯入多個名字。
注意:同一個需要匯出的檔案中,預設匯出和命名匯出不能混用。
將我們需要匯入的包中的檔案改名為index.js:
這樣匯入的時候就可以直接導包了(如果包下檔名不是index不能這樣做):
這個index.js就類似於python中的__init__
。(導包的時候會自動執行__init__檔案
)
# 以後寫的元件,都是單頁面元件 也就是xx.vue檔案
# 以後寫一個元件就是一個xx.vue xx.vue --分為-> 頁面元件和小元件
# 以後一個元件就是一個xx.vue檔案,xx.vue檔案內部都有三部分
-<template></template> # html內容寫在裡面
-並且必須套在一個div標籤裡
-<script></script> # 寫js內容
-<style></style> # 寫css樣式
# main.js 是整個專案的入口
1 把App.vue根元件匯入了
2 使用new Vue({render: h => h(App)}).$mount('#app') 把App.vue元件中得資料和模板,插入到了index.html的id為app的div中了
3 以後,只要在每個元件的export default {} 寫之前學過的所有js的東西
4 以後,只要在每個元件的template,寫模板,插值語法,指令...
5 以後,只要在每個元件的style,寫樣式...
# 1 以後只需要寫xx.vue
-頁面元件
-小元件 給頁面元件用的
# 2 元件中匯出
export default {
name: 'HelloWorld',
data() {
return {
xx: '彭于晏'
}
},
}
# 3 在別的元件中要用,匯入,註冊
# 匯入
import HelloWorld from '../components/HelloWorld.vue'
# 註冊
export default {
components: {
HelloWorld
}
}
# 4 註冊以後,在這個元件中就可以使用匯入的元件 ,寫在<template>
# 自定義屬性
<HelloWorld msg="傳進來的p"/>
檢視HomeView.vue(頁面元件):
檢視HelloWorld.vue(小元件):
注意這裡匯出都需要使用預設匯出,匯出一個物件,在其他頁面直接使用這個物件進行註冊。
正常情況下,想要使用區域性元件,需要在設定項components寫元件相關資訊:
但是,我們可以通過匯入的方式,把HelloWorld(子)中的元件到HomeView(父)中註冊:
元件註冊成功之後,就可以在HomeView使用了:
子元件的msg屬性,是通過父元件標籤裡寫的自定義屬性傳過來的:
main.js匯入了App.vue根元件:
根元件中也需要有template、script、style三種標籤。如果根元件中沒有script標籤,會導致掛載時沒有資料,只有一個template設定項。
在根元件script標籤內寫匯出的內容:
不用給匯出的物件寫template屬性,這裡會自動將上面template標籤的內容掛載到這個物件上。
根元件的內容會通過new Vue({render: h => h(App)}).$mount('#app')
這行程式碼,最終掛載到index.html的div標籤內。
以後開發元件,只需要在template標籤內寫就可以了:
跟之前的寫法一樣,只是換了寫程式碼的位置。
# 安裝axios
-npm install axios -S
# 匯入使用
<script>
import axios from 'axios'
</script>
# 傳送請求,獲取資料
axios.get('http://127.0.0.1:8000/books/').then(res => {
console.log(res.data)
this.bookList=res.data
})
# 先用這種方式解決跨域(django 專案)
1 pip3 install django-cors-headers
2 app中註冊:
INSTALLED_APPS = (
...
'corsheaders',
...
)
3 中介軟體註冊
MIDDLEWARE = [
...
'corsheaders.middleware.CorsMiddleware',
...
]
4 把下面的複製到組態檔中
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',
)
在App.vue根元件寫程式碼:
# 安裝axios
-npm install axios -S
-npm install -S axios
-npm install -S [email protected] # 安裝老版本
'''-S 表示將axios模組儲存到package.json中'''
# 匯入使用
import axios from 'axios'
在App.vue的script標籤內匯入axios:
通過axios傳送請求:
處理跨域問題,參照上面的設定即可。
在template標籤內使用插值語法,顯示後端的資料:
前後端互動流程分析:
登入功能:
寫事件函數,通過axios傳送post請求:
後端寫登入介面:
前端傳送的post請求裡面攜帶的是json字串,所以使用原生django應該在request.body裡面接受。
# props設定項: 在裡面寫接受父傳子自定義的屬性
# props設定項有三種寫法:
-1 陣列寫法
-2 物件物件寫法
-3 物件套物件寫法
# 寫法總結
// 普通使用
// props: ['msg'],
// 屬性驗證
// props: {msg: String},
// 指定型別,必填和預設值
props: {
msg: {
type: String, //型別
required: true, //必要性
default: '老王' //預設值
}
},
新建元件child.vue
:
在根元件引入元件:
在根元件中註冊:
在根元件中使用:
根元件通過自定義屬性進行父傳子(可以寫多個自定義屬性):
子元件通過props設定項接受資料(陣列寫法):
子元件通過props設定項接受資料(物件寫法):
可以進行屬性的驗證,雖然報錯,但前端還是顯示。
子元件通過props設定項接受資料(物件套物件寫法):
這裡設定了,如果自定義屬性沒填寫數值,那麼預設值是老王
,且控制檯不會報錯:
如果設定了required:true
,自定義屬性不填,控制檯會報錯,但是前端還是會渲染預設值老王
。
# mixin(混入) 可以把多個元件共用的設定提取成一個混入物件
-把多個元件中公用的東西,抽取出來,以後可以全域性使用和區域性使用
# 使用步驟
-1 寫個mixin/index.js
export const hunhe = {
data() {
return {
name: '彭于晏'
}
},
methods: {
handlePrintName() {
alert(this.name)
}
},
}
-2 區域性匯入:在元件中
import {hunhe} from "@/mixin";
mixins:[hunhe,]
-3 全域性使用,在main.js 中 以後所有元件都可以用
import {hunhe} from "@/mixin";
Vue.mixin(hunhe)
新建一個元件,並將其匯入到根元件:
寫根元件程式碼:
寫child元件程式碼:
可見根元件和子元件有同樣的函數handlePrintName。
在src新建mixin資料夾,在此資料夾下新建index.js檔案,寫如下程式碼:
這裡的函數,直接將元件中的函數部分賦值過來。
在根元件中匯入混入物件,開始使用:
再寫一個mixins設定項:
如果一個元件的設定項裡既有mixins,又有methods,這兩個可以一起用嗎?
注意:如上範例中,混入匯入的和methods中的函數都是同一個名字。
直接說結論:先使用methods中的函數,如果在methods中找不到,再用mixins的。
擴充套件:
混入不僅僅可以抽取methods中的函數,還可以抽取data()
資料。
查詢順序和之前的一樣,先使用元件自己的資料,如果沒有資料,再去mixins中找資料。
create()
這種生命週期勾點函數也可以抽取到mixins。
需要在main.js中匯入mixin包:
全域性引入之後,相當於在所有元件中都加入了mixins設定項,所有元件就都可以使用混入的函數和資料了。
mixins具體使用情景:
比如有一個記錄使用者瀏覽記錄的功能,通過引入mxins,可以實現在每個元件都可以使用這個功能。
# 功能:用於增強Vue
本質:包含install方法的一個物件,install的第一個引數是Vue,第二個以後的引數是外掛使用者傳遞的資料
# 使用步驟
-寫一個 plugins/index.js
import Vue from "vue";
import axios from "axios";
import {hunhe} from '@/mixin'
export default {
install(miVue) {
// console.log(miVue)
// 1 vue 範例上放個變數
// Vue.prototype.$name = 'lqz' // 類比python,在類上放了一個屬性,所有物件都能取到
// Vue.prototype.$ajax = axios
// 2 使用外掛,加入混入
// 全域性使用混入
// Vue.mixin(hunhe)
// 3 定義全域性元件
// 4 定義自定義指令 v-lqz
Vue.directive("fbind", {
//指令與元素成功繫結時(一上來)
bind(element, binding) {
element.value = binding.value;
},
//指令所在元素被插入頁面時
inserted(element, binding) {
element.focus();
},
//指令所在的模板被重新解析時
update(element, binding) {
element.value = binding.value;
},
});
}
}
2 在main.js 中使用外掛
import plugins from '@/plugins'
Vue.use(plugins) // 本子,使用use,會自動觸發外掛物件中得install
3 以後再元件中可以直接用外掛中寫的東西
# 父元件寫了style,子元件都會使用父元件的style
如果在根元件中寫了樣式,會在所有頁面元件都生效,這樣不太好,所有需要使用scoped。
# 父元件的樣式,在子元件中會生效,在style上寫 <style scoped> </style>讓該樣式只在當前元件中生效
# 範例
<style scoped>
h1 {
background-color: chartreuse;
}
</style>
父元件寫了style,子元件都會使用父元件的style
路由:
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/login',
name: 'login',
component: () => import('@/views/loginView') // 匯入login檢視
},
loginView.vue:
<template>
<div>
<h2>我是登入頁面</h2>
<p>請輸入名字:<input type="text" v-model="username"></p>
<p>請輸入密碼:<input type="password" v-model="password"></p>
<button @click="handleSend">提交按鈕1</button>
<button @click="handleSend2">提交按鈕2</button>
</div>
</template>
<script>
// 匯入axios
import axios from 'axios'
// 匯入登入函數 (方式一:使用預設匯出)
import tools from '@/test_import/index'
let handleSend = tools.handleSend // 不能直接放,需要用一個變數裝一下
// 匯入登入函數 (方式二:使用有名匯出)
import {handleSend2} from '@/test_import'
export default {
name: "loginView",
data() {
return {
username: '',
password: '',
data: null,
}
},
methods: {
handleSend, // 預設匯出
handleSend2, // 有名匯出
}
}
</script>
<style scoped>
</style>
test_import\index.js:
import axios from "axios"; // 這裡必須匯入axios,因為別的包會直接呼叫下面的函數,而下面的函數需要使用這個axios
// 預設匯出
export default {
handleSend() {
axios.post('http://127.0.0.1:8000/api/v1/login/', {
username: this.username,
password: this.password
}).then(res => {
this.data = res.data
if (res.data.code === 1000) {
alert(res.data.msg)
window.location.href = 'http://localhost:8080/'
} else {
alert(res.data.msg)
}
})
}
}
// 有名匯出
export const handleSend2 = function handleSend2() { // 這裡如果使用匿名函數,由於匿名函數沒有this,在別的元件中使用會導致獲取不了資料。
axios.post('http://127.0.0.1:8000/api/v1/login/', {username: this.username, password: this.password}).then(res => {
this.data = res.data
if (res.data.code === 1000) {
alert(res.data.msg)
window.location.href = 'http://localhost:8080/'
} else {
alert(res.data.msg)
}
})
}
前期準備:
imgFather.vue:
<template>
<div> <!-- 注意這個div,別忘了,不然會報錯 -->
<!-- 1. 通過自定義屬性url,給子元件傳資料(父傳子) -->
<imgShow url="https://img1.baidu.com/it/u=3494536116,3351731546&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500"
@sonEvent="eventFunc"></imgShow>
<!-- 2. 通過自定義事件sonEvent,接受子元件傳遞的資料,並使用插值語法顯示(子傳父) -->
<p>{{ text }}</p>
</div>
</template>
<script>
import imgShow from "@/components/imgShow"; // 匯入子元件
export default {
name: "imgFather",
data() {
return {
text: null,
}
},
methods: {
eventFunc(data) {
this.text = data // 接受子元件傳遞的資料data
}
},
components: {
imgShow, // 註冊子元件
}
}
</script>
<style scoped>
</style>
imgShow.vue:
<template>
<div> <!-- 注意這個div,別忘了,不然會報錯 -->
<img :src="url">
為頁面元件註冊路由:
{
path: '/testSlot',
name: 'testSlot',
component: () => import('@/views/testSlot') // 匯入testSlot檢視
},
imgSlot.vue:
<template>
<div>
<slot></slot> <!-- 匿名插槽 -->
<div class="img-padding">
<slot name="girl"></slot> <!-- 有名插槽 -->
</div>
</div>
</template>
<script>
export default {
name: "imgSlot"
}
</script>
<style scoped>
.img-padding {
width: 500px;
height: 500px;
border: 8px outset white;
border-radius: 50%;
margin: 20px auto;
overflow: hidden;
}
</style>
testSlot.vue:
<template>
<div>
<imgSlot>
<p>這是一張小姐姐圖片:</p> <!-- 使用匿名插槽 -->
<div slot="girl"> <!-- 使用有名插槽 -->
<img src="https://inews.gtimg.com/newsapp_bt/0/14043245848/641" alt="">
</div>
</imgSlot>
</div>
</template>
<script>
import imgSlot from "@/components/imgSlot";
export default {
name: "testSlot",
components: {
imgSlot,
}
}
</script>
<style scoped>
</style>