<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<body>
<!--这是 HTML 中的一个 div 元素,它的 id 是 "app"-->
<div id="app">
<!--这是 Vue.js 的插值表达式,它会被 Vue.js 替换为 Vue 实例中 data 对象的 `message` 属性的值-->
{{ message }}
</div>
<!--这行代码是在 HTML 文件中引入 Vue.js 库。这是使用 Vue.js 的前提-->
<script src="vue.js"></script>
<script>
//创建了一个新的 Vue 实例,并将其赋值给变量 app
//Vue 实例是 Vue.js 应用的基础,每个 Vue 应用都是通过创建一个新的 Vue 实例开始的
var app = new Vue({
//这是 Vue 实例的一个选项,它告诉 Vue 实例要管理的 HTML 元素
//'#app' 是一个选择器,它选择了 id 为 'app' 的元素,也就是我们前面提到的 div 元素
el: '#app',
//这是 Vue 实例的另一个选项,它定义了 Vue 实例的数据模型
//在这个例子中,数据模型只有一个属性 message,其值为 'Hello Vue!'。
data: {
message: 'Hello Vue!'
},
template:`<span> {{ message }}</span>`
})
</script>
</body>
在 Vue.js 中,每一个 Vue 应用都是通过构造函数 Vue
创建一个新的 Vue 实例开始的。
一个 Vue 实例其实与一个 JavaScript 对象非常相似,它接收一个选项对象,其中可以包含各种可选参数,如数据、方法等 以下是一个简单的 Vue 实例的创建过程:
var app = new Vue({
el: '#app',
data: {
message: 'hello'
}
});
在这个例子中,new Vue()
创建了一个新的 Vue 实例。这个实例接收一个选项对象作为参数,该对象中定义了一个 el
属性和一个 data
对象。
el
属性是一个字符串,代表了 Vue 应用要挂载的 HTML 元素的选择器。data
对象包含了应用的数据。在这个例子中,data
对象有一个属性 message
。你可以像操作普通 JavaScript 对象一样操作 Vue 实例。例如,你可以在实例上访问数据、调用方法,以及改变它的数据属性的值。
console.log(app.message); // 'hello'
app.message = 'world!';
console.log(app.message); // 'world'
以上的代码展示了如何访问和改变 Vue 实例的数据。所有在 data
对象中声明的属性都会被 Vue 实例代理,所以你可以直接通过 vm.message
访问和修改 message
属性的值。
在 Vue 实例被创建之后,你也可以使用 $data
属性直接访问原始数据对象,并且修改数据仍会触发视图的更新。
console.log(vm.$data.message); // 'world'
vm.$data.message = 'hello';
console.log(vm.$data.message); // 'hello'
注意,Vue 实例的数据是响应式的:当 data
中的数据变化时,所有依赖这些数据的视图都将立即更新。这让状态管理变得非常直接和易于理解。
<div id="app">
{{ message.split('').reverse().join('')}}
</div>
<script>
var app = new Vue({
el: '#app',
data: {
message: 'hello'
}
})
</script>
Vue.js 中的 v-text
是一个用来更新元素的 textContent
的指令。这个指令的值会被转换为字符串,然后会成为指定元素的文本内容。如果这个值的数据变动了,那么元素的文本内容也会随之更新。
下面是一个简单的例子:
<div id="app">
<span v-text="message"></span>
</div>
<script>
new Vue({
el: '#app',
data: {
message: 'Hello, Vue!'
}
})
</script>
在这个例子中,我们创建了一个新的 Vue 实例,绑定到了 id 为 app
的元素。这个 Vue 实例有一个数据属性 message
,我们用 v-text
指令将这个属性绑定到了一个 <span>
元素的文本内容上。所以,<span>
元素的内容会是 message
的值,即 'Hello, Vue!'
。如果 message
的值发生改变,<span>
元素的内容也会自动更新。
需要注意的是,v-text
会覆盖元素中原有的内容。如果你需要插入一些原有内容,那么你可能需要使用 v-html
指令或者双大括号 {{ }}
插值。但是,在大多数情况下,你应该尽量避免使用 v-html
,因为它会增加跨站脚本攻击(XSS)的风险。
与 {{ }}
插值相比,v-text
不会有闪烁问题(即在 Vue 实例加载完成前,用户会看到未编译的插值标签)。这是因为 v-text
不会将元素的内容插入到插值表达式中,而是直接替换掉元素的内容。
在 Vue.js 中,v-html
是一个用于更新元素的 innerHTML
的指令。不同于 v-text
,该指令可以解析并渲染 HTML 内容。
这是一个简单的 v-html
示例:
<div id="app">
<span v-html="message"></span>
</div>
<script>
new Vue({
el: '#app',
data: {
message: '<strong>Hello, Vue!</strong>'
}
})
</script>
在这个例子中,我们创建了一个新的 Vue 实例,它绑定到了 id 为 app
的元素上。Vue 实例有一个数据属性 message
,我们使用 v-html
指令将这个属性绑定到 <span>
元素的 HTML 内容上。所以,<span>
元素的内容将是 message
的值,即 'Hello, Vue!'。如果 message
的值发生变化,<span>
元素的 HTML 内容也会自动更新。
要注意的是,v-html
会覆盖元素的原始内容。如果你想要在现有内容的基础上插入新的内容,你可能需要其他的解决方案,如使用 Vue 的组件系统。
另一个重要的警告是,你应当避免使用 v-html
来插入用户提供的内容,并且无法保证这些内容的安全性。因为这样做会让你的应用程序暴露于跨站脚本攻击(XSS)的风险。只有在你能够完全信任需要通过 v-html
插入的内容的安全性,或者你已经对内容进行了足够的消毒处理时,才可以使用 v-html
。
v-cloak
是 Vue.js 的一个特殊指令,其作用是隐藏未编译的 Vue.js 标签,直至实例准备就绪。这个指令可以解决初始化渲染慢导致的闪烁问题。
当 Vue.js 应用加载的时候,如果渲染速度稍慢,用户可能会短暂地看到原始的 HTML 模板,例如 {{ message }}
这样的插值表达式,这种现象被称为 "闪烁"。v-cloak
与 CSS 规则配合使用,可以隐藏未编译的 Vue.js 标签,直到编译结束后再显示。
下面是一个简单的例子:
<head>
<script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
<style>
[v-cloak] {
display: none;
}
</style>
</head>
<body>
<div id="app" v-cloak>
{{ message }}
</div>
<script src="vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
message: 'Hello, Vue!'
}
})
</script>
</body>
在这个例子中,我们创建了一个新的 Vue 实例,绑定到了 id 为 app
的元素。我们在这个元素上使用了 v-cloak
指令。然后我们在 CSS 中定义了一个规则,该规则隐藏了所有带有 v-cloak
属性的元素。所以,当 Vue 实例还未准备就绪时,这个元素会被隐藏。当 Vue 实例准备就绪,编译结束后,v-cloak
指令会被删除,元素就会被显示出来。
需要注意的是,v-cloak
会等待 Vue 实例结束编译。如果你的 Vue 应用较大,有很多需要编译的模板,那么可能会出现页面在一段时间内什么也没有的情况。在这种情况下,可能需要考虑使用不同的策略,比如显示一个加载指示器。
在 Vue 2 中,v-pre
是一个特殊的指令,其功能是跳过这个元素及其子元素的编译过程。可以用它来显示原始的 Mustache 标签。当你的元素包含大量静态内容时,使用 v-pre
可以降低编译的开销。
这是一个示例:
<body>
<div id="app" >
<span v-pre>{{ this will not be compiled }}</span>
</div>
<script src="vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
}
})
</script>
</body>
在上述代码中,{{ this will not be compiled }}
文本将被直接渲染,而不会被作为 Vue 模板字符串处理。
需要注意的是,v-pre
指令不仅会跳过元素本身,还会跳过它的所有子元素,所以在使用时需要小心。
在 Vue 2 中,v-bind
是一个非常常见和重要的指令,用于绑定一条表达式到元素的一个属性。
例如,你可以使用 v-bind
指令来动态地绑定 title
属性:
<body>
<div id="app" >
<div v-bind:title="title">title</div>
</div>
<script src="vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
title: 'title'
}
})
</script>
</body>
在上面的例子中,title
是一个在 Vue 实例中定义的数据属性。这个 div
元素的 title
将等于 title
的值。
在 Vue 2 中,methods 是 Vue 实例的一个选项,它包含我们定义的方法。这些方法可以在 Vue 实例的模板中通过事件绑定来调用,也可以在 Vue 实例的其他方法或计算属性中调用。
<div id="app">
<button v-on:click="sayHello">Click me</button>
</div>
<script>
new Vue({
el: '#app',
data: {
greeting: 'Hello Vue!'
},
methods: {
sayHello: function() {
alert(this.greeting);
}
}
})
</script>
在这个例子中,我们创建了一个新的 Vue 实例并将其挂载到 id 为 "app" 的 div 元素上。然后我们定义了一个 data 对象和一个 methods 对象。data 对象包含了我们需要在页面上显示的数据,methods 对象包含了我们在页面上的交互逻辑。我们在模板中的 button 元素上使用 v-on 指令来绑定 sayHello 方法,这样当用户点击这个按钮时,sayHello 方法就会被调用。
在 Vue 2 中,v-on
是一个用于监听 DOM 事件的指令。你可以使用它来触发 JavaScript 方法或者运行一段内联的 JavaScript 代码。这是一个非常重要的功能,因为用户交互(比如点击按钮,提交表单等)是由 DOM 事件来驱动的。
以下是一个使用 v-on
来监听按钮点击事件的例子:
<button v-on:click="sayHello">Say hello</button>
在这个例子中,sayHello
是一个在 Vue 实例的 methods
对象中定义的方法。当用户点击这个按钮时,sayHello
方法将会被调用。
你也可以用 v-on
指令来监听键盘事件、鼠标事件、表单事件等等。只需要改变 v-on
后面的事件名就可以了。
v-on
指令有一个简写形式,就是 @
。例如,v-on:click="sayHello"
可以简写为 @click="sayHello"
。
如果你想要监听的事件比较复杂,或者需要访问到事件对象,你可以在 v-on
指令的表达式中使用特殊的变量 $event
。例如:
<button v-on:click="sayHello($event)">Say hello</button>
在这个例子中,sayHello
方法将接收到一个事件对象作为参数。这个事件对象包含了事件的详细信息,比如事件的类型、触发事件的元素、键盘的按键等等。
你可以像下面这样创建一个新的 Vue 实例并挂载到页面上的一个元素:
<body>
<div id="app">
<button v-on:click="sayHello">Say hello</button>
<p>{{ message }}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
},
methods: {
sayHello: function(event) {
this.message = 'Hello from button click!'
}
}
})
</script>
</body>
在这个例子中,我们创建了一个新的 Vue 实例并将其挂载到 id 为 "app" 的 div 元素上。然后我们定义了一个 data
对象和一个 methods
对象。data
对象包含了我们需要在页面上显示的数据,methods
对象包含了我们在页面上的交互逻辑。
注意,我们需要先通过一个 script 标签引入 Vue.js 库,然后再创建 Vue 实例。
在这个例子中,我们有一个按钮和一个段落文本。点击按钮后,sayHello
方法会被调用,然后将 message
数据属性的值更新为 "Hello from button click!"。因为 message
已经与段落文本绑定,所以段落文本也会自动更新。
在 Vue.js 中,$event
是一个特殊的变量,它用于访问原生 DOM 事件在方法内部的参数。当你需要在方法内访问原生事件对象时,可以使用特殊的 $event
变量。
以下是一个例子:
<body>
<div id="app">
<button v-on:click="handleClick($event)">Click me</button>
</div>
<script>
new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
},
methods: {
handleClick: function (event) {
console.log(event.target); // 打印出点击的按钮元素
}
}
})
</script>
</body>
在这个例子中,v-on:click="handleClick($event)"
会在按钮被点击时触发 handleClick
方法。$event
将被解析为原生 DOM 事件对象,然后作为第一个参数传递给 handleClick
方法。
在 Vue.js 中,.stop
事件修饰符用于阻止事件冒泡。当你在元素上使用 .stop
修饰符时,如果此元素的事件被触发,那么这个事件不会向上冒泡至父元素。
这是一个简单的例子:
<body>
<div id="app">
<div id="parent" @click="parentClicked">
<button id="child" @click.stop="childClicked">Click me</button>
</div>
</div>
<script>
new Vue({
el: '#app',
methods: {
parentClicked() {
alert('Parent clicked!');
},
childClicked() {
alert('Child clicked!');
}
}
});
</script>
</body>
在 Vue 实例中,你可以定义 parentClicked
和 childClicked
这两个方法:
在这个例子中,如果你点击 "Click me" 按钮(即 #child 元素),将会触发 childClicked
方法,并且由于 .stop
修饰符的存在,事件将不会冒泡至 #parent 元素,所以 parentClicked
方法不会被触发。你将只看到 "Child clicked!" 的警告框。
如果你移除 .stop
修饰符,那么点击 "Click me" 按钮将会先触发 childClicked
方法,然后事件冒泡至 #parent 元素,再触发 parentClicked
方法,你将看到两个警告框:"Child clicked!" 和 "Parent clicked!"。
这就是 .stop
事件修饰符的基本用法,它可以帮助你更精确地控制事件的行为,尤其是在复杂的 DOM 结构中。
在 Vue2 中,.prevent
是一个事件修饰符,用于告诉 Vue 的事件系统,我们希望阻止原生事件的默认行为。这对应于在 JavaScript 中调用 event.preventDefault()
。
这个修饰符常用在提交表单的时候,我们可能希望阻止表单的自动提交,而是使用 AJAX 来处理。
下面是一个简单的示例:
<body>
<div id="app">
<form id="myForm">
<input type="text" id="messageInput" />
<button type="submit">Submit</button>
</form>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
message: ''
},
mounted() {
const form = document.getElementById('myForm');
const messageInput = document.getElementById('messageInput');
form.addEventListener('submit', (event) => {
event.preventDefault();
this.message = messageInput.value;
this.submitForm();
});
},
methods: {
submitForm() {
console.log('Form submitted: ', this.message);
}
}
});
</script>
</body>
在这个例子中,我们在 submit
事件上添加了 .prevent
修饰符,这样当用户点击 "Submit" 按钮时,浏览器的默认提交行为(会重新加载页面)就被阻止了。相反,我们的 submitForm
方法会被调用,我们可以在这个方法中处理表单提交,比如通过 AJAX 来提交。
在Vue2中,修饰符被用作一种特殊的指令后缀,它告诉Vue如何在DOM级别处理原生事件。".capture"是其中一种事件修饰符,它使事件监听器在事件捕获模式下触发,而非默认的冒泡模式。
在解释.capture
修饰符之前,我们首先需要了解事件的冒泡和捕获模式。
事件冒泡和捕获:
冒泡模式:在冒泡模式中,事件首先在触发事件的最深的元素(目标元素)开始,然后逐级向上移动,经过所有的父元素,直到document对象。例如,如果你在一个嵌套的元素中点击,那么冒泡模式会首先触发元素本身的点击事件,然后是其父元素的点击事件,然后是其祖父元素的点击事件,以此类推。
捕获模式:捕获模式则是冒泡模式的相反。事件首先在document对象开始,然后逐级向下移动,经过所有的父元素,直到达到触发事件的最深的元素。这就像是事件先经过所有的关卡,然后才到达目标。
.capture
修饰符就是使Vue在捕获模式下监听DOM事件。
下面是一个简单的使用.capture
修饰符的示例:
<body>
<div id="myDiv" @click.capture="handleClick">
<button>Click me</button>
</div>
<script>
new Vue({
el: '#myDiv',
methods: {
handleClick: function() {
alert('div clicked!');
}
}
});
</script>
</body>
在这个例子中,当你点击按钮时,捕获模式确保了div
的点击事件先于按钮的点击事件触发,尽管实际上按钮被点击了。这就是.capture
修饰符的作用。
在 Vue2 中,.self
是一个事件修饰符,用于确保只有当事件在该元素本身(而不是子元素)触发时,才会触发事件回调函数。这对应于 JavaScript 中对事件的目标元素(event.target
)和当前元素(event.currentTarget
)的比较。
这个修饰符常用在你希望事件只在特定元素上触发,而不是在其子元素上触发时。
以下是一个简单的例子:
<body>
<div id="app">
<div @click.capture="captureClick" @click="handleClick">
<button>Click me</button>
</div>
</div>
<script>
new Vue({
el: '#app',
methods: {
captureClick: function () {
alert('div captureClicked!');
},
handleClick: function () {
alert('div clicked!');
}
}
});
</script>
</body>
在这个例子中,divClicked
方法只有在点击 <div>
本身(而不是按钮)时才会被触发。如果你点击 "Click Me" 按钮,事件不会触发,因为 .self
修饰符使得事件只在 <div>
元素上触发。这样可以让你更精确地控制事件的触发位置。
在Vue2中,.once
修饰符用于指定事件监听器在触发一次之后就自动解除绑定,即这个监听器只会被触发一次。
下面是一个简单的使用.once
修饰符的示例:
<body>
<div id="app">
<button @click.once="handleClick">Click me</button>
</div>
<script>
new Vue({
el: '#app',
data: {
counter: 0
},
methods: {
handleClick: function () {
this.counter++;
alert('Button clicked for the ' + this.counter + ' time(s)');
}
}
});
</script>
</body>
在这个例子中,按钮的点击事件只会触发一次。当你点击按钮,浏览器会弹出一个对话框,显示“Button clicked for the 1 time(s)”。但是,如果你再次点击按钮,无论你点击多少次,都不会再次触发事件,因此不会再次弹出对话框。
这就是.once
修饰符的作用。它使你能够方便地限制事件处理器的触发次数,而无需在JavaScript代码中手动解除事件绑定。
在 Vue2 中,.passive
是一个事件修饰符,用于增强性能,特别是在移动端。这对应于在 JavaScript 中对事件调用 addEventListener
方法时使用 { passive: true }
选项。
当你添加了 .passive
修饰符后,你就告诉浏览器你不打算阻止事件的默认行为。这样,浏览器就可以在事件处理程序运行的同时做一些性能优化。这对于一些高频触发的事件(例如滚动或触摸事件)特别有用。
下面是一个简单的示例:
<body>
<div id="app">
<div @scroll.passive="onScroll">
内容
</div>
</div>
<script>
new Vue({
el: '#app',
methods: {
onScroll(event) {
console.log('Scrolled!');
// 处理滚动事件
}
}
});
</script>
</body>
在这个例子中,onScroll
方法会在 <div>
发生滚动时被触发。使用 .passive
修饰符可以在处理滚动事件的同时,优化页面的滚动性能。
但是请注意,因为 .passive
修饰符告诉浏览器你不会阻止事件的默认行为,所以如果你尝试在使用 .passive
修饰符的事件处理程序中调用 event.preventDefault()
,这将无效。
在 Vue2 中,为了处理键盘事件,Vue 提供了一些按键修饰符。这些修饰符允许你在事件触发时更加精确地处理不同的按键。这些修饰符可以在 v-on
或其缩写 @
后使用。
以下是一些常用的按键修饰符:
.enter
:只有在按下 Enter 键时才触发事件处理函数.tab
:只有在按下 Tab 键时才触发事件处理函数.delete
:只有在按下 Delete 或 Backspace 键时才触发事件处理函数.esc
:只有在按下 Esc 键时才触发事件处理函数.space
:只有在按下 Space 键时才触发事件处理函数.up
:只有在按下 Up 键时才触发事件处理函数.down
:只有在按下 Down 键时才触发事件处理函数.left
:只有在按下 Left 键时才触发事件处理函数.right
:只有在按下 Right 键时才触发事件处理函数以下是一个使用 .enter
按键修饰符的示例:
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
<div id="app">
<input @keyup.enter="submit" />
</div>
<script>
new Vue({
el: '#app',
methods: {
submit() {
console.log('Enter key was pressed');
}
}
})
</script>
</body>
</html>
在这个例子中,当在输入框中按下 Enter 键时,submit
方法会被调用。
你也可以使用按键的 ASCII 码作为修饰符,例如 `@keyup.13="submit",其中 13 是 Enter 键的 ASCII 码。但是,使用名字(如
.enter`)通常更容易理解。
请注意,Vue2 也支持系统修饰符(如 .ctrl
、.alt
、.shift
、.meta
),可以与按键修饰符一起使用,例如 `@keydown.ctrl.enter="submit",这样只有在同时按下 Ctrl 键和 Enter 键时,
submit` 方法才会被调用。
在 Vue2 中,为了处理鼠标按钮事件,Vue 提供了一些鼠标按钮修饰符。这些修饰符使你能够在事件触发时更精确地处理不同的鼠标按钮。
以下是一些常用的鼠标按钮修饰符:
.left
:只有在按下鼠标左键时才触发事件处理函数.right
:只有在按下鼠标右键时才触发事件处理函数.middle
:只有在按下鼠标中键时才触发事件处理函数以下是一个使用 .left
鼠标按钮修饰符的示例:
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
<div id="app">
<button @click.left="leftClick">Click me</button>
</div>
<script>
new Vue({
el: '#app',
methods: {
leftClick() {
console.log('Left mouse button was clicked');
}
}
})
</script>
</body>
</html>
在这个例子中,我们创建了一个 Vue 实例,附加到了 ID 为 app
的 div 上。当点击按钮并且是用鼠标左键点击时,leftClick
方法会被调用,控制台将打印出 'Left mouse button was clicked'。
需要注意的是,.left
,.right
和 .middle
这些修饰符只在 Vue 2.2.0 及以上版本中可用。
在 Vue.js 中,methods
是一个特殊的对象,它包含了可以在 Vue 组件中使用的方法。在这些方法中,this
关键字被自动绑定到当前 Vue 实例。
举个例子,假设我们有一个 Vue 组件,它包含一个 data
属性和一个 methods
属性:
new Vue({
el: '#app',
data: {
message: 'Hello, Vue!'
},
methods: {
sayHello: function() {
console.log(this.message);
}
}
});
在这个例子中,sayHello
方法中的 this
指向的是 Vue 实例,所以 this.message
就是 data
中的 message
。因此,当我们调用 sayHello
方法时,它将会打印出 'Hello, Vue!'
。
需要注意的是,this
的绑定只在 Vue 组件的生命周期和事件处理器中是自动的。如果你在其他地方,比如 setTimeout
或 setInterval
的回调函数中使用 this
,你可能需要手动绑定 this
,或者使用箭头函数来保留 this
的绑定。例如:
methods: {
sayHello: function() {
setTimeout(() => {
console.log(this.message);
}, 1000);
}
}
在这个例子中,我们使用了箭头函数,它不会创建自己的 this
绑定,而是继承了外层 sayHello
方法的 this
绑定。因此,this.message
仍然是 data
中的 message
,即使我们在 setTimeout
的回调函数中使用它。
在 Vue.js 中,v-model
是一个非常重要的指令,它可以用来创建双向数据绑定。这意味着,当你在表单元素(如 input 或 textarea)上使用 v-model
指令时,这些元素的值将与 Vue 实例的数据属性绑定在一起。当我们在表单元素中输入值时,Vue 实例的数据属性将会自动更新;反之,当 Vue 实例的数据属性发生变化时,表单元素的值也会相应地更新。
这是一个简单的例子:
<body>
<div id="app">
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
message: 'Hello'
}
})
</script>
</body>
</html>
在上述代码中,input
元素的值与 message
数据属性绑定在一起。当你在 input
元素中输入文本时,message
的值会自动更新,反之亦然。
v-model
在内部实际上是一种语法糖,它将 v-bind
用于 prop 和 v-on
用于事件组合在一起。例如,对于一个 input 元素,v-model="message"
在内部等同于 v-bind:value="message" v-on:input="message = $event.target.value"
。
使用 v-bind
和 v-on
的指令组合来替换 v-model
指令,你的代码将会如下所示:
<head>
<script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
<div id="app">
<input v-bind:value="message" v-on:input="updateMessage($event)" placeholder="edit me">
<p>Message is: {{ message }}</p>
</div>
<script>
new Vue({
el: '#app',
data() {
return {
message: ''
}
},
methods: {
updateMessage(event) {
this.message = event.target.value;
}
}
})
</script>
</body>
这里,v-bind:value="message"
将 message
数据属性绑定到 input
元素的值。然后,v-on:input="updateMessage($event)"
会在每次 input
事件触发(也就是用户输入内容)时更新 message
的值。
为了实现 v-on:input
的功能,我们在 Vue 实例的 methods
对象中定义了一个名为 updateMessage
的方法。这个方法接受一个事件对象作为参数(这里我们用 $event
表示这个事件对象),然后将 message
数据属性设置为 input
元素的当前值(也就是事件对象的 target.value
属性)。
在 Vue 2 中,v-once
是一个特殊的指令,它能够阻止元素和所有的子元素被再次编译。这意味着,元素和所有子元素的 Vue 指令将只会被编译一次,然后将保持原样,不会再发生任何改变。这在你想要优化更新性能的时候会很有用,因为它可以防止不必要的重渲染。
以下是一个简单的示例:
<body>
<div id="app">
<span v-once>This will never change: {{msg}}</span>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
msg: 'hello'
}
})
app.msg = 'world'
</script>
</body>
在上述例子中,msg
数据属性的值将被渲染到 span
元素中,但是因为 v-once
的存在,无论 msg
的值怎么变化,span
元素的内容都不会改变。换句话说,span
元素及其所有子元素的内容和行为在被编译和渲染一次后,将不再改变。
v-once
指令在你知道一些内容永远不会改变,或者出于性能考虑希望减少渲染成本时非常有用。
在 Vue 2 中,v-show
是一个用来控制元素可见性的指令。与 v-if
指令不同,v-show
指令不会真正地添加或移除元素,而是通过 CSS 的 display
属性来切换元素的可见性。
当 v-show
的表达式的值为 true
时,元素会被显示;当值为 false
时,元素会被隐藏。但无论如何,元素始终在 DOM 中。
以下是一个简单的示例:
<body>
<div id="app">
<div v-show="isShowing">Hello Vue!</div>
<button v-on:click="toggleVisibility">Toggle visibility</button>
</div>
<script>
new Vue({
el: '#app',
data: {
isShowing: true
},
methods: {
toggleVisibility: function () {
this.isShowing = !this.isShowing;
}
}
})
</script>
</body>
在这个例子中,当 isShowing
的值为 true
时,div
元素将被显示;当 isShowing
的值为 false
时,div
元素将被隐藏。我们还有一个按钮,点击这个按钮会调用 toggleVisibility
方法,该方法将切换 isShowing
的值。
v-show
指令对于频繁切换元素的可见性来说是一个好的选择,因为它不会导致频繁地添加和移除元素。然而,如果你的元素在初始渲染时就不应该可见,或者不经常改变可见性,那么使用 v-if
指令可能会更好,因为 v-if
指令不会在元素不可见时渲染和占用 DOM 资源。
在 Vue 2 中,v-if
是一个条件指令,用于根据表达式的真假值来决定是否渲染元素。
如果 v-if
的表达式的值为 true
,那么元素将被渲染;如果值为 false
,那么元素将不被渲染。
以下是一个简单的示例:
<body>
<div id="app">
<div v-if="showMessage">Hello Vue!</div>
<button v-on:click="toggleMessage">Toggle message</button>
</div>
<script>
new Vue({
el: '#app',
data: {
showMessage: true
},
methods: {
toggleMessage: function () {
this.showMessage = !this.showMessage;
}
}
})
</script>
</body>
在这个例子中,当 showMessage
的值为 true
时,div
元素将被渲染;当 showMessage
的值为 false
时,div
元素将不被渲染。我们还有一个按钮,点击这个按钮会调用 toggleMessage
方法,该方法将切换 showMessage
的值。
需要注意的是,v-if
是“惰性”的,也就是说,如果在初始渲染时条件为 false
,那么这个元素将不会被渲染,也不会执行任何与之相关的渲染成本。只有当条件第一次变为 true
时,才会开始渲染元素。
另外,你还可以使用 v-else
和 v-else-if
指令来添加更多的条件分支。
<body>
<div id="app">
<div v-if="value === 'A'">Value is A</div>
<div v-else-if="value === 'B'">Value is B</div>
<div v-else>Value is neither A nor B</div>
<button v-on:click="changeValue">Change value</button>
</div>
<script>
new Vue({
el: '#app',
data: {
value: 'A'
},
methods: {
changeValue: function () {
if (this.value === 'A') {
this.value = 'B';
} else if (this.value === 'B') {
this.value = 'C';
} else {
this.value = 'A';
}
}
}
})
</script>
</body>
v-for
是 Vue.js 中的一个内置指令,它用于渲染一个列表。它需要以 item in items
形式的特殊语法,其中 items
是原始数据数组,item
是数组元素迭代的别名。
下面是一个基本的使用示例:
<body>
<div id="app">
<ul >
<li v-for="item in items">
{{ item.message }}
</li>
</ul>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
items: [
{ message: 'hello' },
{ message: 'world' }
]
}
})
</script>
</body>
在这个例子中,Vue.js 会为 items
数组的每个元素创建一个 <li>
元素,并将元素的内容设置为该元素的 message
属性的值。
在 v-for
块中,我们拥有对父作用域属性的完全访问权。v-for
还支持一个可选的第二个参数为当前项的索引。
<body>
<div id="app">
<ul id="container">
<li v-for="(item, index) in items">
{{ index }} - {{ item.message }}
</li>
</ul>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
items: [
{ message: 'hello' },
{ message: 'world' }
]
}
})
</script>
</body>
在这个例子中,我们不仅显示了每个元素的 message
属性的值,还显示了元素在 items
数组中的索引。
需要注意的一点是,当 Vue.js 更新使用 v-for
渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是简单地复用此处每个元素,这是一个默认的性能优化。要强制其重新排序元素,你需要提供一个唯一的 key
属性。
<head>
<script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
<div id="app">
<ul id="container">
<li v-for="(item, index) in items" :key="item.id">
{{ index }} - {{ item.message }}
</li>
</ul>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
items: [
{ message: 'hello' },
{ message: 'world' }
]
}
})
</script>
</body>
在这个例子中,每个 item
都有一个唯一的 id
,这个 id
被用作 key
。这样,即使 items
数组的顺序被改变,Vue.js 也会重新排序 DOM 元素以匹配 items
数组的顺序。
在 Vue 中,<template>
标签是一种基础结构,用于声明 Vue 实例或组件的 HTML 模板。它并不会被包含在最终的 HTML 结构中,它仅仅是一个声明模板的容器。它的内容会被作为 Vue 实例或组件的模板进行编译。
<template>
标签内部可以使用 Vue 的模板语法,包括数据插值、指令、过滤器等等。
以下是一个基础的 Vue 实例使用 <template>
标签的例子:
<body>
<div id="app">
<ul id="container">
<template v-for="(item, index) in items">
<li >
{{ index }} - {{ item.message }}
</li>
<li>
{{ index }} - {{ item.message }}
</li>
</template>
</ul>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
items: [
{ message: 'hello' },
{ message: 'world' }
]
}
})
</script>
</body>
在这个例子中,<template>
标签中的 <p>{{ message }}</p>
就是 Vue 实例的模板。{{ message }}
是 Vue 的数据插值语法,它会被 Vue 实例的 data
中的 message
属性的值替换。
在 Vue.js 中,你可以使用 v-bind:class
(或简写为 :class
)指令来动态绑定 CSS 类名。v-bind:class
可以接收一个对象或数组作为参数,提供一种灵活的方式来设置元素的 CSS 类。
你可以传递一个对象给 v-bind:class
,以动态地切换 CSS 类:
<head>
<script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
<style>
.active{
color: green;
}
</style>
</head>
<body>
<div id="app">
<div :class="{ active: isActive }">内容</div>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
isActive: true
}
})
</script>
</body>
在这个例子中,.active
类的存在与否将取决于数据属性 isActive
的 truthiness(即当 isActive
的值为 truthy 时,.active
类存在,否则不存在)。
你也可以在对象中添加多个字段来动态切换多个类:
<head>
<script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
<style>
.active{
color: green;
}
.inActive{
color: red;
}
</style>
</head>
<body>
<div id="app">
<div :class="{ active: isActive ,inActive: !isActive }">内容</div>
<button @click="changeActive">切换</button>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
isActive: true
},
methods: {
changeActive() {
this.isActive = !this.isActive
}
}
})
</script>
</body>
你可以传递一个数组给 v-bind:class
,以应用一个类列表:
<head>
<script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
<style>
.basic{
background-color: gray;
}
.active{
color: green;
}
</style>
</head>
<body>
<div id="app">
<div :class="[{ active: isActive },'basic']">内容</div>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
isActive: true
}
})
</script>
</body>
在 Vue.js 中,你可以使用 v-bind:style
(或简写为 :style
)指令来动态地绑定内联样式。与 v-bind:class
类似,你可以使用对象语法或数组语法来绑定样式。
你可以直接通过对象语法来设置样式。对象内的属性名就是样式名,可以使用 camelCase 或 kebab-case(需要用引号括起来)。
<head>
<script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
<div id="app">
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }">内容</div>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
activeColor: 'red',
fontSize: 30
}
})
</script>
</body>
在这个例子中,字体颜色将会被设置为 activeColor
,字体大小将会被设置为 fontSize
。
你也可以传递一个数组给 v-bind:style
,以应用多个样式对象:
<head>
<script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
<div id="app">
<div :style="[styleObject1, styleObject2]">内容</div>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
styleObject1: {
color: 'red',
fontSize: '30px'
},
styleObject2: {
fontWeight: 'bold'
}
}
})
</script>
</body>
在这个例子中,styleObject1
和 styleObject2
都是数据对象,它们的属性将被用作 CSS 样式。
以下是一个使用 Vue.js 2 编写的简单的待办事项应用的示例:
HTML 部分:
<body>
<div id="todo-app">
<input v-model="newTodo" @keyup.enter="addTodo">
<ul>
<li v-for="(todo, index) in todos" :key="index">
{{ todo.text }}
<button @click="removeTodo(index)">X</button>
</li>
</ul>
</div>
<script>
var app = new Vue({
el: '#todo-app',
data: {
newTodo: '',
todos: []
},
methods: {
addTodo: function () {
if (this.newTodo.trim() !== '') {
this.todos.push({ text: this.newTodo });
this.newTodo = '';
}
},
removeTodo: function (index) {
this.todos.splice(index, 1);
}
}
});
</script>
</body>
在这个应用中,你可以在输入框中键入一个待办事项,然后按 Enter 键添加待办事项。每个待办事项都会被添加到一个列表中,并且每个待办事项旁边都有一个按钮,你可以点击这个按钮来删除待办事项。
以下是这个应用的工作原理:
v-model="newTodo"
把输入框的值绑定到 newTodo
数据属性。在输入框按下 Enter 键时调用
addTodo` 方法。v-for="(todo, index) in todos"
为 todos
数组中的每个待办事项创建一个列表项,其中 todo
是待办事项,index
是待办事项的索引。{{ todo.text }}
显示待办事项的文本。@click="removeTodo(index)"
在点击按钮时调用 removeTodo
方法,删除对应的待办事项。addTodo
方法会检查 newTodo
是否为空,如果不为空,就把 newTodo
添加到 todos
数组,然后清空 newTodo
。removeTodo
方法会接收一个索引,然后从 todos
数组中删除对应索引的待办事项。
当然可以,以下是一个使用 Vue2 的简单选项卡组件的示例:
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
<div id="app">
<div>
<button v-for="tab in tabs" :key="tab" @click="activeTab = tab">
{{ tab }}
</button>
</div>
<div v-if="activeTab === 'Tab 1'">
Content of Tab 1
</div>
<div v-if="activeTab === 'Tab 2'">
Content of Tab 2
</div>
<div v-if="activeTab === 'Tab 3'">
Content of Tab 3
</div>
</div>
<script>
new Vue({
el: '#app',
data: {
tabs: ['Tab 1', 'Tab 2', 'Tab 3'],
activeTab: 'Tab 1'
}
})
</script>
</body>
</html>
在这个例子中,我们创建了一个 Vue 实例,附加到了 ID 为 app
的 div 上。我们有一个名为 tabs
的数据项,包含三个选项卡的名称。activeTab
数据项保存当前活动的选项卡的名称。
我们用 v-for
指令为每个选项卡创建一个按钮,并在点击按钮时将 activeTab
设置为该选项卡的名称。然后,我们根据 activeTab
的值显示相应选项卡的内容。这是一个基本的选项卡系统的实现,你可以根据需要添加更多的功能或样式。
Vue.js 提供了一些修饰符来帮助处理表单:
.lazy
: 在默认情况下,v-model
在每次 input
事件触发后将输入框的值与数据进行同步。你可以添加 lazy
修饰符,从而将同步改为在 change
事件发生时:
<!-- 在“change”时而非“input”时更新 -->
<input v-model.lazy="msg" >
.number
: 如果想自动将用户的输入值转为 Number 类型(如果原始输入能够被 parseFloat()
解析的话),你可以给 v-model
添加 number
修饰符:
<input v-model.number="age" type="number">
这通常很有用,因为即使在 type="number"
输入框中,HTML 输入元素的值也总是会返回字符串。如果你想要用户输入的就是一个被解析为数字的值,那就使用 v-model.number
。
.trim
: 如果你想自动过滤用户输入的首尾空格,你可以给 v-model
添加 trim
修饰符:
<input v-model.trim="msg">
这些修饰符也可以链式调用:
<input v-model.trim.number.lazy="value">
在上述例子中,用户的输入将会:
.trim
移除开始和结束位置的空格字符.number
将有效的字符串转换为数字.lazy
将在 change
事件时而不是 input
事件时更新<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
<style>
#app {
display: flex;
justify-content: center;
flex: 1;
}
</style>
</head>
<body>
<div id="app">
<form @submit.prevent="submitForm" style="width:15%">
<label>全名:</label>
<input type="text" v-model.lazy.trim="form.name"><br/>
<label>邮箱:</label>
<input type="email" v-model.trim="form.email"><br/>
<label>密码:</label>
<input type="password" v-model="form.password"><br/>
<label>年龄:</label>
<input type="number" v-model.number="form.age"><br/>
<label>性别:</label>
<input type="radio" id="man" value="man" v-model="form.gender">
<label for="man">男</label>
<input type="radio" id="female" value="female" v-model="form.gender">
<label for="female">女</label><br/>
<label>国家:</label>
<select v-model="form.country">
<option v-for="country in COUNTRIES" :value="country.value" :key="country.value">{{ country.title }}</option>
</select><br/>
<label>爱好:</label>
<template v-for="hobby in HOBBIES" :key="hobby.value">
<input type="checkbox" :id="hobby.value" :value="hobby.value" v-model="form.hobbies">
<label :for="hobby.value">{{hobby.title}}</label>
</template><br/>
<label>简介:</label>
<textarea v-model="form.bio"></textarea><br/>
<button type="submit">注册</button>
</form>
<div style="width:15%">
<p>全名: {{ form.name }}</p>
<p>邮箱: {{ form.email }}</p>
<p>密码: {{ form.password }}</p>
<p>年龄: {{ form.age }}</p>
<p>性别: {{ form.gender }}</p>
<p>国家: {{ form.country }}</p>
<p>爱好: {{ form.hobbies.join(', ') }}</p>
<p>简介: {{ form.bio }}</p>
</div>
</div>
<script>
const COUNTRIES = [
{ value: 'cn', title: '中国' },
{ value: 'us', title: '美国' },
{ value: 'uk', title: '英国' }
];
const HOBBIES = [
{ value: 'football', title: '足球' },
{ value: 'basketball', title: '篮球' },
{ value: 'baseball', title: '棒球' }
]
new Vue({
el: '#app',
data: function
() {
return {
HOBBIES,
COUNTRIES,
form: {
name: '',
email: '',
password: '',
gender: 'man',
country: 'cn',
hobbies: [],
bio: '',
age: 18,
},
checkAll: false,
isIndeterminate: true,
}
},
methods: {
submitForm() {
console.log(this.form);
}
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<style>
#app {
display: flex;
justify-content: center;
flex: 1;
}
</style>
</head>
<body>
<div id="app">
<el-form @submit.native.prevent="submitForm" style="width:25%">
<el-form-item label="全名:">
<el-input v-model.lazy.trim="form.name"></el-input>
</el-form-item>
<el-form-item label="邮箱:">
<el-input v-model.trim="form.email"></el-input>
</el-form-item>
<el-form-item label="密码:">
<el-input v-model="form.password" show-password></el-input>
</el-form-item>
<el-form-item label="年龄:">
<el-input-number
v-model.number="form.age"
controls-position="right"></el-input-number>
</el-form-item>
<el-form-item label="性别:">
<el-radio-group v-model="form.gender">
<el-radio label="man">男</el-radio>
<el-radio label="female">女</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="国家:">
<el-select v-model="form.country" placeholder="请选择一个国家">
<el-option v-for="country in COUNTRIES"
:label="country.title"
:value="country.value"
:key="country.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="爱好:">
<el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange">全选</el-checkbox>
<div style="margin: 15px 0;"></div>
<el-checkbox-group v-model="form.hobbies" @change="handleCheckedHobbiesChange">
<el-checkbox v-for="hobby in HOBBIES"
:label="hobby.value"
:key="hobby.value">{{hobby.title}}</el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item label="简介:">
<el-input type="textarea" v-model="form.bio"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" native-type="submit">注册</el-button>
</el-form-item>
</el-form>
<div style="width:25%;margin-left:50px">
<h2>表单预览:</h2>
<p>全名: {{ form.name }}</p>
<p>邮箱: {{ form.email }}</p>
<p>密码: {{ form.password }}</p>
<p>年龄: {{ form.age }}</p>
<p>性别: {{ form.gender }}</p>
<p>国家: {{ form.country }}</p>
<p>爱好: {{ form.hobbies.join(', ') }}</p>
<p>简介: {{ form.bio }}</p>
</div>
</div>
<script>
const COUNTRIES = [
{ value: 'cn', title: '中国' },
{ value: 'us', title: '美国' },
{ value: 'uk', title: '英国' }
];
const HOBBIES = [
{ value: 'football', title: '足球' },
{ value: 'basketball', title: '篮球' },
{ value: 'baseball', title: '棒球' }
]
new Vue({
el: '#app',
data: function () {
return {
HOBBIES,
COUNTRIES,
form: {
name: '',
email: '',
password: '',
gender: 'man',
country: 'cn',
hobbies: [],
bio: '',
age: 18,
},
checkAll: false,
isIndeterminate: true,
}
},
methods: {
submitForm() {
console.log(this.form);
},
handleCheckAllChange(val) {
this.form.hobbies = val ? HOBBIES.map(hobby => hobby.value) : [];
this.isIndeterminate = false;
},
handleCheckedHobbiesChange(value) {
let checkedCount = value.length;
this.checkAll = checkedCount === HOBBIES.length;
this.isIndeterminate = checkedCount > 0 && checkedCount < HOBBIES.length;
}
}
})
</script>
</body>
</html>
在 Vue.js 中,自定义指令是一种可以复用的功能,这个功能可以直接应用在 HTML 元素上。自定义指令提供了一种方法来封装 DOM 操作,这样你就可以在应用程序的多个组件中重用这些操作。
每个 Vue 实例在创建时都会调用 Vue.directive(name, definition)
来全局注册自定义指令。其中,name
是指令的名字,而 definition
可以是一个对象或函数。如果是对象,那么这个对象可以包含一些生命周期钩子函数,这些函数在指令的不同阶段被调用。这些阶段包括:
bind
: 只调用一次,指令第一次绑定到元素时调用。这里可以进行一次性的初始化设置。
inserted
: 被绑定元素插入父节点时调用(仅保证父节点存在,但不一定已被插入文档中)。
update
: 所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。
componentUpdated
: 指令所在组件的 VNode 及其子 VNode 全部更新后调用。
unbind
: 只调用一次,指令与元素解绑时调用。
bind
: 只调用一次,指令第一次绑定到元素时调用。这里可以进行一次性的初始化设置。在 Vue 中,binding
是一个对象,传递给指令钩子函数的第二个参数。它包含了一些有用的信息,你可以在指令中使用这些信息。以下是 binding
对象的属性:
name
:指令的名字,不包括 v-
前缀。value
:指令的绑定值,例如 v-my-directive="1 + 1"
中的 2
。oldValue
:指令绑定的前一个值,仅在 update
和 componentUpdated
钩子中可用。无论值是否改变都可用。expression
:字符串形式的指令表达式,例如 v-my-directive="1 + 1"
中的 "1 + 1"
。arg
:传给指令的参数,可选,例如 v-my-directive:foo
中的 "foo"
。modifiers
:一个包含修饰符的对象,例如 v-my-directive.foo.bar
中的 { foo: true, bar: true }
。因此,binding
提供了一种灵活的方式,可以用来在自定义指令中处理各种情况。例如,你可以根据 binding.value
和 binding.oldValue
的不同来决定是否更新 DOM,或者根据 binding.modifiers
的存在与否来改变指令的行为。
<body>
<script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
<div id="app">
<div v-draggable:absolute.ctrl="styleObj"></div>
</div>
<script>
//定义一个指令 名字叫draggable,再定义一个对象,里面编写很多钩子函数
//def 指的就是指令的定义对象
//name: "draggable" 就是指令的名字,就是v-后面这个单词
//rawName: "v-draggable" 就是加上前面的v-的原生的指令名称
//modifiers: {disable:true} 指令修饰符
Vue.directive('draggable',{
//这就是一个钩子函数,你不需要自己调用此函数,只需要写好放在这就可以
bind(el,binding){
console.log(binding);
//如果有disable这个修饰符,那就直接返回,不再去支持拖动
if(binding.modifiers.disable)return;
let isCtrl = false;
//获取指令的参数
el.style.position=binding.arg;
//通过binding.value获取样式对象
let {value:styleObj} = binding;//let styleObj=binding.value;
//把样式对象里的样式赋给真实的DOM元素
for(let key in styleObj){
el.style[key]=styleObj[key];
}
let isDragging = false;//当前是否正在拖拽
let offsetX,offsetY;
//给当前这个DIV添加鼠标按下的事件
el.addEventListener('mousedown',(event)=>{
//如果需要按下ctrl键,但当前并没有按下ctrl键的话就不能拖
if(binding.modifiers.ctrl && !isCtrl){
return;
}
offsetX=event.offsetX;
offsetY=event.offsetY;
isDragging=true;
});
//当我们移动鼠标的时候,计算元素的最新的位置
el.addEventListener('mousemove',(event)=>{
if(isDragging){
el.style.left = event.clientX-offsetX +'px';
el.style.top = event.clientY-offsetY+'px';
}
});
//当松下的时候,停止拖动
el.addEventListener('mouseup',(event)=>{
isDragging=false;
});
//监听按键事件,当按下ctrl键的话就把isCtrl=true
document.addEventListener('keydown',(event)=>{
if(event.key==='Control')isCtrl=true;
});
//监听按键事件,当松开ctrl键的话就把isCtrl=false
document.addEventListener('keyup',(event)=>{
if(event.key==='Control')isCtrl=false;
});
}
});
var vm = new Vue({
el:'#app',
data:{
styleObj:{width:'100px',height:'100px',backgroundColor: 'green'}
}
})
</script>
</body>
inserted
: 被绑定元素插入父节点时调用(仅保证父节点存在,但不一定已被插入文档中)。自定义指令的使用方法非常简单,只需要在你想要添加自定义行为的 HTML 元素上添加 v-your-directive
。例如,如果你的指令名字是 focus
,那么你可以在任何元素上添加 v-focus
,这样就能在该元素上应用这个指令的行为。
这里有一个自定义指令的简单示例:
Vue.directive('focus', {
inserted: function(el) {
// 聚焦元素
el.focus();
}
});
然后在模板中使用它:
<input v-focus>
这样,当页面加载并且该指令被插入到 DOM 中时,这个元素就会自动获取焦点。
在 Vue 2 中,自定义指令的 update
钩子函数在元素的数据发生变化时会被调用。以下是一个使用 update
钩子的例子,这个自定义指令 v-color
会根据绑定的值改变元素的背景颜色:
<body>
<script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
<div id="app">
<div v-color="color">color</div>
<button @click="changeToRed">变红</button>
</div>
<script>
Vue.directive('color',{
//当本DOM元素创建之后先调用bind
//然后会把DOM元素添加到父DOM上进行渲染。inserted
bind(el,binding){
el.style.color = binding.value;
},
//在元素的数据或者说值发生变化时调用
update(el,binding){
el.style.color = binding.value;
}
});
var vm = new Vue({
el:'#app',
data:{color:'green'},
methods:{
changeToRed(){
this.color = 'red'
}
}
})
</script>
</body>
componentUpdated
钩子函数会在包含组件的 VNode 及其子 VNode 全部更新后调用。
这里有一个例子,使用 componentUpdated
钩子函数在组件更新后,检查元素的内容,并根据长度改变元素的背景颜色:
<body>
<script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
<div id="app">
<input v-checklength="username" v-model="username">
</div>
<script>
//检查内容的长度,如果小于6位变红,大于等于6位变绿
Vue.directive('checklength',{
bind(el){
el.style.color ='gray';
},
componentUpdated(el,binding){
let {value} = el;
if(value.length<6){
el.style.color ='red';
}else{
el.style.color ='green';
}
}
});
var vm = new Vue({
el:'#app',
data:{username:''}
})
</script>
</body>
在 Vue 的自定义指令中,update
和 componentUpdated
是两个钩子函数,它们在指令所在的元素更新时被调用,但具体的调用时间和调用条件有所不同。
update
钩子:当指令所在的元素更新时调用,但并不保证其子节点也已更新。这个钩子函数会在指令所在组件的 VNode 更新时调用,但在其子 VNode 更新之前调用。
componentUpdated
钩子:指令所在的元素及其子节点都更新完成后调用。这个钩子函数会在指令所在组件的 VNode 及其子 VNode 更新完成后调用。
下面是一个示例,使用 update
和 componentUpdated
钩子跟踪并打印更新的次数:
let updateCount = 0;
let componentUpdatedCount = 0;
Vue.directive('count-updates', {
update: function(el, binding, vnode, oldVnode) {
updateCount++;
console.log(`Update count: ${updateCount}`);
},
componentUpdated: function(el, binding, vnode, oldVnode) {
componentUpdatedCount++;
console.log(`Component Updated count: ${componentUpdatedCount}`);
}
});
在这个示例中,每当指令所在的元素或组件更新时,update
钩子就会增加 updateCount
并打印更新的次数。同样,每当指令所在的元素和其子节点都更新完成时,componentUpdated
钩子就会增加 componentUpdatedCount
并打印更新的次数。
在 Vue 中,unbind
钩子函数在指令从元素上解绑时被调用。这个钩子函数通常被用来执行清理操作,比如移除事件监听器。
这是一个使用 unbind
钩子函数的示例,该指令 v-click-outside
用于点击元素外部时触发某个操作:
<body>
<script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
<div id="app">
<div v-draggable:absolute.ctrl="styleObj"></div>
</div>
<script>
//定义一个指令 名字叫draggable,再定义一个对象,里面编写很多钩子函数
//def 指的就是指令的定义对象
//name: "draggable" 就是指令的名字,就是v-后面这个单词
//rawName: "v-draggable" 就是加上前面的v-的原生的指令名称
//modifiers: {disable:true} 指令修饰符
Vue.directive('draggable', {
//这就是一个钩子函数,你不需要自己调用此函数,只需要写好放在这就可以
bind(el, binding) {
console.log(binding);
//如果有disable这个修饰符,那就直接返回,不再去支持拖动
if (binding.modifiers.disable) return;
let isCtrl = false;
//获取指令的参数
el.style.position = binding.arg;
//通过binding.value获取样式对象
let { value: styleObj } = binding;//let styleObj=binding.value;
//把样式对象里的样式赋给真实的DOM元素
for (let key in styleObj) {
el.style[key] = styleObj[key];
}
let isDragging = false;//当前是否正在拖拽
let offsetX, offsetY;
//给当前这个DIV添加鼠标按下的事件
el.addEventListener('mousedown', (event) => {
//如果需要按下ctrl键,但当前并没有按下ctrl键的话就不能拖
if (binding.modifiers.ctrl && !isCtrl) {
return;
}
offsetX = event.offsetX;
offsetY = event.offsetY;
isDragging = true;
});
//当我们移动鼠标的时候,计算元素的最新的位置
el.addEventListener('mousemove', (event) => {
if (isDragging) {
el.style.left = event.clientX - offsetX + 'px';
el.style.top = event.clientY - offsetY + 'px';
}
});
//当松下的时候,停止拖动
el.addEventListener('mouseup', (event) => {
isDragging = false;
});
el.onKeyDown = (event) => {
if (event.key === 'Control') isCtrl = true;
}
//监听按键事件,当按下ctrl键的话就把isCtrl=true
document.addEventListener('keydown', el.onKeyDown);
el.onKeyUp = (event) => {
if (event.key === 'Control') isCtrl = false;
}
//监听按键事件,当松开ctrl键的话就把isCtrl=false
document.addEventListener('keyup', el.onKeyUp);
},
unbind(el, binding) {
console.log('unbind')
document.removeEventListener('keydown', el.onKeyDown);
document.removeEventListener('keyup', el.onKeyUp);
}
});
var vm = new Vue({
el: '#app',
data: {
styleObj: { width: '100px', height: '100px', backgroundColor: 'green' }
}
})
vm.$destroy();
</script>
</body>
在这个例子中,当点击发生在元素外部时,会调用 handleClickOutside
方法。当 v-click-outside
指令从元素上解绑时,事件监听器会被移除,以避免不必要的内存使用。
在 Vue.js 中,unbind
钩子函数会在以下情况下被触发:
这个钩子函数常常用于执行清理操作,比如移除指令在 bind
钩子函数中绑定的事件监听器,以防止内存泄露。
在原生 JavaScript 中,并没有内置的 "钩子函数" 概念,但我们可以借用该概念来理解一些特定的功能。
"钩子函数" 的概念主要是指在程序的特定阶段或事件发生时被自动调用的函数。在某种意义上,你可以将事件处理程序视为一种钩子函数。例如,你可能会在按钮被点击时运行一些代码:
button.addEventListener('click', function() {
console.log('Button clicked!');
});
在这个例子中,函数就是一个 "钩子",它 "钩住" 了 click 事件,并在每次点击按钮时运行。
然而,真正的 "钩子函数" 更常见于那些允许你插入自己的代码以影响其行为的库和框架。这些库和框架会提供一些函数或方法,在特定的时间或在某些事件发生时,它们会被自动调用。你可以在这些函数或方法中添加自己的代码,从而改变程序的行为。这就是所谓的 "钩子函数"。