官网地址:
vue开发版本:
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
vue 生成版本:(min版本)
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.min.js"></script>
cdn版本:
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script>
vue2 hello world 小案例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Hello World with Vue</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> </head> <body> <div id="app"> {{ message }} </div> <script> // 创建Vue实例 new Vue({ el: '#app', // 绑定Vue实例到id为'app'的DOM元素上 data: { message: 'Hello, World!' // 定义数据属性 } }); </script> </body> </html>
vue模板语法:----1插值---文本插值:
<div>{{ message }}</div>
vue模板语法:---1插值---原始html: (这个v-html的意思是不放在{{****}}展示,而是在标签中展示)
<div v-html="rawHtml"></div>
vue模板语法:----2指令---条件渲染
<div v-if="seen">Now you see me</div> <div v-else>Now you don't</div>
vue模板语法:----2指令---列表渲染
<ul> <li v-for="item in items" :key="item.id">{{ item.text }}</li> </ul>
vue模板语法:----2指令----事件监听:
<button v-on:click="doSomething">Click me</button>
vue模板语法:---2指令----双向绑定:
<input v-model="message">
vue模板语法:---3属性绑定:
<img v-bind:src="imageSrc">
vue模板语法:----4计算属性:
<div>{{ reversedMessage }}</div>
computed: { reversedMessage: function () { return this.message.split('').reverse().join('') } }
vue模板语法:----4监听器
watch: { message: function (newVal, oldVal) { console.log('Message changed from', oldVal, 'to', newVal); } }
vue模板语法:---5样式绑定---class
<div :class="{ active: isActive }"></div>
vue模板语法:----5样式绑定---style:
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
vue模板语法:--6条件+循环:
<ul> <li v-for="item in items" v-if="item.show">{{ item.text }}</li> </ul>
vue模板语法: 完整的html示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue Template Syntax Example</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> </head> <body> <div id="app"> <h1>{{ message }}</h1> <p v-html="rawHtml"></p> <p v-if="seen">You can see me</p> <p v-else>You cannot see me</p> <ul> <li v-for="item in items" :key="item.id">{{ item.text }}</li> </ul> <button v-on:click="doSomething">Click me</button> <input v-model="message"> <div :class="{ active: isActive }">Class Binding</div> <div :style="{ color: activeColor, fontSize: fontSize + 'px' }">Style Binding</div> </div> <script> new Vue({ el: '#app', data: { message: 'Hello, Vue!', rawHtml: '<strong>This is bold!</strong>', seen: true, items: [ { id: 1, text: 'Item 1' }, { id: 2, text: 'Item 2' }, { id: 3, text: 'Item 3' } ], isActive: true, activeColor: 'red', fontSize: 30 }, methods: { doSomething() { alert('Button clicked!'); } }, computed: { reversedMessage: function () { return this.message.split('').reverse().join(''); } }, watch: { message: function (newVal, oldVal) { console.log('Message changed from', oldVal, 'to', newVal); } } }); </script> </body> </html>
数据绑定----单向数据绑定
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue v-bind:value Example</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> </head> <body> <div id="app"> <p>Initial Value: {{ message }}</p> <input v-bind:value="message" readonly> </div> <script> new Vue({ el: '#app', data: { message: 'Hello, Vue!' } }); </script> </body> </html>
数据绑定---双向数据绑定
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue v-model Example</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> </head> <body> <div id="app"> <p>Current Value: {{ message }}</p> <input v-model="message"> </div> <script> new Vue({ el: '#app', data: { message: 'Hello, Vue!' } }); </script> </body> </html>
解释一下MVVM:
M模型
V视图
VM视图模型 。ViewModel 是视图和模型之间的桥梁,负责处理界面逻辑。
解释说明Object.defineProperty: 给一个对象增加属性
let person = { firstName: 'John', lastName: 'Doe' }; Object.defineProperty(person, 'fullName', { get() { return `${this.firstName} ${this.lastName}`; }, set(newValue) { const parts = newValue.split(' '); if (parts.length === 2) { this.firstName = parts[0]; this.lastName = parts[1]; } else { throw new Error('Invalid name format'); } }, enumerable: true, configurable: true }); console.log(person.fullName); // John Doe person.fullName = 'Jane Smith'; console.log(person.firstName); // Jane console.log(person.lastName); // Smith // 试图重新定义属性时不会报错,因为 configurable: true Object.defineProperty(person, 'fullName', { enumerable: false }); console.log(Object.keys(person)); // ["firstName", "lastName"] (fullName 不再可枚举) // 再次尝试修改 fullName 属性时将不会生效,因为它已经被重新定义为不可枚举 try { person.fullName = 'Alice Johnson'; } catch (e) { console.error(e.message); // 不会触发 } console.log(person.fullName); // 仍然输出 Jane Smith
模拟vue.js中的数据代理:
数据代理是一种在对象中创建对另一个对象属性的访问和操作方法的技术
function createProxy(obj, key, target) { Object.defineProperty(obj, key, { get() { return target[key]; }, set(value) { target[key] = value; }, enumerable: true, configurable: true }); } // 创建一个对象 let data = { message: 'Hello, World!' }; // 创建一个代理对象 let proxy = {}; // 为代理对象添加数据代理 createProxy(proxy, 'message', data); // 访问代理对象的属性 console.log(proxy.message); // Hello, World! // 修改代理对象的属性 proxy.message = 'Hello, Vue!'; console.log(data.message); // Hello, Vue! // 直接访问和修改原对象的数据 data.message = 'Hello, JavaScript!'; console.log(proxy.message); // Hello, JavaScript!
如何理解Vue中的数据代理?
vue之所以可以 在vue中设置data属性,并且在插值中进行显示,是因为object.defineProperty的数据代理。也就是vue的实例中有对其他对象的get和set的操作。
vue2中的事件处理:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue 2 Event Handling</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script>
</head>
<body>
<div id="app">
<p>{{ message }}</p>
<button @click="updateMessage">Click me</button>
</div>
<script>
// 创建 Vue 实例
new Vue({
el: '#app',
data: {
message: 'Hello, Vue!'
},
methods: {
updateMessage() {
this.message = 'You clicked the button!';
}
}
});
</script>
</body>
</html>
vue中的事件修饰符:
常见事件修饰符
.stop
:调用event.stopPropagation()
,阻止事件冒泡。.prevent
:调用event.preventDefault()
,阻止默认行为。.capture
:添加事件侦听器时使用捕获模式。.self
:只有事件目标是侦听器绑定的元素自身时触发回调。.once
:事件只触发一次。.passive
:告诉浏览器event.preventDefault()
不会被调用。<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue 2 Event Modifiers</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> </head> <body> <div id="app"> <!-- 阻止事件冒泡 --> <button @click.stop="handleClick">Click me (stop)</button> <!-- 阻止默认行为 --> <form @submit.prevent="handleSubmit"> <button type="submit">Submit (prevent)</button> </form> <!-- 使用捕获模式 --> <div @click.capture="handleClickCapture">Click me (capture)</div> <!-- 事件目标是自身时触发 --> <div @click.self="handleClickSelf">Click me (self)</div> <!-- 事件只触发一次 --> <button @click.once="handleClickOnce">Click me (once)</button> </div> <script> // 创建 Vue 实例 new Vue({ el: '#app', methods: { handleClick() { alert('Button clicked!'); }, handleSubmit() { alert('Form submitted!'); }, handleClickCapture() { alert('Captured click event!'); }, handleClickSelf() { alert('Clicked self!'); }, handleClickOnce() { alert('Button clicked once!'); } } }); </script> </body> </html>
vue中的键盘事件:
常见的键盘事件修饰符
.enter
:按下 Enter 键.tab
:按下 Tab 键.delete
(捕获 "删除" 和 "退格" 键):按下 Delete 键.esc
:按下 Esc 键.space
:按下 Space 键.up
:按下 Up 键.down
:按下 Down 键.left
:按下 Left 键.right
:按下 Right 键<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue Keyboard Events</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> </head> <body> <div id="app"> <input type="text" v-model="inputValue" @keyup.enter="handleEnter" @keyup.esc="handleEsc" @keyup.space="handleSpace"> <p>Current Input: {{ inputValue }}</p> </div> <script> new Vue({ el: '#app', data: { inputValue: '' }, methods: { handleEnter() { alert('Enter key pressed! Current input: ' + this.inputValue); }, handleEsc() { this.inputValue = ''; }, handleSpace() { alert('Space key pressed!'); } } }); </script> </body> </html>
事件修饰符prevent:(阻止表单的默认提交行为)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue 2 Form Submit Prevent</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> </head> <body> <div id="app"> <form @submit.prevent="handleSubmit"> <label for="name">Name:</label> <input type="text" v-model="name" id="name" required> <button type="submit">Submit</button> </form> <p>Submitted Name: {{ submittedName }}</p> </div> <script> // 创建 Vue 实例 new Vue({ el: '#app', data: { name: '', submittedName: '' }, methods: { handleSubmit() { this.submittedName = this.name; alert('Form submitted with name: ' + this.name); } } }); </script> </body> </html>
计算属性 举例:
示例:使用计算属性生成全名
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue 2 Computed Property</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> </head> <body> <div id="app"> <form @submit.prevent="handleSubmit"> <label for="firstName">First Name:</label> <input type="text" v-model="firstName" id="firstName" required> <label for="lastName">Last Name:</label> <input type="text" v-model="lastName" id="lastName" required> <button type="submit">Submit</button> </form> <p>Full Name: {{ fullName }}</p> <p>Submitted Full Name: {{ submittedFullName }}</p> </div> <script> // 创建 Vue 实例 new Vue({ el: '#app', data: { firstName: '', lastName: '', submittedFullName: '' }, computed: { fullName() { return this.firstName + ' ' + this.lastName; } }, methods: { handleSubmit() { this.submittedFullName = this.fullName; alert('Form submitted with full name: ' + this.fullName); } } }); </script> </body> </html>
计算属性的特点:(相比为什么不用插值语法和methods?)
插值语法无法处理繁琐的工作量的操作。
methods每次使用都会触发方法。
计算属性:根据本身有的data中的属性进行再加工,并且只调用一次。
计算属性中的仅有get的写法:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue 2 Computed Property with Getter</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> </head> <body> <div id="app"> <form @submit.prevent="handleSubmit"> <label for="firstName">First Name:</label> <input type="text" v-model="firstName" id="firstName" required> <label for="lastName">Last Name:</label> <input type="text" v-model="lastName" id="lastName" required> <button type="submit">Submit</button> </form> <p>Full Name: {{ fullName }}</p> <p>Submitted Full Name: {{ submittedFullName }}</p> </div> <script> new Vue({ el: '#app', data: { firstName: '', lastName: '', submittedFullName: '' }, computed: { fullName() { return this.firstName + ' ' + this.lastName; } }, methods: { handleSubmit() { this.submittedFullName = this.fullName; alert('Form submitted with full name: ' + this.fullName); } } }); </script> </body> </html>
计算属性中的get和set同时的写法:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue 2 Computed Property with Getter and Setter</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> </head> <body> <div id="app"> <form @submit.prevent="handleSubmit"> <label for="firstName">First Name:</label> <input type="text" v-model="firstName" id="firstName" required> <label for="lastName">Last Name:</label> <input type="text" v-model="lastName" id="lastName" required> <button type="submit">Submit</button> </form> <p>Full Name: {{ fullName }}</p> <p>Submitted Full Name: {{ submittedFullName }}</p> <p> <label for="fullNameInput">Set Full Name:</label> <input type="text" v-model="fullName" id="fullNameInput"> </p> </div> <script> new Vue({ el: '#app', data: { firstName: '', lastName: '', submittedFullName: '' }, computed: { fullName: { // getter get() { return this.firstName + ' ' + this.lastName; }, // setter set(newValue) { const names = newValue.split(' '); this.firstName = names[0] || ''; this.lastName = names[1] || ''; } } }, methods: { handleSubmit() { this.submittedFullName = this.fullName; alert('Form submitted with full name: ' + this.fullName); } } }); </script> </body> </html>
监视属性watch:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue 2 Watch Property Example</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> </head> <body> <div id="app"> <label for="firstName">First Name:</label> <input type="text" v-model="firstName" id="firstName"> <label for="lastName">Last Name:</label> <input type="text" v-model="lastName" id="lastName"> <p>Full Name: {{ fullName }}</p> <p>Previous First Name: {{ previousFirstName }}</p> </div> <script> new Vue({ el: '#app', data: { firstName: '', lastName: '', previousFirstName: '' }, computed: { fullName() { return this.firstName + ' ' + this.lastName; } }, watch: { // 监视 firstName 的变化 firstName(newVal, oldVal) { this.previousFirstName = oldVal; console.log(`First Name changed from ${oldVal} to ${newVal}`); } } }); </script> </body> </html>
写一个深度监视的例子:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue 2 Deep Watch Example</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> </head> <body> <div id="app"> <label for="user">User:</label> <input type="text" v-model="user.name" id="user" placeholder="Enter Name"> <p>User Name: {{ user.name }}</p> <p>User Age: {{ user.age }}</p> <p>User Details: {{ userDetails }}</p> </div> <script> new Vue({ el: '#app', data: { user: { name: '', age: 0 }, userDetails: '' }, watch: { user: { handler(newVal, oldVal) { this.userDetails = JSON.stringify(newVal); console.log('User object changed:', newVal); }, deep: true } } }); </script> </body> </html>
绑定class样式:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue 2 Class Binding Example</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> <style> .active { color: green; font-weight: bold; } .error { color: red; } </style> </head> <body> <div id="app"> <h1 :class="{ active: isActive, error: hasError }">Hello World</h1> <button @click="toggleActive">Toggle Active</button> <button @click="toggleError">Toggle Error</button> </div> <script> new Vue({ el: '#app', data: { isActive: true, hasError: false }, methods: { toggleActive() { this.isActive = !this.isActive; }, toggleError() { this.hasError = !this.hasError; } } }); </script> </body> </html>
绑定style样式:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue 2 Style Binding Example</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> <style> .box { width: 100px; height: 100px; border: 1px solid #000; } </style> </head> <body> <div id="app"> <div class="box" :style="boxStyle"></div> <button @click="changeColor">Change Color</button> <button @click="increaseSize">Increase Size</button> </div> <script> new Vue({ el: '#app', data: { backgroundColor: 'red', size: 100 }, computed: { boxStyle() { return { backgroundColor: this.backgroundColor, width: this.size + 'px', height: this.size + 'px' }; } }, methods: { changeColor() { this.backgroundColor = this.backgroundColor === 'red' ? 'blue' : 'red'; }, increaseSize() { this.size += 20; } } }); </script> </body> </html>
vue2中的条件渲染:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue 2 Conditional Rendering Example</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> <style> .hidden { display: none; } </style> </head> <body> <div id="app"> <h1>Vue 2 Conditional Rendering Example</h1> <!-- v-if / v-else-if / v-else Example --> <div> <p>v-if / v-else-if / v-else Example:</p> <button @click="toggleStatus">Toggle Status</button> <p v-if="status === 'success'">Success!</p> <p v-else-if="status === 'warning'">Warning!</p> <p v-else>Error!</p> </div> <!-- v-show Example --> <div> <p>v-show Example:</p> <button @click="toggleVisibility">Toggle Visibility</button> <p v-show="isVisible">This paragraph is conditionally rendered using v-show.</p> </div> <!-- v-if with v-for Example --> <div> <p>v-if with v-for Example:</p> <ul> <li v-for="item in items" :key="item.id" v-if="item.visible">{{ item.text }}</li> </ul> </div> <!-- v-if with v-else Example --> <div> <p>v-if with v-else Example:</p> <p v-if="isLoggedIn">Welcome, User!</p> <p v-else>Please log in.</p> </div> </div> <script> new Vue({ el: '#app', data: { status: 'success', isVisible: true, isLoggedIn: false, items: [ { id: 1, text: 'Item 1', visible: true }, { id: 2, text: 'Item 2', visible: false }, { id: 3, text: 'Item 3', visible: true } ] }, methods: { toggleStatus() { if (this.status === 'success') { this.status = 'warning'; } else if (this.status === 'warning') { this.status = 'error'; } else { this.status = 'success'; } }, toggleVisibility() { this.isVisible = !this.isVisible; } } }); </script> </body> </html>
vue2列表渲染:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue 2 Object Rendering Example</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> </head> <body> <div id="app"> <h1>Vue 2 Object Rendering Example</h1> <!-- Object Rendering --> <ul> <li v-for="(value, key, index) in object" :key="index"> {{ key }}: {{ value }} </li> </ul> </div> <script> new Vue({ el: '#app', data: { object: { name: 'John Doe', age: 30, city: 'New York' } } }); </script> </body> </html>
列表过滤:(使用filter)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue 2 List Filtering Example</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> </head> <body> <div id="app"> <h1>Vue 2 List Filtering Example</h1> <!-- Input for Filtering --> <input v-model="search" placeholder="Search items..."> <!-- Render Filtered List --> <ul> <li v-for="item in filteredItems" :key="item.id"> {{ item.name }} - {{ item.quantity }} </li> </ul> </div> <script> new Vue({ el: '#app', data: { search: '', items: [ { id: 1, name: 'Apple', quantity: 10 }, { id: 2, name: 'Banana', quantity: 20 }, { id: 3, name: 'Cherry', quantity: 30 }, { id: 4, name: 'Date', quantity: 15 }, { id: 5, name: 'Elderberry', quantity: 5 } ] }, computed: { filteredItems() { return this.items.filter(item => { return item.name.toLowerCase().includes(this.search.toLowerCase()); }); } } }); </script> </body> </html>
列表过滤+排序:filter+sort
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue 2 List Filtering and Sorting Example</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> </head> <body> <div id="app"> <h1>Vue 2 List Filtering and Sorting Example</h1> <!-- Input for Filtering --> <!-- 绑定 search 输入框的值,用于实时过滤列表 --> <input v-model="search" placeholder="Search items..."> <!-- Select for Sorting --> <!-- 绑定 sortKey 和 sortOrder 选择框的值,用于排序列表 --> <select v-model="sortKey"> <option value="name">Name</option> <option value="quantity">Quantity</option> </select> <select v-model="sortOrder"> <option value="asc">Ascending</option> <option value="desc">Descending</option> </select> <!-- Render Filtered and Sorted List --> <!-- 使用 v-for 遍历 filteredAndSortedItems 计算属性,并渲染列表项 --> <ul> <li v-for="item in filteredAndSortedItems" :key="item.id"> {{ item.name }} - {{ item.quantity }} </li> </ul> </div> <script> // 创建 Vue 实例 new Vue({ el: '#app', // 绑定 Vue 实例的 HTML 元素 data: { // 定义数据属性 search: '', // 搜索关键字 sortKey: 'name', // 排序键,默认按名称排序 sortOrder: 'asc', // 排序顺序,默认升序 // 列表数据项 items: [ { id: 1, name: 'Apple', quantity: 10 }, { id: 2, name: 'Banana', quantity: 20 }, { id: 3, name: 'Cherry', quantity: 30 }, { id: 4, name: 'Date', quantity: 15 }, { id: 5, name: 'Elderberry', quantity: 5 } ] }, computed: { // 定义计算属性,用于过滤和排序列表 filteredAndSortedItems() { // 先进行过滤操作 let filteredItems = this.items.filter(item => { // 通过搜索关键字过滤列表项 return item.name.toLowerCase().includes(this.search.toLowerCase()); }); // 然后进行排序操作 let sortedItems = filteredItems.sort((a, b) => { // 根据排序顺序设置排序修饰符 let modifier = this.sortOrder === 'asc' ? 1 : -1; // 比较当前排序键的值 if (a[this.sortKey] < b[this.sortKey]) return -1 * modifier; if (a[this.sortKey] > b[this.sortKey]) return 1 * modifier; return 0; }); // 返回过滤和排序后的列表 return sortedItems; } } }); </script> </body> </html>
使用Vue.set给对象添加属性:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue.set Example</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> </head> <body> <div id="app"> <h1>Vue.set Example</h1> <!-- Display object properties --> <p>Initial Properties:</p> <ul> <li v-for="(value, key) in user" :key="key">{{ key }}: {{ value }}</li> </ul> <!-- Input fields to add new property --> <input v-model="newKey" placeholder="Enter new key"> <input v-model="newValue" placeholder="Enter new value"> <button @click="addProperty">Add Property</button> <!-- Display updated object properties --> <p>Updated Properties:</p> <ul> <li v-for="(value, key) in user" :key="key">{{ key }}: {{ value }}</li> </ul> </div> <script> new Vue({ el: '#app', // 绑定 Vue 实例的 HTML 元素 data: { // 定义数据属性 user: { name: 'John Doe', // 初始属性 age: 30 }, newKey: '', // 新属性的键 newValue: '' // 新属性的值 }, methods: { // 添加新属性的方法 addProperty() { if (this.newKey && this.newValue) { // 使用 Vue.set 确保新属性是响应式的 Vue.set(this.user, this.newKey, this.newValue); // 清空输入框 this.newKey = ''; this.newValue = ''; } } } }); </script> </body> </html>
写一个表单:(输入框 单选框 多选框 下拉框 文本框 选择框 提交按钮)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue 2 Form Example</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> </head> <body> <div id="app"> <h1>Vue 2 Form Example</h1> <!-- 表单开始 --> <form @submit.prevent="handleSubmit"> <!-- 账号 --> <div> <label for="username">账号:</label> <input type="text" id="username" v-model="form.username" required> </div> <!-- 密码 --> <div> <label for="password">密码:</label> <input type="password" id="password" v-model="form.password" required> </div> <!-- 性别 --> <div> <label>性别:</label> <label><input type="radio" value="男" v-model="form.gender"> 男</label> <label><input type="radio" value="女" v-model="form.gender"> 女</label> </div> <!-- 爱好 --> <div> <label>爱好:</label> <label><input type="checkbox" value="读书" v-model="form.hobbies"> 读书</label> <label><input type="checkbox" value="看报" v-model="form.hobbies"> 看报</label> <label><input type="checkbox" value="运动" v-model="form.hobbies"> 运动</label> </div> <!-- 所属校区 --> <div> <label for="campus">所属校区:</label> <select id="campus" v-model="form.campus"> <option value="校区A">校区A</option> <option value="校区B">校区B</option> <option value="校区C">校区C</option> </select> </div> <!-- 其他信息 --> <div> <label for="additionalInfo">其他信息:</label> <textarea id="additionalInfo" v-model="form.additionalInfo"></textarea> </div> <!-- 选择框 --> <div> <label><input type="checkbox" v-model="form.agreement" required> 阅读并接受协议</label> </div> <!-- 提交按钮 --> <div> <button type="submit">提交</button> </div> </form> <!-- 提交结果显示 --> <div v-if="submitted"> <h2>提交结果:</h2> <pre>{{ form }}</pre> </div> </div> <script> new Vue({ el: '#app', data: { // 表单数据对象 form: { username: '', // 账号 password: '', // 密码 gender: '', // 性别 hobbies: [], // 爱好 campus: '', // 所属校区 additionalInfo: '', // 其他信息 agreement: false // 阅读并接受协议 }, submitted: false // 提交状态 }, methods: { // 表单提交处理 handleSubmit() { // 检查表单是否有效 if (this.form.agreement) { this.submitted = true; // 设置提交状态为真 console.log("表单已提交:", this.form); // 打印表单数据到控制台 } else { alert("请阅读并接受协议"); } } } }); </script> </body> </html>
过滤器:(使用filters----区别列表过滤filter)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue 2 Filters Example</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> </head> <body> <div id="app"> <h1>Vue 2 Filters Example</h1> <!-- 使用过滤器格式化日期 --> <p>原始日期:{{ date }}</p> <p>格式化日期:{{ date | formatDate }}</p> <!-- 使用过滤器转换文本为大写 --> <p>原始文本:{{ message }}</p> <p>大写文本:{{ message | uppercase }}</p> </div> <script> // 创建 Vue 实例 new Vue({ el: '#app', // 绑定 Vue 实例的 HTML 元素 data: { // 定义数据属性 date: new Date(), // 当前日期 message: 'Hello, Vue.js!' // 原始文本 }, filters: { // 自定义格式化日期的过滤器 formatDate(value) { if (!value) return ''; const date = new Date(value); const options = { year: 'numeric', month: '2-digit', day: '2-digit' }; return date.toLocaleDateString(undefined, options); }, // 自定义转换文本为大写的过滤器 uppercase(value) { if (!value) return ''; return value.toUpperCase(); } } }); </script> </body> </html>
vue内置指令有哪些?
指令 描述 缩写 v-bind
绑定 HTML 属性 :attribute="expression"
v-model
双向绑定表单元素的值 无 v-if
条件渲染 无 v-else-if
v-if
的 else-if 分支无 v-else
v-if
的 else 分支无 v-show
条件显示或隐藏元素 无 v-for
循环渲染列表 无 v-on
绑定事件监听器 @event="handler"
v-bind:class
动态绑定 class :class="classObject"
v-bind:style
动态绑定内联样式 :style="styleObject"
v-pre
跳过元素和子元素的编译过程 无 v-cloak
保持编译前的状态,直到实例准备好 无 v-once
只渲染元素和组件一次 无
内置指令 v-text 如何理解?
v-text就是替代插值:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue v-text Example</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> </head> <body> <div id="app"> <h1>Vue v-text Example</h1> <!-- 使用 v-text --> <p v-text="message"></p> </div> <script> new Vue({ el: '#app', data: { message: 'Hello, Vue.js!' } }); </script> </body> </html>
v-html 存在的 XSS 问题
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue v-html XSS Example</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> </head> <body> <div id="app"> <h1>Vue v-html XSS Example</h1> <!-- 使用 v-html --> <div v-html="userInput"></div> </div> <script> new Vue({ el: '#app', data: { // 模拟用户输入的 HTML 内容 userInput: '<p>This is a <strong>bold</strong> text.</p><script>alert("XSS Attack!");</script>' } }); </script> </body> </html>
v-cloak: (要显示的插值晚出现了,就使用v-cloak隐藏)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue v-cloak Example</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script>
<style>
/* 定义 v-cloak 的样式 */
[v-cloak] {
display: none;
}
</style>
</head>
<body>
<div id="app">
<h1 v-cloak>{{ message }}</h1>
</div>
<script>
new Vue({
el: '#app',
data: {
message: 'Hello, Vue.js!'
}
});
</script>
</body>
</html>
v-once: 只渲染一次
v-once
是 Vue 中的一个指令,用于只渲染元素和组件一次。使用v-once
后,元素或组件在初次渲染后不会再重新渲染,这在需要优化性能或者内容不会改变时非常有用。<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue v-once Example</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> </head> <body> <div id="app"> <h1 v-once>{{ message }}</h1> <button @click="changeMessage">Change Message</button> </div> <script> new Vue({ el: '#app', data: { message: 'Hello, Vue.js!' }, methods: { changeMessage() { this.message = 'Message has changed!'; } } }); </script> </body> </html>
v-pre:不进行解析
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue v-pre Example</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> </head> <body> <div id="app"> <h1 v-pre>{{ message }}</h1> <p v-pre> This will not be compiled: {{ rawText }} </p> <p> This will be compiled: {{ message }} </p> </div> <script> new Vue({ el: '#app', data: { message: 'Hello, Vue.js!', rawText: 'This is raw text!' } }); </script> </body> </html>
自定义指令--函数式:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue Custom Directive Example</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> </head> <body> <div id="app"> <h1 v-highlight="'yellow'">This text should be highlighted in yellow.</h1> <h1 v-highlight="'lightgreen'">This text should be highlighted in lightgreen.</h1> </div> <script> // 注册一个全局自定义指令 'highlight' Vue.directive('highlight', function (el, binding) { // 设置元素的背景颜色为传入的值 el.style.backgroundColor = binding.value; }); new Vue({ el: '#app' }); </script> </body> </html>
自定义指令------对象式:
(对象式自定义指令适合需要更细粒度控制的场景,比如需要处理不同的生命周期钩子(bind
、inserted
、update
、componentUpdated
、unbind
)。)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue Custom Directive - Object Example</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> </head> <body> <div id="app"> <h1 v-highlight="'yellow'">This text should be highlighted in yellow.</h1> <h1 v-highlight="'lightgreen'">This text should be highlighted in lightgreen.</h1> </div> <script> // 注册一个全局自定义指令 'highlight' Vue.directive('highlight', { // 指令绑定到元素上时调用 bind(el, binding) { el.style.backgroundColor = binding.value; }, // 插入父节点时调用 inserted(el, binding) { console.log('Element inserted into parent node.'); }, // 所在组件的 VNode 更新时调用 update(el, binding) { el.style.backgroundColor = binding.value; }, // 所在组件的 VNode 及其子 VNode 全部更新后调用 componentUpdated(el, binding) { console.log('Component updated.'); }, // 指令与元素解绑时调用 unbind(el, binding) { console.log('Directive unbound from element.'); } }); new Vue({ el: '#app' }); </script> </body> </html>
vue2生命周期
Vue 实例生命周期钩子
- beforeCreate:实例初始化之后,数据观测和事件配置之前调用。
- created:实例已经创建完成,数据观测和事件配置已经完成,但模板编译和挂载尚未开始。
- beforeMount:在挂载开始之前被调用,相关的
render
函数首次被调用。- mounted:实例挂载完成后调用,这时
el
被新创建的vm.$el
替换。- beforeUpdate:数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。
- updated:由于数据更改导致的虚拟 DOM 重新渲染和打补丁完成之后调用。
- beforeDestroy:实例销毁之前调用。
- destroyed:实例销毁后调用。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue Lifecycle Example</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> </head> <body> <div id="app"> <h1>{{ message }}</h1> <button @click="changeMessage">Change Message</button> <button @click="destroyInstance">Destroy Instance</button> </div> <script> new Vue({ el: '#app', data: { message: 'Hello, Vue.js!' }, methods: { changeMessage() { this.message = 'Message has changed!'; }, destroyInstance() { this.$destroy(); } }, beforeCreate() { console.log('beforeCreate: Vue instance is being created.'); }, created() { console.log('created: Vue instance has been created.'); }, beforeMount() { console.log('beforeMount: Vue instance is about to be mounted.'); }, mounted() { console.log('mounted: Vue instance has been mounted.'); }, beforeUpdate() { console.log('beforeUpdate: Vue instance is about to update.'); }, updated() { console.log('updated: Vue instance has been updated.'); }, beforeDestroy() { console.log('beforeDestroy: Vue instance is about to be destroyed.'); }, destroyed() { console.log('destroyed: Vue instance has been destroyed.'); } }); </script> </body> </html>
什么是非单文件组件和单文件组件:
非单文件组件:1.html(包含多个vue文件)
单文件组件:1.vue
使用Vue.component和Vue.extend的区别
vue.component
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue Global Component Example</title> <script src="https://cdn.jsdelivr.net/npm/vue@2"></script> <style> .component { margin: 20px; padding: 20px; border: 1px solid #ccc; text-align: center; } </style> </head> <body> <div id="app"> <!-- 使用全局注册的组件 --> <global-component></global-component> </div> <script> // 定义并全局注册一个组件 Vue.component('global-component', { template: '<div class="component"><h2>Hello from Global Component!</h2><p>This is a globally registered Vue component.</p></div>' }); // 创建 Vue 实例 new Vue({ el: '#app' }); </script> </body> </html>
Vue.extend
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue Extend Example</title> <script src="https://cdn.jsdelivr.net/npm/vue@2"></script> <style> .component { margin: 20px; padding: 20px; border: 1px solid #ccc; text-align: center; } </style> </head> <body> <div id="app"> <!-- 使用局部注册的组件 --> <extended-component></extended-component> </div> <script> // 使用 Vue.extend 创建一个组件构造器 const ExtendedComponent = Vue.extend({ template: '<div class="component"><h2>Hello from Extended Component!</h2><p>This component is created using Vue.extend.</p></div>' }); // 创建 Vue 实例,并局部注册组件 new Vue({ el: '#app', components: { 'extended-component': ExtendedComponent } }); </script> </body> </html>
非单文件包含若干个子组件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue 2 Multiple Components Example</title> <script src="https://cdn.jsdelivr.net/npm/vue@2"></script> <style> .app { text-align: center; } .counter { font-size: 2em; margin-top: 20px; } .buttons { margin-top: 10px; } button { font-size: 1em; padding: 10px; margin: 5px; } </style> </head> <body> <div id="app" class="app"> <header-component></header-component> <counter-component></counter-component> </div> <script> // 定义头部组件 Vue.component('header-component', { template: `<header><h1>Vue 2 多组件示例</h1></header>` }); // 定义计数器组件 Vue.component('counter-component', { data: function() { return { count: 0 }; }, template: ` <div class="counter"> <div>{{ count }}</div> <div class="buttons"> <button @click="decrement">-</button> <button @click="increment">+</button> </div> </div> `, methods: { increment() { this.count++; }, decrement() { this.count--; } } }); // 创建 Vue 实例并挂载到 #app new Vue({ el: '#app' }); </script> </body> </html>
vue2写一个页面,app下嵌套hello组件和school组件,school组件中再嵌套student组件。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue 2 Nested Components Example</title> <script src="https://cdn.jsdelivr.net/npm/vue@2"></script> <style> .component { margin: 20px; padding: 20px; border: 1px solid #ccc; } </style> </head> <body> <div id="root"></div> <!-- Hello Component Template --> <template id="hello-template"> <div class="component"> <h2>Hello Component</h2> <p>Welcome to the Hello Component!</p> </div> </template> <!-- Student Component Template --> <template id="student-template"> <div class="component"> <h4>Student Component</h4> <p>This is the Student Component inside School Component.</p> </div> </template> <!-- School Component Template --> <template id="school-template"> <div class="component"> <h3>School Component</h3> <student-component></student-component> </div> </template> <script> // 定义 hello 组件 const HelloComponent = Vue.extend({ template: '#hello-template' }); // 定义 student 组件 const StudentComponent = Vue.extend({ template: '#student-template' }); // 定义 school 组件 const SchoolComponent = Vue.extend({ template: '#school-template', components: { 'student-component': StudentComponent } }); // 定义主 app 组件 const AppComponent = Vue.extend({ template: ` <div class="component"> <h1>App Component</h1> <hello-component></hello-component> <school-component></school-component> </div> `, components: { 'hello-component': HelloComponent, 'school-component': SchoolComponent } }); // 创建 Vue 实例并挂载到 #root new Vue({ el: '#root', render: h => h(AppComponent) }); </script> </body> </html>
如何理解VueComponent:
vue中使用vue.extends创建组件的时候,自动创建了一个VueComponent的实例对象。这个VueComponent和Vue实例对象很类似。
***.vue 文件如何转为js文件?(因为浏览器不认识vue,只认识js)
1 使用webpack
2 使用vue脚手架
如何在webstorm中使用高亮代码效果:
安装Vetur插件
写一个单文件组件的例子:
<template> <div> <p>学校名称:{{ schoolName }}</p> <p>学校地址:{{ schoolAddress }}</p> <button @click="showSchoolName">点我提示学校名</button> </div> </template> <script> export default { name: 'School', data() { return { schoolName: '示例学校', schoolAddress: '示例地址' }; }, methods: { showSchoolName() { alert(`学校名称是:${this.schoolName}`); } } }; </script> <style scoped> p { font-size: 16px; margin: 5px 0; } button { margin-top: 10px; padding: 5px 10px; font-size: 14px; } </style>
写一个单文件组件结构:(App.vue main.js School.vue Student.vue 其中App.vue包含School和Student main.js包含App)
目录结构:
src/ ├── components/ │ ├── School.vue │ └── Student.vue ├── App.vue └── main.js
school.vue
<template> <div> <p>学校名称:{{ schoolName }}</p> <p>学校地址:{{ schoolAddress }}</p> <button @click="showSchoolName">点我提示学校名</button> </div> </template> <script> export default { name: 'School', data() { return { schoolName: '示例学校', schoolAddress: '示例地址' }; }, methods: { showSchoolName() { alert(`学校名称是:${this.schoolName}`); } } }; </script> <style scoped> p { font-size: 16px; margin: 5px 0; } button { margin-top: 10px; padding: 5px 10px; font-size: 14px; } </style>
student.vue
<template> <div> <p>学生姓名:{{ studentName }}</p> <p>学生年龄:{{ studentAge }}</p> <button @click="showStudentName">点我提示学生名</button> </div> </template> <script> export default { name: 'Student', data() { return { studentName: '张三', studentAge: 18 }; }, methods: { showStudentName() { alert(`学生姓名是:${this.studentName}`); } } }; </script> <style scoped> p { font-size: 16px; margin: 5px 0; } button { margin-top: 10px; padding: 5px 10px; font-size: 14px; } </style>
app.vue
<template> <div id="app"> <School /> <Student /> </div> </template> <script> import School from './components/School.vue'; import Student from './components/Student.vue'; export default { name: 'App', components: { School, Student } }; </script> <style> /* 全局样式 */ #app { font-family: Avenir, Helvetica, Arial, sans-serif; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
main.js
import Vue from 'vue'; import App from './App.vue'; Vue.config.productionTip = false; new Vue({ render: h => h(App), }).$mount('#app');