vue3学习随便记7

Posted sjg20010414

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue3学习随便记7相关的知识,希望对你有一定的参考价值。

事件处理

监听事件

其实我们已经用了不少监听事件,即 v-on:click="methodName"(简写为 @click="methodName" )

事件处理方法

事件处理总是对应一个方法,直接写 JS 代码作为事件处理是不行的。

<html>

<head>
    <script src="vue.global.js"></script>
</head>

<body>
    <div id="app">
        <button @click="greet">问候</button>
        <button @click="say('hi')">打招呼1</button>
        <button @click="say('hey')">打招呼2</button>
        <button @click="warn('表单还不能提交', $event)">提交</button>
    </div>
    <script>
        const app = Vue.createApp(
            data() 
                return 
                    name: 'Vue3'
                
            ,
            methods: 
                greet(event) 
                    alert('Hello ' + this.name)
                    if (event) 
                        alert(event.target.tagName)
                    
                ,
                say(message) 
                    alert(message)
                ,
                warn(message, event) 
                    console.log(event)
                    if (event) 
                        event.preventDefault()
                    
                    alert(message)
                
            
        )
        const vm = app.mount('#app')
    </script>
</body>

</html>

事件处理只写方法名时,方法的实现中第一个参数为事件参数event(或简写e),如上面代码中的event。事件处理中方法带了参数,那么方法实现的参数就对应所带参数,如上面代码中的 'hi'和'hey'对应message。如果事件处理中仍然想使用事件参数event,那么就应该用$event表示这是实例的参数而非用户指定的参数,事件实现中一般用 event 或 e 与之对应。

为单个事件指定多个事件处理器

<button @click="one($event), two($event)">
  Submit
</button>
methods: 
  one(event) 
    // 第一个事件处理器逻辑...
  ,
  two(event) 
   // 第二个事件处理器逻辑...
  

事件修饰符

事件修饰符其实是把和DOM有关的经常会遇到的处理模式化了,这样事件方法处理中就是纯粹的数据逻辑,而没有DOM事件细节了。前面已经提到过 .prevent,来阻止事件的默认行为。其他还有 .stop 阻止事件冒泡,.capture 预先捕获事件,.self 事件目标对象是当前元素自己,.once 事件只触发一次。

多个修饰符是可以串联的,并且串联时顺序是有讲究的,因此,@click.prevent.self 会阻止所有的点击,@click.self.prevent 只阻止对元素自身的点击。

修饰符 .once 比较特殊,因为它不仅可以对原生的 DOM事件进行修饰,还可以对自定义的组件事件进行修饰。

.passive 修饰符可以提高滚动的性能(参考 EventTarget.addEventListener() - Web APIs | MDN),因为它会忽略 preventDefault(),所以,不要把 .passive 和 .prevent 一起使用。

按键修饰符

在监听键盘事件时,我们往往要检查是哪个键按下或者弹起之类的,按键修饰符可以直接指定是哪个键,如

<!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
<input @keyup.enter="submit" />

其他的键怎么知道修饰符是什么呢?可以参考  Key Values - Web APIs | MDN 先获取 KeyboardEvent.key 值对应的按键名,如 下一页对应的按键名是 "PageDown",把它写成 kebab-case 格式 page-down,所以,下一页按键修饰符是 .page-down

<input @keyup.page-down="onPageDown" />

因为最常用的按键总是那几个,所以,Vue为它们提供了别名:

  • .enter
  • .tab
  • .delete (捕获“删除”和“退格”键)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

系统修饰键

系统修饰键用于组合键或鼠标键盘组合操作

  • .ctrl
  • .alt
  • .shift
  • .meta

例如

<!-- Alt + Enter -->
<input @keyup.alt.enter="clear" />

<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>

如果我们想响应只有Ctrl键按下的情况,而不是Ctrl作为组合键的一部分,怎么办呢? .exact 修饰符就是这个目的

<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<button @click.ctrl="onClick">A</button>

<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button @click.ctrl.exact="onCtrlClick">A</button>

<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button @click.exact="onClick">A</button>

如果要指定鼠标按钮是左中右哪个,可以使用鼠标按钮修饰符

  • .left
  • .right
  • .middle

在HTML中监听事件是否造成紧耦合

Vue在HTML中监听事件一定程度上使得HTML视图部分和JS处理代码部分耦合起来,但这通常不是问题,因为 Vue的事件处理都在当前视图的ViewModel上,如果维护上有困难,通常是模块化(划分子组件)工作没有做好。不是 javascript 里用代码去绑定事件,可以让 ViewModel 代码是非常纯粹的逻辑,和 DOM 完全解耦。

表单输入绑定

基础用法

Vue中用 v-model 指令为表单元素 <input>、<textarea> 和 <select> 创建双向绑定,对于不同的元素,v-model 会自动在内部使用不同的 property (属性)和 event(事件):

  • text 和 textarea : 属性 value 和 事件 input
  • checkbox 和 radio: 属性 checked 和 事件 change
  • select: 属性 value 和 事件 change

