近幾天更新完畢,不定期持續更新,建議關注收藏點贊。
目錄
- 工具推薦
- vscode插件
- vue-devtools
- ESLint
- JSX語法擴展
- 簡介
- 設計模式
- 快速入門
- @vue/cli腳手架
- 使用
- vue指令
工具推薦
工欲善其事,必先利其器。
vscode插件
Vetur:vue代碼高亮插件
VueHelper:代碼提示插件
vue-devtools
vue-devtools 是一個專門為 Vue.js 開發者打造的 瀏覽器開發者工具插件,可以用來 調試、查看和修改 Vue 應用的內部狀態。
簡單來說,它就像給 Vue 應用裝了個“透視眼”,讓你能輕松看到組件之間是怎么工作的。
- vue-devtools 能干嘛?【5點】
查看組件結構:類似一棵樹,展示你的應用是由哪些組件組成的,誰嵌套誰。你可以直接點進每個組件,看到它的名字、props、data、computed 等。
實時查看和修改數據:能看到組件當前的數據(data、props、computed)。修改數據還能立刻看到頁面更新,適合調試。
事件追蹤:查看哪個組件發出了哪個自定義事件($emit)。可以看到事件的名字、參數、傳播鏈等。
Vuex 調試(如果你用了 Vuex):查看 Vuex 的 state、getters、mutations、actions。
時間旅行調試(Time Travel Debugging):可以前進后退查看狀態變化。
性能檢測(性能分析標簽頁):查看組件的更新頻率、渲染開銷,找出性能瓶頸。 - 安裝
Chrome 插件商店搜索 vue-devtools 安裝。或者在 Firefox 也可以裝。
如果是開發桌面應用或在本地調試,Vue 官方還提供了獨立版(Electron 應用)。 - 使用
確保你的 Vue 應用在開發模式Vue 在生產模式下默認關閉調試信息,vue-devtools 可能檢測不到。所以開發時要確保沒有 Vue.config.productionTip = false 或類似壓縮優化設置。
ESLint
它是一個代碼檢查工具,用于JavaScript 和 TypeScript 的靜態代碼分析工具,主要功能是識別并修復代碼中的問題,比如語法錯誤、不一致的風格、潛在的 bug 等。
npm install eslint --save-dev
npx eslint --init #初始化配置
#這個命令會引導你選擇項目的風格、使用的框架(React、Vue等)、
#是否使用 TypeScript 等,并生成一個配置文件(.eslintrc.js、.eslintrc.json 等)。
npx eslint yourfile.js #檢查這個文件
npx eslint yourfile.js --fix #自動修復代碼
比如:如果在main.js 聲明個變量而不使用,則終端和網頁都會報錯,因為不嚴謹。
- 解決方式
方式1: 手動解決掉錯誤, 以后項目中會講如何自動解決
方式2: 暫時關閉eslint檢查, 在vue.config.js中配置后重啟服務
module.exports={//其他配置略lintOnSave:false//關閉eslint檢查
}
- 常配合使用的插件/配置
eslint-config-airbnb: Airbnb 代碼規范
eslint-plugin-react: 檢查 React 項目
eslint-plugin-import: 管理模塊導入
eslint-config-prettier: 配合 Prettier,關閉 ESLint 中和 Prettier 沖突的規則
JSX語法擴展
JSX(JavaScript XML)是一種 JavaScript 的語法擴展,主要用于Vue/ React。它讓你可以在 JavaScript 中寫出類似 HTML 的代碼,描述界面的結構。
Vue 本身沒有默認使用 JSX,默認用的是模板語法(.vue 文件里的 < template>),但支持 JSX 語法擴展
function Welcome(props) {return <h1>Hello, {props.name}</h1>;
}const element = <Welcome name="Alice" />;
- JSX 的核心特點
- 像 HTML 但不是 HTML
const name = "ChatGPT";
const element = <h1>Hello, {name}!</h1>;
- 標簽必須閉合
// 正確
<img src="logo.png" />
- 只能有一個根節點
// 錯誤 ?
return (<h1>Title</h1><p>Description</p>
);// 正確 ?
return (<div><h1>Title</h1><p>Description</p></div>
);
- class 改為 className
因為 class 是 JavaScript 的關鍵字,所以在 JSX 中寫樣式類時要用 className
<div className="container">Hello</div>
- JSX 配合 ESLint
為了讓 ESLint 正確識別 JSX,你需要使用對應的插件和解析器:
#react
npm install eslint-plugin-react eslint-plugin-react-hooks --save-dev#vue
npm install --save-dev eslint eslint-plugin-vue @vue/eslint-config-standard babel-eslint eslint-plugin-babel eslint-plugin-import eslint-plugin-node eslint-plugin-promise#vue3還需要
npm install @vitejs/plugin-vue-jsx @vue/babel-plugin-jsx --save-dev
//配置 .eslintrc.js 示例
//react
module.exports = {parser: 'babel-eslint',extends: ['eslint:recommended','plugin:react/recommended'],plugins: ['react'],rules: {'react/prop-types': 'off'},settings: {react: {version: 'detect'}}
};//vue
module.exports = {root: true,env: {node: true,},parserOptions: {parser: 'babel-eslint',ecmaVersion: 2020,sourceType: 'module',ecmaFeatures: {jsx: true, // 開啟 JSX 支持},},extends: ['eslint:recommended','plugin:vue/vue3-recommended', // Vue 3 推薦配置'plugin:import/recommended','plugin:promise/recommended',],plugins: ['vue', 'babel'],rules: {// 自定義規則,例如關閉 console 警告'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off','no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',// Vue 特有規則'vue/no-multiple-template-root': 'off', // Vue 3 不再強制單根節點},
};//babel.config.js
module.exports = {presets: ['@vue/cli-plugin-babel/preset'],plugins: ['@vue/babel-plugin-jsx'],
};//Vue 組件中使用 JSX
<script setup>
import { defineComponent } from 'vue';export default defineComponent({setup() {return () => <div class="hello">Hello from JSX!</div>;},
});
</script>
簡介
vue的底層還是原生js。開發更加的效率和簡潔, 易于維護, 現在很多項目都是用vue開發的。
漸進式聲明式組件化的javacript框架,官網地址: https://cn.vuejs.org/ 。
漸進式: 逐漸進步, 想用什么就用什么, 不必全都使用
- vue的特點:
- 漸進式
- 聲明式渲染:ue 基于標準 HTML 拓展了一套模板語法,使得我們可以聲明式地描述最終輸出的 HTML 和 JavaScript 狀態之間的關系。
- 數據驅動視圖 (響應式):Vue 會自動跟蹤 JavaScript 狀態并在其發生變化時響應式地更新 DOM。
- 極少的去寫DOM操作相關代碼
- 雙向綁定
- 組件系統
- 不兼容IE8及以下瀏覽器(因為vue的響應式原理是基于es5的Object.defineProperty(),而這個方法不支持ie8及以下)
- 庫 v.s. 框架
庫: 封裝的屬性或方法 (例jquery.js),還是那個規則、語法、元素。
框架: 擁有自己的規則和元素, 比庫強大的多 (例vue.js) - 工程化開發方式:在webpack環境中開發vue,這是最推薦的企業常用方式
- 目前Vue2已停止維護,之后所有Vue3的變化都用高亮顯示
最簡單的實例
<div id="app"><button @click="count++">Count is: {{ count }}</button>
</div>
import { createApp, ref } from 'vue'createApp({setup() {return {count: ref(0)}}
}).mount('#app')
設計模式
- vue是MVVM設計模式
vue源碼內采用MVVM設計模式思想, 大大減少了DOM操作, 提高開發效率
用數據驅動視圖改變, 操作dom的事,由vue源碼內部來做。vue是數據變化視圖自動更新, 減少操作DOM時間, 提高開發效率
- 在vue中,不推薦直接手動操作DOM!!!
- 在vue中,通過數據驅動視圖,不要在想著怎么操作DOM,而是想著如何操作數據!!(思想轉變)
- MVVM
MVVM,一種軟件架構模式,決定了寫代碼的思想和層次
M: model數據模型 (data里定義)
V: view視圖 (html頁面)
VM: ViewModel視圖模型 (vue.js源碼)
MVVM通過數據雙向綁定
讓數據自動地雙向同步 不再需要操作DOM
V(修改視圖) -> M(數據自動同步)
M(修改數據) -> V(視圖自動同步)
- MVVM
M層和V層可以互相改變
在devtool工具可以改變M層的變量, 觀察V層(視圖的自動同步);(devtool工具就是chrome瀏覽器檢查工具(開發者模式)里多出來的vue工具)
- 對比MVC設計模式
- 組件化:模塊獨立,復用性強,適用于所有現代前端項目,如React, Vue
- Flux/Redux:單向數據流,適合大型狀態管理,見于react
- MVC: 也是一種設計模式, 組織代碼的結構, 是model數據模型, view視圖, Controller控制器, 在控制器這層里編寫js代碼, 來控制數據和視圖關聯
應用于早期小項目 - MVVM: 即Model-View-ViewModel的簡寫。即模型-視圖-視圖模型, VM是這個設計模式的核心, 連接v和m的橋梁, 內部會監聽DOM事件, 監聽數據對象變化來影響對方. 我們稱之為數據綁定
應用于Vue, Angular 等現代框架,響應式數據雙向綁定
React 并不嚴格是 MVVM,為什么很多人還是說 React 屬于 MVVM?因為它也有:Model(state、props)、View(JSX)、某種“中間層邏輯”(用 Hook、useEffect 實現的)但這些功能都融合在組件中,不像 Vue 的 ViewModel 那么清晰分層。
React 是一種以組件為中心、函數式編程風格、支持單向數據流的前端庫。它既不像傳統 MVC,也不是典型 MVVM,而是一種組件驅動的 UI 架構。
React 的不同點:
- React 是單向數據流
數據從組件的 state/props 向下流動到 UI。
沒有像 Vue 那樣的“自動雙向綁定”。- 沒有“真正意義上的 ViewModel”
在 React 中,沒有一個專門處理邏輯與數據綁定的“ViewModel”。
組件本身就承擔了“視圖”和“一部分邏輯”的職責。- React 強調函數式思想
使用 Hook 來組合邏輯,而不是 ViewModel。
傾向于將 UI 表現為“狀態的純函數”。
快速入門
- 單文件組件
使用一種類似 HTML 格式的文件來書寫 Vue 組件,它被稱為單文件組件 (也被稱為 *.vue 文件,英文 Single-File Components,縮寫為 SFC)。顧名思義,Vue 的單文件組件會將一個組件的邏輯 (JavaScript),模板 (HTML) 和樣式 (CSS) 封裝在同一個文件里。
//app.vue
<script setup>
import { ref } from 'vue'
// “ref”是用來存儲值的響應式數據源。
const count = ref(0)
</script><template><button @click="count++">Count is: {{ count }}</button>
</template><style scoped>
button {font-weight: bold;
}
</style>//更復雜的例子
<!--
這個示例展示了如何通過 v-on 指令處理用戶輸入。
--><script setup>
import { ref } from 'vue'const message = ref('Hello World!')function reverseMessage() {// 通過其 .value 屬性// 訪問/修改一個 ref 的值。message.value = message.value.split('').reverse().join('')
}function notify() {alert('navigation was prevented.')
}
</script><template><!--注意我們不需要在模板中寫 .value,因為在模板中 ref 會自動“解包”。--><h1>{{ message }}</h1><!--綁定到一個方法/函數。這個 @click 語法是 v-on:click 的簡寫。--><button @click="reverseMessage">Reverse Message</button><!-- 也可以寫成一個內聯表達式語句 --><button @click="message += '!'">Append "!"</button><!--Vue 也為一些像 e.preventDefault() 和 e.stopPropagation()這樣的常見任務提供了修飾符。--><a href="https://vuejs.org" @click.prevent="notify">A link with e.preventDefault()</a>
</template><style>
button, a {display: block;margin-bottom: 1em;
}
</style>//attribute綁定
<!--
現在我們將元素的 attribute / property 響應式地綁定到狀態上。
這個 :title 語法是 v-bind:title 的簡寫。
--><script setup>
import { ref } from 'vue'const message = ref('Hello World!')
const isRed = ref(true)
const color = ref('green')function toggleRed() {isRed.value = !isRed.value
}function toggleColor() {color.value = color.value === 'green' ? 'blue' : 'green'
}
</script><template><p><span :title="message">Hover your mouse over me for a few seconds to see my dynamically bound title!</span></p><!--除了普通字符串之外,class 綁定還特別支持了對象和數組--><p :class="{ red: isRed }" @click="toggleRed">This should be red... but click me to toggle it.</p><!-- 樣式綁定也支持對象和數組 --><p :style="{ color }" @click="toggleColor">This should be green, and should toggle between green and blue on click.</p>
</template><style>
.red {color: red;
}
</style>//條件&循環
<!--
我們可以通過 v-if 和 v-for 指令條件性地或循環地渲染內容。
--><script setup>
import { ref } from 'vue'const show = ref(true)
const list = ref([1, 2, 3])
</script><template><button @click="show = !show">Toggle List</button><button @click="list.push(list.length + 1)">Push Number</button><button @click="list.pop()">Pop Number</button><button @click="list.reverse()">Reverse List</button><ul v-if="show && list.length"><li v-for="item of list">{{ item }}</li></ul><p v-else-if="list.length">List is not empty, but hidden.</p><p v-else>List is empty.</p>
</template>//表單綁定
<!--
我們可以使用 v-model 指令在狀態和表單輸入之間創建雙向綁定。
--><script setup>
import { ref } from 'vue'const text = ref('Edit me')
const checked = ref(true)
const checkedNames = ref(['Jack'])
const picked = ref('One')
const selected = ref('A')
const multiSelected = ref(['A'])
</script><template><h2>Text Input</h2><input v-model="text"><p>{{ text }}</p><h2>Checkbox</h2><input type="checkbox" id="checkbox" v-model="checked"><label for="checkbox">Checked: {{ checked }}</label><!--多個復選框可以綁定到相同的 v-model 數組--><h2>Multi Checkbox</h2><input type="checkbox" id="jack" value="Jack" v-model="checkedNames"><label for="jack">Jack</label><input type="checkbox" id="john" value="John" v-model="checkedNames"><label for="john">John</label><input type="checkbox" id="mike" value="Mike" v-model="checkedNames"><label for="mike">Mike</label><p>Checked names: {{ checkedNames }}</p><h2>Radio</h2><input type="radio" id="one" value="One" v-model="picked"><label for="one">One</label><br><input type="radio" id="two" value="Two" v-model="picked"><label for="two">Two</label><p>Picked: {{ picked }}</p><h2>Select</h2><select v-model="selected"><option disabled value="">Please select one</option><option>A</option><option>B</option><option>C</option></select><p>Selected: {{ selected }}</p><h2>Multi Select</h2><select v-model="multiSelected" multiple style="width:100px"><option>A</option><option>B</option><option>C</option></select><p>Selected: {{ multiSelected }}</p>
</template>
- vue組件風格:兩種不同的風格書寫:選項式 API 和組合式 API。
在生產項目中:當你不需要使用構建工具,或者打算主要在低復雜度的場景中使用 Vue,例如漸進增強的應用場景,推薦采用選項式 API。
當你打算用 Vue 構建完整的單頁應用,推薦采用組合式 API + 單文件組件。
- 組合式 API (Composition API)
通過組合式 API,我們可以使用導入的 API 函數來描述組件邏輯。在單文件組件中,組合式 API 通常會與<script setup>
搭配使用。這個 setup attribute 是一個標識,告訴 Vue 需要在編譯時進行一些處理,讓我們可以更簡潔地使用組合式 API。比如,<script setup>
中的導入和頂層變量/函數都能夠在模板中直接使用。
<script setup>
import { ref, onMounted } from 'vue'// 響應式狀態
const count = ref(0)// 用來修改狀態、觸發更新的函數
function increment() {count.value++
}// 生命周期鉤子
onMounted(() => {console.log(`The initial count is ${count.value}.`)
})
</script><template><button @click="increment">Count is: {{ count }}</button>
</template>
- 選項式 API (Options API)
用包含多個選項的對象來描述組件的邏輯,例如 data、methods 和 mounted。選項所定義的屬性都會暴露在函數內部的 this 上,它會指向當前的組件實例。
<script>
export default {// data() 返回的屬性將會成為響應式的狀態// 并且暴露在 `this` 上data() {return {count: 0}},// methods 是一些用來更改狀態與觸發更新的函數// 它們可以在模板中作為事件處理器綁定methods: {increment() {this.count++}},// 生命周期鉤子會在組件生命周期的各個不同階段被調用// 例如這個函數就會在組件掛載完成后被調用mounted() {console.log(`The initial count is ${this.count}.`)}
}
</script><template><button @click="increment">Count is: {{ count }}</button>
</template>
- 簡單組件 多文件
//app.vue
<!--
這里展示了最簡單的組件,它接收一個 prop 并渲染出來。
--><script setup>
import { ref } from 'vue'
import TodoItem from './TodoItem.vue'const groceryList = ref([{ id: 0, text: 'Vegetables' },{ id: 1, text: 'Cheese' },{ id: 2, text: 'Whatever else humans are supposed to eat' }
])
</script><template><ol><!--我們給每個 todo 項提供它所表示的 todo 對象,以便能夠動態展示內容。同時還需要給每個組件提供一個“key”,--><TodoItemv-for="item in groceryList":todo="item":key="item.id"></TodoItem></ol>
</template>//TodoItem.vue
<script setup>
const props = defineProps({todo: Object
})
</script><template><li>{{ todo.text }}</li>
</template>
@vue/cli腳手架
Vue CLI 里的 cli 指的是:Command Line Interface(命令行界面)
webpack自己配置環境很麻煩, 下載@vue/cli包,
@vue/cli是Vue官方提供的一個全局模塊包, 用vue命令創建腳手架項目,開箱即用、0配置webpack、支持babel、css、 less、開發服務器。vue命令創建工程目錄, 項目內置webpack本地熱更新服務器, 幫我們打包項目預覽項目
- 安裝
把@vue/cli模塊包按到全局
yarn global add @vue/cli
# OR
npm install -g @vue/clivue -V
項目里包含 webpack 嗎?是的,雖然你沒手動安裝,但在項目的 node_modules 里,間接安裝了 webpack,因為:@vue/cli-service 依賴了 webpack,你可以通過運行npm ls webpack
來查看具體版本。
即使你是用 yarn 安裝的 @vue/cli 或創建的項目,你依然可以用npm ls webpack
來查看項目中是否安裝了 webpack,因為:npm ls webpack
會去看當前項目的 node_modules 目錄里是否安裝了 webpack(不管你是用 npm 還是 yarn 裝的)。yarn 和 npm 都是基于 package.json 和 node_modules 工作的。
- 創建項目
注意: 項目名不能帶大寫字母, 中文和特殊符號
# vue和create是命令, vuecli-demo是文件夾名
vue create vuecli-demo#選擇模版preset:選擇用什么方式下載腳手架項目需要的依賴包
#可以上下箭頭選擇, 弄錯了ctrl+c重來cd vuecil-demonpm run serve
# 或 啟動本地熱更新開發服務器
yarn serve
- 文件目錄
vuecil-demo # 項目目錄├── node_modules # 項目依賴的第三方包├── public # 靜態文件目錄├── favicon.ico# 瀏覽器小圖標└── index.html # 單頁面的html文件(網頁瀏覽的是它)├── src # 業務文件夾├── assets # 靜態資源└── logo.png # vue的logo圖片├── components # 組件目錄└── HelloWorld.vue # 歡迎頁面vue代碼文件 ├── App.vue # 整個應用的根組件└── main.js # webpack入口js文件├── .gitignore # git提交忽略配置├── babel.config.js # babel配置├── package.json # 依賴包列表├── README.md # 項目說明└── yarn.lock # 項目包版本鎖定和緩存地址
public/index.html – 瀏覽器運行的網頁
src/main.js – webpack打包的入口文件 vue初始化
src/App.vue – vue項目入口頁面 App.vue => main.js => index.html
- vue項目架構
- @vue/cli 自定義配置
項目中沒有webpack.config.js文件,因為@vue/cli用的vue.config.js
src并列處新建vue.config.js
/* 覆蓋webpack的配置 */
module.exports = {devServer: { // 自定義服務配置open: true, // 自動打開瀏覽器port: 3000}
}
- @vue/cli 單vue文件
單vue文件好處, 獨立作用域互不影響,不再擔心變量重名問題
Vue推薦采用.vue文件來開發項目
template里只能有一個根標簽
vue文件-獨立模塊-作用域互不影響
style配合scoped屬性, 保證樣式只針對當前template內標簽生效
vue文件配合webpack, 把他們打包起來插入到index.html, 然后在瀏覽器運行
<!--App.vue文件 -->
<!-- template必須, 只能有一個根標簽, 影響渲染到頁面的標簽結構 -->
<template><div>歡迎使用vue</div>
</template><!-- js相關 -->
<script>
export default {name: 'App'
}
</script><!-- 當前組件的樣式, 設置scoped, 可以保證樣式只對當前頁面有效 -->
<style scoped>
</style>
去掉默認的內容:src/App.vue默認有很多內容,以及assets 和 components 文件夾下的一切都刪除掉
使用
- 插值表達式/聲明式渲染/文本插值 這三個名字是一個東西
在dom標簽中, 直接插入內容; dom中插值表達式賦值, vue的變量必須在data里聲明。
運用JSX語法{{表達式}}
<!--App.vue文件 -->
<template><div><h1>{{ msg }}</h1><h2>{{ obj.name }}</h2><h3>{{ obj.age > 18 ? '成年' : '未成年' }}</h3></div>
</template><script>
export default {data() { // 格式固定, 定義vue數據的地方return { // key相當于變量名msg: "hello, vue",obj: {name: "小vue",age: 5}}}
}
</script><style>
</style>
- 寫法區分
new Vue({ data: {} }):用來創建根實例。
export default { data() { return {} } }:用來定義一個組件。這個寫法是為了讓每個組件實例的數據互不干擾,所以必須寫成返回對象的函數。為了組件復用時避免數據共享帶來的副作用。
項目 | new Vue({...}) | export default {...} |
---|---|---|
使用位置 | main.js 等入口文件 | .vue 文件組件 |
作用 | 創建整個 Vue 應用的根實例 | 定義一個 Vue 組件 |
是誰調用它? | 你自己在寫:new Vue(...) | Vue 自己去加載組件用的 |
data寫法 | 可以直接寫對象:data: {} | 必須是函數:data() { return {} } |
組件復用性 | 不考慮復用,數據共享沒問題 | 組件可復用,需要數據隔離 |
示例 | main.js 里 | MyComponent.vue 里 |
vue指令
vue指令, 實質上就是特殊的 html 標簽屬性, 特點: v- 開頭,每個指令, 都有獨立的作用
- v-bind:給dom加屬性的,屬性內容就是vue變量的值, 影響標簽顯示效果
v-bind:屬性名="vue變量"
簡寫:屬性名="vue變量"
<!-- vue指令-v-bind屬性動態賦值 -->
<a v-bind:href="url">我是a標簽</a>
<img :src="imgSrc">
- v-on:給標簽綁定事件
在 Vue 中,事件修飾符給事件擴展額外功能, 可以鏈式書寫,Vue 會從左到右依次執行修飾符
<!--
v-on:事件名="要執行的少量代碼"
v-on:事件名="methods中的函數"
v-on:事件名="methods中的函數(實參)"
無傳參, 通過形參直接接收
傳參, 通過$event指代事件對象傳給事件處理函數
簡寫: @事件名="methods中的函數"
--><!--
@事件名.修飾符="methods里函數"
.stop - 阻止事件冒泡
.prevent - 阻止默認行為
.once - 程序運行期間, 只觸發一次事件處理函數
--><!-- vue指令: v-on事件綁定-->
<template><div><p>你要買商品的數量: {{count}}</p><button v-on:click="count = count + 1">增加1</button><button v-on:click="addFn">增加1個</button><button v-on:click="addCountFn(5)">一次加5件</button><button @click="subFn">減少</button><a @click="one" href="http://www.baidu.com">阻止百度</a><hr><a @click="two(10, $event)" href="http://www.baidu.com">阻止去百度</a></div>
</template>
<script>export default {// ...其他省略methods: {addFn(){ // this代表export default后面的組件對象(下屬有data里return出來的屬性)this.count++},addCountFn(num){this.count += num},subFn(){this.count--},one(e){e.preventDefault()},two(num, e){e.preventDefault()}}}
</script><template><div @click="fatherFn"><!-- vue對事件進行了修飾符設置, 在事件后面.修飾符名即可使用更多的功能 --><button @click.stop="btn">.stop阻止事件冒泡</button><a href="http://www.baidu.com" @click.prevent="btn">.prevent阻止默認行為</a><button @click.once="btn">.once程序運行期間, 只觸發一次事件處理函數</button></div>
</template><script>
export default {methods: {fatherFn(){console.log("father被觸發");},btn(){console.log(1);}}
}
</script>
- v-on按鍵修飾符
給鍵盤事件, 添加修飾符, 增強能力
@keyup.enter - 監測回車按鍵
@keyup.esc - 監測返回按鍵
<template><div><input type="text" @keydown.enter="enterFn"><hr><input type="text" @keydown.esc="escFn"></div>
</template><script>
export default {methods: {enterFn(){console.log("enter回車按鍵了");},escFn(){console.log("esc按鍵了");}}
}
</script><!-- 例子 -->
<template><div><h1>{{ message }}</h1><button @click="btn">逆轉世界</button></div>
</template><script>
export default {data() {return {message: "HELLO, WORLD",};},methods: {btn(){this.message = this.message.split("").reverse().join("")}}
};
</script>
- v-model:把value屬性和vue數據變量, 雙向綁定到一起。
雙向數據綁定:數據變化 -> 視圖自動同步,視圖變化 -> 數據自動同步
v-model="vue數據變量"<template><div><!-- v-model:是實現vuejs變量和表單標簽value屬性, 雙向綁定的指令--><div><span>用戶名:</span><input type="text" v-model="username" /></div><div><span>密碼:</span><input type="password" v-model="pass" /></div><div><span>來自于: </span><!-- 下拉菜單要綁定在select上 --><select v-model="from"><option value="北京市">北京</option><option value="南京市">南京</option><option value="天津市">天津</option></select></div><div><!-- (重要)遇到復選框, v-model的變量值非數組 - 關聯的是復選框的checked屬性數組 - 關聯的是復選框的value屬性--><span>愛好: </span><input type="checkbox" v-model="hobby" value="抽煙">抽煙<input type="checkbox" v-model="hobby" value="喝酒">喝酒<input type="checkbox" v-model="hobby" value="寫代碼">寫代碼</div><div><span>性別: </span><input type="radio" value="男" name="sex" v-model="gender">男<input type="radio" value="女" name="sex" v-model="gender">女</div><div><span>自我介紹</span><textarea v-model="intro"></textarea></div></div>
</template><script>
export default {data() {return {username: "",pass: "",from: "",hobby: [], sex: "",intro: "",};// 總結:// 特別注意: v-model, 在input[checkbox]的多選框狀態// 變量為非數組, 則綁定的是checked的屬性(true/false) - 常用于: 單個綁定使用// 變量為數組, 則綁定的是他們的value屬性里的值 - 常用于: 收集勾選了哪些值}
};
</script>
- v-model修飾符
- v-model.修飾符=“vue數據變量”
- .number 以parseFloat轉成數字類型
- .trim 去除首尾空白字符
- .lazy 在change時觸發而非input時
在 Vue 中使用 v-model 時,默認是綁定在 input 事件上的,也就是說只要用戶輸入了內容(比如鍵盤敲一下),就會觸發數據更新。
lazy會改為在 change 事件時才更新綁定的數據,也就是說用戶只有在失去焦點或按下 Enter 的時候,message 才會更新。
<template><div><div><span>年齡:</span><input type="text" v-model.number="age"></div><div><span>人生格言:</span><input type="text" v-model.trim="motto"></div><div><span>自我介紹:</span><textarea v-model.lazy="intro"></textarea></div></div>
</template><script>
export default {data() {return {age: "",motto: "",intro: ""}}
}
</script>
- v-text和v-html
注意: 會覆蓋插值表達式
v-text把值當成普通字符串顯示, v-html把值當做html解析- v-text=“vue數據變量”
- v-html=“vue數據變量”
<template><div><p v-text="str"></p><p v-html="str"></p></div>
</template><script>
export default {data() {return {str: "<span>我是一個span標簽</span>"}}
}
</script>
- v-show和v-if控制標簽的隱藏或出現
- v-show=“vue變量”
- v-if=“vue變量”
原理:
- v-show 用的display:none隱藏 (適用于:頻繁切換使用)
- v-if-else 直接從DOM樹上移除
<template><div><h1 v-show="isOk">v-show的盒子</h1><h1 v-if="isOk">v-if的盒子</h1><div><p v-if="age > 18">我成年了</p><p v-else>還得多吃飯</p></div></div>
</template><script>
export default {data() {return {isOk: true,age: 15}}
}
</script><!-- 例子:折疊面板-->
<template><div id="app"><h3>案例:折疊面板</h3><div><div class="title"><h4>芙蓉樓送辛漸</h4><span class="btn" >收起</span></div><div class="container"><p>寒雨連江夜入吳,</p><p>平明送客楚山孤。</p><p>洛陽親友如相問,</p><p>一片冰心在玉壺。</p></div></div></div>
</template><script>
export default {data() {return {}}
}
</script><style lang="less">
body {background-color: #ccc;#app {width: 400px;margin: 20px auto;background-color: #fff;border: 4px solid blueviolet;border-radius: 1em;box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.5);padding: 1em 2em 2em;h3 {text-align: center;}.title {display: flex;justify-content: space-between;align-items: center;border: 1px solid #ccc;padding: 0 1em;}.title h4 {line-height: 2;margin: 0;}.container {border: 1px solid #ccc;padding: 0 1em;}.btn {/* 鼠標改成手的形狀 */cursor: pointer;}}
}
</style>
使用less語法,需要加載less相應模塊
yarn add less@3.0.4 less-loader@5.0.0 -D
<template><div id="app"><h3>案例:折疊面板</h3><div><div class="title"><h4>芙蓉樓送辛漸</h4><span class="btn" @click="isShow = !isShow">{{ isShow ? '收起' : '展開' }}</span></div><div class="container" v-show="isShow"><p>寒雨連江夜入吳, </p><p>平明送客楚山孤。</p><p>洛陽親友如相問,</p><p>一片冰心在玉壺。</p></div></div></div>
</template><script>
export default {data() {return {isShow: false}}
}
</script>
- v-for
vue最常用指令, 鋪設頁面利器, 快速把數據賦予到相同的dom結構上循環生成
列表渲染, 所在標簽結構, 按照數據數量, 循環生成。 目標結構:數組 / 對象 / 數字 / 字符串 (可遍歷結構)- v-for=“(值, 索引) in 目標結構”
- v-for=“值 in 目標結構”
注意: v-for的臨時變量名不能用到v-for范圍外
<template><div id="app"><div id="app"><!-- v-for 把一組數據, 渲染成一組DOM --><!-- 口訣: 讓誰循環生成, v-for就寫誰身上 --><p>學生姓名</p><ul><li v-for="(item, index) in arr" :key="item">{{ index }} - {{ item }}</li></ul><p>學生詳細信息</p><ul><li v-for="obj in stuArr" :key="obj.id"><span>{{ obj.name }}</span><span>{{ obj.sex }}</span><span>{{ obj.hobby }}</span></li></ul><!-- v-for遍歷對象(了解) --><p>老師信息</p><div v-for="(value, key) in tObj" :key="value">{{ key }} -- {{ value }}</div><!-- v-for遍歷整數(了解) - 從1開始 --><p>序號</p><div v-for="i in count" :key="i">{{ i }}</div></div></div>
</template><script>
export default {data() {return {arr: ["小明", "小歡歡", "大黃"],stuArr: [{id: 1001,name: "孫悟空",sex: "男",hobby: "吃桃子",},{id: 1002,name: "豬八戒",sex: "男",hobby: "背媳婦",},],tObj: {name: "小黑",age: 18,class: "1期",},count: 10,};},
};
</script><!-- 例子 -->
<template><div id="app"><ul><li v-for="item in myArr" :key="item">{{ item }}</li></ul><button @click="btn">走一走</button></div>
</template><script>
export default {data() {return {myArr: ["帥哥", "美女", "程序猿"],};},methods: {btn() {// 頭部數據加入到末尾this.myArr.push(this.myArr[0]);// 再把頭部的數據刪除掉this.myArr.shift();},},
};
</script><template><div id="app"><ul><li v-for="(item, ind) in arr" :key="item"><span>{{ item }}</span><button @click="del(ind)">刪除</button></li></ul><button @click="add">生成</button></div>
</template><script>
export default {data() {return {arr: [1, 5, 3],};},methods: {add() {this.arr.push(Math.floor(Math.random() * 20));},del(index) {this.arr.splice(index, 1);},},
};
</script><template><div id="app"><table class="tb"><tr><th>編號</th><th>品牌名稱</th><th>創立時間</th><th>操作</th></tr><!-- 循環渲染的元素tr --><tr v-for="(item,index) in list" :key="item.id"><td>{{item.id}}</td><td>{{item.name}}</td><td>{{item.time}}</td><td><button @click="del(index)">刪除</button></td></tr><tr v-if="list.length === 0"><td colspan="4">沒有數據咯~</td></tr></table></div>
</template><script>
export default {data() {return {list: [{ id: 1, name: "奔馳", time: "2020-08-01" },{ id: 2, name: "寶馬", time: "2020-08-02" },{ id: 3, name: "奧迪", time: "2020-08-03" },],};},methods: {del(index) {// 刪除按鈕 - 得到索引, 刪除數組里元素this.list.splice(index, 1);},},
};
</script>
v-for=“i in count” :key=“i” 里為什么“非要”加 key,其實是和 Vue 的 性能優化機制有關。推薦使用唯一的、穩定的值作為 key
在使用 v-for 渲染列表時,Vue 需要在 更新 DOM 時判斷哪些元素該重用、哪些該添加、哪些該刪除。加了 key,Vue 才能:更高效地更新列表(知道哪個項變了、哪個刪了)、保證組件狀態穩定(比如 < input> 不會錯位)、減少不必要的 DOM 操作
如果你不給每個元素一個獨一無二的 key,Vue 就會用一種叫 “就地復用” 的策略:簡單地按順序復用已有的 DOM 元素,不管它們代表什么數據。這有時會導致非常奇怪的行為
<input v-for="item in items" :value="item.name">
如果你改變了 items 的順序,而沒設置 key,輸入框的值可能會錯亂,因為 DOM 元素被“錯誤地復用了”。
- 為什么避免v-for和v-if在一起使用
? Vue 處理指令時,v-for 比 v-if 具有更高的優先級, 雖然用起來也沒報錯好使, 但是性能不高, 如果你有5個元素被v-for循環, v-if也會分別執行5次.
舉例子:
<div v-for="item in items" v-if="item.visible">{{ item.name }}
</div>
這段代碼 Vue 是怎么處理的?
Vue 先處理 v-for,然后才處理 v-if。
意思是:先把 items 數組的每一項都“跑一遍”(v-for),對每一項再判斷一下 item.visible 是不是 true(v-if);
v-for 會讓 Vue 創建 全部渲染實例(哪怕最后你只顯示了其中幾個),因為它不知道哪些會被 v-if 過濾掉,所以它都要先處理一遍,再做判斷。
* 為什么這會影響性能?
想象一下如果 items 不是 5 個,而是 5000 個,那 Vue 就會:
先“跑一遍”5000 個元素
然后對每個元素都做 v-if 判斷
雖然你最后可能只顯示 10 個,但 Vue 干的活其實是 5000 次。
- 推薦寫法
把過濾邏輯放到 computed 或 template 外面!
<template><div v-for="item in visibleItems">{{ item.name }}</div>
</template><script>
export default {computed: {visibleItems() {return this.items.filter(item => item.visible);}}
}
</script>