绑定事件v-on和按键修饰符
-
v-on:click 表示在button元素上监听click事件 简写:@click
-
enter space tab 按键修饰符
-
keyup是用户松开按键才触发
-
keydown是在用户按下按键时立即触发
代码展示:
<!DOCTYPE html><html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml"><head><meta charset="UTF-8"><title>Title</title></head><body><div id="app">{{msg}}<h2>{{web.title}}</h2><h2>{{web.age}}</h2><a :href="web.url">{{web.url}}</a><!-- v-on:click 表示在button元素上监听click事件--><button v-on:click="edit">修改url</button><!-- 简写:@click--><button @click="edit">修改url-简写模式</button><hr><!-- 当用户按下回车键并松开的时候触发-->回车<input type="text" @keyup.enter="add(1,2)"><br>空格<input type="text" @keyup.space="add(1,2)"><br><!-- 不能使用keyup,当按下tab键时,光标会移到下一个文本框,失去焦点,所以要使用keydown-->Tab<input type="text" @keydown.tab="add(1,2)"><br>W <input type="text" @keyup.w="add(1,2)"><br><!-- 组合快捷键-->CTRL+shift+enter <input type="text" @keyup.ctrl.shift.enter="add(1,2)"></div><script type="module">import {createApp,reactive} from "./vue.esm-browser.js";createApp({setup(){const web=reactive({title:'vue3',author:'vue',year:'2023',age:18,url:'https://www.baidu.com'})const edit= ()=>{web.url='https://www.meituan.com'}const add =(a,b)=>{return web.age += a+b}return{msg:'hello world',//普通变量web,//响应式数据edit,add}}}).mount('#app')</script></body></html>
显示和隐藏 v-show
v-show:通过设置布尔值确定是否显示
原理:通过添加移除插件中style的display:none来实现显示与隐藏
代码展示:
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body><div id="app"><h2>{{web.show}}</h2><p v-show="web.show"> 你好,Vue</p><button @click="toggle">切换</button></div><script type="module">import {createApp,reactive} from './vue.esm-browser.js'createApp({setup(){const web=reactive({show:true})const toggle=()=>{web.show=!web.show}return{web,toggle//方法}}}).mount('#app')</script></body></html>
条件渲染v-if(判断)
-
v-if 用于对元素进行条件渲染,当条件为true时,渲染该元素,当为false时,则不渲染
-
v-if 适用于较少改变的场景,因为频繁从DOM中添加与删除元素,会导致性能下降
-
v-else-if v-else
-
v-show 通过添加移除插件中style的display:none来实现显示与隐藏
-
v-show 适用于频繁切换元素的显示状态,因为只改变display属性,不需要重新渲染整个组件
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body><div id="app"><h2>{{web.show}}</h2><p v-show="web.show"> 你好,Vue</p><p v-if="web.show">你好,if</p><button @click="toggle">切换</button><p v-if="web.user < 1000">新网站</p><p v-else-if="web.user >= 1000 && web.user < 10000">老网站</p><p v-else>老老网站</p></div><script type="module">import {createApp,reactive} from './vue.esm-browser.js'createApp({setup(){const web=reactive({show:true,user:11100})const toggle=()=>{web.show=!web.show}return{web,toggle//方法}}}).mount('#app')</script></body></html>
Vue:双向数据绑定 v-model
什么是双向数据绑定
Vue. js 是一个MVVM 框架,即数据双向绑定,即当数据发生变化的时候,视图也就发生变化,当视图发生变化的时候,数据也会跟着同步变化。这也算是 Vue.js 的精髓之处了。
值得注意的是,我们所说的数据双向绑定,一定是对于U1控件醉说的,非UI 控件不会涉及到数据双向绑定。单向数据绑定是使用状态管理工具的前提。如果我们使用 vuex,那么数据流也是单项的,这时就会和双向数据绑定有冲突。
为什么要实现数据的双向绑定
在 Vue.js 中,如果使用 vuex,实际上数据还是单向的,之所以说是数据双向绑定,这是用的UI 控件来说,对于我们处理表单,Vue. js 的双向数据绑定用起来就特别舒服了。即两者并不互斥,在全局性数据流使用单项,方便跟踪;局部性数据流使用双向,简单易操作。
在表单中使用双向数据绑定
你可以用 v-model指令在表单<input>、(textarea)及<select> 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但v-model 本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。 注意:v-model 会忽略所有表单元素的value、checked、selected 特性的初始值而总是将Vue 实例的数据作为数据来源。你应该通过 JavaScript 在组件的 data 选项中声明初始值!
代码示例
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body><div id="app">输入的文本: <input type="text" v-model="number">{{number}}文本域: <textarea name="" id="" cols="30" rows="10" v-model="obj.name"></textarea> {{obj.name}}<br>单选框: <input type="radio" v-model="obj.name" value="zhangsan">zhangsan<input type="radio" v-model="obj.name" value="lisi">lisi<p>选中了谁:{{obj.name}}</p>下拉框:<select v-model="obj.name"><option value="" disabled>===请选择===</option><option value="zhangsan" selected>zhangsan</option><option value="lisi">lisi</option></select></div><script type="module">import {createApp,ref,reactive} from './vue.esm-browser.js'createApp({setup(){const number = ref(0)//响应式数据 ref用于存储单个基本类型的数据,如数字,字符串等number.value = 20 // 使用ref创建的响应式对象,可以直接修改其value值const obj = reactive({//响应式数据 reactive用于存储对象,数组等复杂数据类型name:'zhangsan',age:18})obj.name = 'lisi'//使用reactive创建的响应式对象,可以直接通过属性名修改其属性值return{msg:'hello world',number,obj}}}).mount('#app')</script></body></html>
注意:如果v-model表达式的初始值未能匹配任何选项,<select>元素会被渲染为“未选中状态”,推荐提供一个值为空的禁用选择项
v-model常用修饰符
-
v-model.lazy:在失去焦点或按下回车键之后渲染
-
v-model.number:输入框的值被转换成数字类型,非数字类型不识别
-
v-model.trim:去除首尾空格
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<div id="app"><h3>url:{{web.url}}</h3><h3>user:{{web.user}}</h3>实时渲染<input type="text" v-model="web.url"><br>
<!-- 输入100人,web.user的值仍为100-->在失去焦点或按下回车键之后渲染<input type="text" v-model.lazy="web.url"><br>输入框的值被转换成数字类型<input type="text" v-model.number="web.user"><br>去除首尾空格<input type="text" v-model.trim="web.url"><br>
</div>
<script type="module">import {createApp,reactive} from './vue.esm-browser.js'createApp({setup(){const web = reactive({url:'https://www.baidu.com',user:10})return{web}}}).mount('#app')</script>
</body>
</html>
v-for(循环)
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body><div class="app"><li v-for="(item,index) in vm.items">{{item.name}}===={{index}}</li></div><script type="module">import {createApp,reactive,ref} from "./vue.esm-browser.js";createApp({setup(){const vm = reactive({msg:"hello world",items:[{name:"xwq",age:18},{name:"xwq1",age:19},{name:"xwq2",age:20}]})const message = ref("hello world1")return{vm,message}}}).mount(".app")</script></body></html>
Attribute绑定 :v-bind:
双大括号不能在 HTML attributes 中使用。想要响应式地绑定一个 attribute,应该使用 v-bind指令
<b :class="{textColor:web.fontStatus}"> 你好</b>
v-bind
指令指示 Vue 将元素的 class
attribute 与组件的 选择器
属性保持一致。如果绑定的值是 null
或者 undefined
,那么该 attribute 将会从渲染的元素上移除。
可以直接简写为 v-bind: ==》:
开头为 :
的 attribute 可能和一般的 HTML attribute 看起来不太一样,但它的确是合法的 attribute 名称字符,并且所有支持 Vue 的浏览器都能正确解析它。
<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<style>.textColor{color: red;}
</style>
<div id="app">
<!-- :value--><h3>value="xwqnoicwen"</h3><input type="text" value="xwqnoicwen"><h3>value="xwqnoicwen"</h3><input type="text" v-bind:value="web.url"><p></p><input type="text" :value="web.url">
<!--:src--><h3>src="101.png"</h3><img src="101.png" style="width: 10%" height="10%"><p></p><img :src="web.img" style="width: 10%" height="10%">
<!-- :class--><h3>class="textColor"</h3><b class="textColor"> 你好</b><p></p>
<!-- 可以通过布尔值确认是否渲染样式--><b :class="{textColor:web.fontStatus}"> 你好</b>
</div>
<script type="module">import {createApp,reactive} from './vue.esm-browser.js'createApp({setup(){const web = reactive({url:'https://www.baidu.com',fontStatus:false,img:"101.png"})return{web}}}).mount("#app")
</script>
</body>
</html>
渲染数据 v-text和v-html
-
v-text将数据解析纯文本格式 与{{}}作用相同
-
v-html将数据解析成HTML格式
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title><script src="vue.global.js"></script></head><body><div id="app"><!-- 差值表达式,将vue实例中定义的数据在视图中渲染-->{{msg}}<h2>{{web.title}}</h2><p>Using text interpolation: {{ rawHtml }}</p><p>Using v-html directive: <span v-text="rawHtml"></span></p><p>Using v-html directive: <span v-html="rawHtml"></span></p><a :href="web.url">{{web.title}}</a></div><script>//这里使用的是一种解构赋值语法,将vue对象中的createApp方法,reactive方法,mount方法等挂载到Vue上const {createApp,reactive,ref} = VuecreateApp({//设置响应数据和方法等setup(){const web=reactive({title:'vue3',author:'vue',year:'2023',url:'https://www.baidu.com'})const rawHtml = '<span style="color:red">this should be red</span>'return{msg:'hello world',web,rawHtml}}}).mount('#app')</script></body></html>
计算属性 computed
计算属性缓存 vs 方法
你可能注意到我们在表达式中像这样调用一个函数也会获得和计算属性相同的结果:
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body><div id="app"><h2>{{add()}}</h2><h2>{{add()}}</h2><h2>{{sum}}</h2><h2>{{sum}}</h2></div><script type="module">import {createApp,reactive,computed} from './vue.esm-browser.js'createApp({setup(){const data= reactive({x:10,y:20})//方法 无缓存let add = () =>{console.log('add')//打印两次,说明方法是没有缓存的,return data.x+data.y}//计算属性 有缓存 【计算属性根据其以来的响应式数据变化而重新计算】const sum = computed(()=>{console.log('sum')//打印一次return data.x+data.y})return{add,sum}}}).mount('#app')</script></body></html>
若我们将同样的函数定义为一个方法而不是计算属性,两种方式在结果上确实是完全相同的,
不同之处在于计算属性值会基于其响应式依赖被缓存。一个计算属性仅会在其响应式依赖更新时才重新计算。
这意味着只要 author.books
不改变,无论多少次访问 publishedBooksMessage
都会立即返回先前的计算结果,而不用重复执行 getter 函数。
这也解释了为什么下面的计算属性永远不会更新,因为 Date.now()
并不是一个响应式依赖:
js
const now = computed(() => Date.now())
相比之下,方法调用总是会在重渲染发生时再次执行函数。没有缓存
为什么需要缓存呢?想象一下我们有一个非常耗性能的计算属性 list
,需要循环一个巨大的数组并做许多计算逻辑,并且可能也有其他计算属性依赖于 list
。没有缓存的话,我们会重复执行非常多次 list
的 getter,然而这实际上没有必要!如果你确定不需要缓存,那么也可以使用方法调用。
手动监听侦听器 watch()
侦听一个或多个响应式数据源,并在数据源变化时调用所给的回调函数。
详细:
watch()
默认是懒侦听的,即仅在侦听源发生变化时才执行回调函数。
第一个参数是侦听器的源。这个来源可以是以下几种:
-
一个函数,返回一个值
-
一个 ref
-
一个响应式对象
-
...或是由以上类型的值组成的数组
第二个参数是在发生变化时要调用的回调函数。这个回调函数接受三个参数:新值、旧值,以及一个用于注册副作用清理的回调函数。该回调函数会在副作用下一次重新执行前调用,可以用来清除无效的副作用,例如等待中的异步请求。
当侦听多个来源时,回调函数接受两个数组,分别对应来源数组中的新值和旧值。
第三个可选的参数是一个对象,支持以下这些选项:
-
immediate
:在侦听器创建时立即触发回调。第一次调用时旧值是undefined
。 -
deep
:如果源是对象,强制深度遍历,以便在深层级变更时触发回调。在 3.5+ 中,此参数还可以是指示最大遍历深度的数字。参考深层侦听器。 -
flush
:调整回调函数的刷新时机。参考回调的刷新时机及 watchEffect()。 -
onTrack / onTrigger
:调试侦听器的依赖。参考调试侦听器。 -
once
:(3.4+) 回调函数只会运行一次。侦听器将在回调函数首次运行后自动停止。
与 watchEffect() 相比,watch()
使我们可以:
-
懒执行副作用;
-
更加明确是应该由哪个状态触发侦听器重新执行;
-
可以访问所侦听状态的前一个值和当前值。
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>侦听器</title></head><body><div id="app">爱好<select v-model="hobby"><option value="" disabled>请选择</option><option value="1">足球</option><option value="2">篮球</option><option value="3">排球</option></select><hr>年<select v-model="date.year"><option value="" disabled>请选择</option><option value="2020">2020</option><option value="2021">2021</option><option value="2023">2022</option></select>月<select v-model="date.month"><option value="" disabled>请选择</option><option value="1">1</option><option value="2">2</option><option value="3">3</option></select></div><script type="module">import {createApp,ref,reactive,watch} from './vue.esm-browser.js'createApp({setup(){const hobby = ref('')//爱好const date = reactive({year:'2023',month:'1'})// 监听hobby的变化 通过监听的值,可以获取到变化前后的值,这样当你切换到某个选项时,我们可以进行对应的操作watch(hobby,(newValue,oldValue)=>{console.log("newValue\t"+newValue,"oldValue\t"+oldValue)if(newValue==='1'){alert('足球')}else if(newValue==='2'){alert('篮球')}else if(newValue==='3'){alert('排球')}})// 监听date的变化watch(date,(newValue,oldValue)=>{/**JS中对象和数组是通过引用传递的,而不是通过值传递的* 当修改对象或数组的时候,实际上修改的是对象或数组的引用,而不是创建一个新的对象或数组* 所以,当监听到date的变化时,newValue和oldValue都是同一个对象,* 所以,如果修改了对象或数组的值,那么打印的结果是修改后的值*/console.log("newValue\t",newValue,"oldValue",oldValue)if(newValue.year==='2020'&&newValue.month==='1'){alert('2020年1月')}else if(newValue.year==='2021'&&newValue.month==='2'){alert('2021年2月')}else if(newValue.year==='2023'&&newValue.month==='3'){alert('2023年3月')}})//监听date.year的变化watch(()=>date.year,(newValue,oldValue)=>{console.log("newValue\t",newValue,"oldValue\t",oldValue)if(newValue==='2020'){alert('2020年')}else if(newValue==='2021'){alert('2021年')}else if(newValue==='2023'){alert('2023年')}})return{hobby,date}}}).mount('#app')</script></body></html>
自动侦听器 watchEffect()
立即运行一个函数,同时响应式地追踪其依赖,并在依赖更改时重新执行。
第一个参数就是要运行的副作用函数。这个副作用函数的参数也是一个函数,用来注册清理回调。清理回调会在该副作用下一次执行前被调用,可以用来清理无效的副作用,例如等待中的异步请求 (参见下面的示例)。
第二个参数是一个可选的选项,可以用来调整副作用的刷新时机或调试副作用的依赖。
默认情况下,侦听器将在组件渲染之前执行。设置 flush: 'post'
将会使侦听器延迟到组件渲染之后再执行。详见回调的触发时机。在某些特殊情况下 (例如要使缓存失效),可能有必要在响应式依赖发生改变时立即触发侦听器。这可以通过设置 flush: 'sync'
来实现。然而,该设置应谨慎使用,因为如果有多个属性同时更新,这将导致一些性能和数据一致性的问题。
简单代码展示:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>侦听器</title>
</head>
<body>
<div id="app">爱好<select v-model="hobby"><option value="" disabled>请选择</option><option value="1">足球</option><option value="2">篮球</option><option value="3">排球</option></select><hr>年<select v-model="date.year"><option value="" disabled>请选择</option><option value="2020">2020</option><option value="2021">2021</option><option value="2022">2022</option></select>月<select v-model="date.month"><option value="" disabled>请选择</option><option value="1">1</option><option value="2">2</option><option value="3">3</option></select>
</div>
<script type="module">import {createApp,ref,reactive,watchEffect} from './vue.esm-browser.js'createApp({setup(){const hobby = ref('')//爱好const date = reactive({year:'2023',month:'1'})//自动监听watchEffect(()=> {console.log("监听开始")if (hobby.value === '1') {alert('足球')}if (date.year === '2022') {alert('2022')}if (date.month === '3') {alert('3')}})return{hobby,date}}}).mount('#app')
</script>
</body>
</html>
返回值是一个用来停止该副作用的函数。
const count = ref(0)watchEffect(() => console.log(count.value))// -> 输出 0count.value++// -> 输出 1
停止侦听器:
js
const stop = watchEffect(() => {})// 当不再需要此侦听器时:stop()
暂停/恢复侦听器:
js
const { stop, pause, resume } = watchEffect(() => {})// 暂停侦听器pause()// 稍后恢复resume()// 停止stop()
副作用清理:
js
watchEffect(async (onCleanup) => {const { response, cancel } = doAsyncWork(newId)// 如果 `id` 变化,则调用 `cancel`,// 如果之前的请求未完成,则取消该请求onCleanup(cancel)data.value = await response})
3.5+ 中的副作用清理:
js
import { onWatcherCleanup } from 'vue'watchEffect(async () => {const { response, cancel } = doAsyncWork(newId)// 如果 `id` 变化,则调用 `cancel`,// 如果之前的请求未完成,则取消该请求onWatcherCleanup(cancel)data.value = await response})
选项:
js
watchEffect(() => {}, {flush: 'post',onTrack(e) {debugger},onTrigger(e) {debugger}})
以上就是Vue.js常用的指令,希望对大家有所帮助