当使用 v-model 指令绑定时,元素本身的 value、checked 值即使设置了也无效,因为总是会自动被替换为绑定的变量的值。对于中文这样用额外输入法的语言,在输入法组织文字的过程中,Vue  v-model 不会认为这是在输入,如果要响应文字组织过程,应该自行绑定到 value 并监听 input事件(这一条暂时我没有找到输入法怎样的状态满足)。

文本和多行文本

<html>

<head>
    <script src="vue.global.js"></script>
</head>

<body>
    <div id="app">
        <input v-model="message" placeholder="在此编辑" />
        <p>消息为:  message </p>
        <span>多行消息:</span>
        <p style="white-space: pre-line;"> text </p>
        <textarea v-model="text" placeholder="可添加多行"></textarea>
        <br /><br />
        <textarea> text </textarea>  <!-- bad -->
    </div>
    <script>
        const app = Vue.createApp(
            data() 
                return 
                    message: '',
                    text: '',
                    note: ''
                
            ,
            methods: 
                inputHandler(e) 
                    console.log(e)
                
            
        )
        const vm = app.mount('#app')
    </script>
</body>

</html>

需要注意,对 textarea 进行插值(第2个textarea) 不能实现双向绑定,即在textarea中输入的内容不会被反映到变量 text,正确的做法是第1个textarea,用 v-model,这样输入的内容会反映到变量 text,从而在“多行消息:”后面显示出来(此时,如果第2个textarea之前是空的,text的值也会反映到这个textarea的显示上,反之,第2个textarea如果之前非空,就仍然保持原样,这个行为略显诡异)。

复选框和单选框

单个复选框,绑定到布尔值;多个复选框,则成组绑定到数组(每个复选框的value值成为数组的元素)。多个单选框的行为和绑定到数组的多个复选框类似,只是它绑定到单个值的vm属性,取值为多个单选框中的某个的value值。

<html>

<head>
    <script src="vue.global.js"></script>
</head>

<body>
    <div id="app">
        <div id="v-model-checkbox">
            <input type="checkbox" id="checkbox" v-model="checked" />
            <label for="checkbox">值: checked </label>
        </div>
        <div id="v-model-multiple-checkboxes">
            <input type="checkbox" id="zs" value="张三" v-model="checkedNames" />
            <label for="zs">张三</label>
            <input type="checkbox" id="ls" value="李四" v-model="checkedNames" />
            <label for="ls">李四</label>
            <input type="checkbox" id="ww" value="王五" v-model="checkedNames" />
            <label for="ww">王五</label>
            <br />
            <span>勾选的名字: checkedNames </span>
        </div>
        <div id="v-model-radiobutton">
            <input type="radio" id="china" value="中国" v-model="picked" />
            <label for="china">中国</label>
            <br />
            <input type="radio" id="usa" value="美国" v-model="picked" />
            <label for="usa">美国</label>
            <br />
            <span>选择了:  picked </span>
        </div>
    </div>
    <script>
        const app = Vue.createApp(
            data() 
                return 
                    checked: false,
                    checkedNames: [],
                    picked: ''
                
            ,
            methods: 
                inputHandler(e) 
                    console.log(e)
                
            
        )
        const vm = app.mount('#app')
    </script>
</body>

</html>

 选择框(下拉列表或多选框)

选择框作为单选的下拉列表时,绑定到单值的vm属性上,选择时,属性的值就是所选项的值(所选项没有提供value属性的,值就是其内部文本)。v-model 表达式初始值如果和所有option都不能匹配,<select>元素渲染为“未选中”状态,这在ios中会造成用户无法选择第一个选项,所以,通常额外加一个禁用的值为空的选项。

选择框作为多选框时,绑定到一个数组,数组的元素由option的值构成,同样,所选项没有提供value属性的,值就是其内部文本。(选择时需要使用 Shift 或 Ctrl 键)。

<html>

<head>
    <script src="vue.global.js"></script>
</head>

<body>
    <div id="app">
        <div id="v-model-select-bad">
            <select v-model="selectedBad">
                <option value="优秀">A</option>
                <option>B</option>
                <option>C</option>
                <option>D</option>
            </select>
            <span>已选择: selectedBad </span>
        </div>
        <br /><br />
        <div id="v-model-select">
            <select v-model="selected">
                <option disabled value="">请选择一个</option>
                <option value="优秀">A</option>
                <option>B</option>
                <option>C</option>
                <option>D</option>
            </select>
            <span>已选择: selected </span>
        </div>
        <br /><br />
        <div id="v-model-multiple-select">
            <select v-model="multipleSelected" multiple>
                <option>A</option>
                <option>B</option>
                <option>C</option>
                <option value="不及格">D</option>
            </select>
            <span>已选择: multipleSelected </span>
        </div>
    </div>
    <script>
        const app = Vue.createApp(
            data() 
                return 
                    selectedBad: '',
                    selected: '',
                    multipleSelected: []
                
            
        )
        const vm = app.mount('#app')
    </script>
</body>

</html>

 直接写 option,只能静态写选项,而且比较累,更常用的做法是用 v-for 渲染动态选项:

    <div id="app">
        <div id="v-model-select">
            <select v-model="selected">
                <option v-for="option in options" :value="option.value">
                     option.text 
                </option>
            </select>
            <span>已选择: selected </span>
        </div>
        
    </div>
    <script>
        const app = Vue.createApp(
            data() 
                return 
                    selected: 'A',
                    options: [
                         text: '优秀', value: 'A',
                         text: '良好', value: 'B',
                         text: '中等', value: 'C',
                         text: '及格', value: 'D',
                         text: '不及格', value: 'F',
                    ]
                
            
        )
        const vm = app.mount('#app')
    </script>

值绑定

 对于单选按钮、复选框以及选择框的选项,v-model 绑定的值通常是静态字符串(对于单个checkbox也可以是布尔值),要绑定值到vm的动态属性上,应该用 v-bind 指令来绑定,此外, v-bind 可以将输入值绑定到非字符串,例如对象。

<!-- 当选中时,`picked` 为字符串 "a" -->
<input type="radio" v-model="picked" value="a" />

<!-- `toggle` 为 true 或 false -->
<input type="checkbox" v-model="toggle" />

<!-- 当选中第一个选项时,`selected` 为字符串 "abc" -->
<select v-model="selected">
  <option value="abc">ABC</option>
</select>

对于 checkbox,绑定的值可以是 true/false 这样的取值,也可以是 yes/no 这样的取值,方法是使用 true-value 和 false-value 

    <div id="app">
        <div id="v-model-checkbox">
            <input type="checkbox" id="checkbox" v-model="toggle"
                true-value="yes" false-value="no" @change="show" />
            <label for="checkbox">值: toggle </label>
        </div>
    </div>
    <script>
        const app = Vue.createApp(
            data() 
                return 
                    toggle: null
                
            ,
            methods: 
                show(e) 
                    console.log(this.toggle)
                
            
        )
        const vm = app.mount('#app')
    </script>

 

对于 radio,可以用 v-bind:value 指定选中时的值

<input type="radio" v-model="pick" v-bind:value="a" />
// 当选中时
vm.pick === vm.a

对于 select,可以给 option 绑定非常规字符串的值,例如对象

<select v-model="selected">
  <!-- 内联对象字面量 -->
  <option :value=" number: 123 ">123</option>
</select>
// 当选中时
typeof vm.selected // => 'object'
vm.selected.number // => 123

修饰符

之前关于事件我们提到过修饰符(改变事件的默认行为),对于表单输入,也可以添加修饰符,改变一些行为。例如,默认 v-model 针对 input 事件触发,从而随着用户输入使得输入框的值不停改变时与数据保持同步,我们可以添加 .lazy 修饰符,转变成触发 change 事件之后进行同步

<!-- 在“change”时而非“input”时更新 -->
<input v-model.lazy="msg" />

自动将用户的输入值转为数值类型,使用 .number 修饰符。这个修饰符主要起到自动转换作用。(注意,如果输入类型是 number,Vue会自动将原始字符串转换为数字,不需要此修饰符,所以,该修饰符主要针对输入类型为 text 的情况。如果这个值无法被 parseFloat() 解析,将返回原始值。)

    <div id="app">
        <input v-model.number="age" placeholder="在此输入年龄" @change="show" />
        <p>年龄为:  age </p>
    </div>
    <script>
        const app = Vue.createApp(
            data() 
                return 
                    age: null
                
            ,
            methods: 
                show(e) 
                    console.log(typeof this.age)
                    console.log(this.age)
                
            
        )
        const vm = app.mount('#app')
    </script>

 

自动将用户输入的首尾空白字符去除,可以使用 .trim 修饰符。理解了 .number 修饰符的过滤器作用,不难理解 .trim 的过滤作用。

<input v-model.trim="msg" />

在组件上使用 v-model

HTML原生的输入元素(表单输入)是相当有限的,有时候不能很好满足需求。Vue组件系统允许你创建完全自定义行为且可复用的输入组件,即输入组件可以用户自定义扩展,并且可以和 v-model 一起使用。组件细节在后面具体了解,这里我们可以看看自定义组件使用 v-model 大概怎么样

app.component('custom-input', 
  props: ['modelValue'],
  emits: ['update:modelValue'],
  template: `
    <input
      :value="modelValue"
      @input="$emit('update:modelValue', $event.target.value)"
    >
  `
)
<custom-input v-model="searchText"></custom-input>

以上是关于vue3学习随便记7的主要内容,如果未能解决你的问题,请参考以下文章

vue3学习随便记11

vue3学习随便记10

vue3学习随便记10

vue3学习随便记8

vue3学习随便记8

vue3学习随便记5