当前位置: 首页 > news >正文

【Vue】基础系列(三三)指令语法-事件及其修饰符,动态样式,v-model的用法,数据持久化存在本地localStorage

和阿牛一起冲Vue


🌕写在前面
🍊博客主页勇敢link牛牛
🎉欢迎关注:🔎点赞👍收藏⭐️留言📝
🌟本文由 勇敢link牛牛 原创,CSDN首发!
📆首发时间:🌹2022年8月30日🌹
🆕最新更新时间:🎄2022年8月30日🎄
✉️愿你熬过万丈孤独,藏下星辰大海!
📠参考书籍:📚《Vue2》
🙏作者水平很有限,如果发现错误,请留言轰炸哦!万分感谢感谢感谢!


指令语法-事件及其修饰符,动态样式,数据持久化

  • 和阿牛一起冲Vue
  • 指令集合
    • v-bind动态属性数据绑定
    • 循环 v-for
    • v-on事件及事件对象
    • Todos案例;
    • 事件修饰符
    • 按键修饰符
    • 动态绑定样式
      • class样式处理
      • 绑定style
    • v-model指令,受控 input表单
    • 单个,多个,全选框
    • 单选和下拉
    • v-model修饰符
    • 购物车持久化
  • 自定义指令-表单验证

指令集合

v-bind动态属性数据绑定

v-bind动态属性数据绑定
语法:

  • 标准语法:v-bind:属性=“动态数据”
  • 简写语法::属性=“动态数据”
<div id="app">
	<img src="http://www.mobiletrain.org/images_index/right-fixed-face.png" alt="">
  <img v-bind:src="src" alt="">
  <img :src="src" alt="">

</div>


<script>
  const vm = new Vue({
    el: '#app',
    data: {
      src: 'http://www.mobiletrain.org/images_index/right-fixed-face.png'
    }
  })
</script>

循环 v-for

vue中对于v-for进行了增强,它可以用 for in/of 都可以,而且两者都可以进行对象的迭代
语法:vue2中小括号可以写,也可以不写,在vue3中一定要写小括号

注:

  • vue2中如果一个标签中同时有v-ifv-for,则v-for的优先级高于v-if,所以在vue2中不推荐两者在一个标签中
  • vue3中v-if优先级高于v-for

语法: v-for="(元素,索引) in/of 数组"

语法:v-for="(元素,键名,索引) in/of 对象"

:v-for,建议给循环项每个添加一个key来作标识,用于提升性能,key值,一定要唯一不重复的,不太建议使用循环的索引当作key值,一般在和后台请求数据时,要求后台提供一个唯一的id给我们

<!-- 循环数组 -->
<li v-for="(item,index) in user">{{index}} -- {{item}}</li>
<li v-for="item,index in user">{{index}} -- {{item}}</li>
<li v-for="item,index in user" :key="item.id">{{item.name}}</li>

<!-- 循环对象 -->
<div v-for="item,key,index in user" :key="key">{{index}} -- {{key}} -- {{item}}</div>

v-on事件及事件对象

v-on:事件名="实现的方法[此方法定义在vue配置中的methods中]"
v-on使用很频繁,可以使用语法糖: @事件名=“方法”
绑定的方法,它可以写小括号,也可以不写小括号

** @click="change"事件**

<div id="app">
    {{message}}
    <button @click="change">点击改变信息</button>
    <button v-on:click="clickFn">点击事件</button>
	<button @click="clickFn">点击事件</button>
	<button @click="($event)=>change($event)">点击改变信息</button>
</div>

methods中定义方法不用使用箭头函数,但是在方法体中建议使用箭头函数,用来保持this指向

var vm = new Vue({
    el:"#app",
    data:function(){
        return {
            message:"车到山前必有路"
        }
    },
    methods:{
       change(){
            setTimeout(()=>{
                this.message= "我一定会回来的";
            },2000)
       }
    }
})

1、如果你绑定方法时,没有写小括号,则vue在解析时,会自动给你映射一个event给绑定方法

2、如果你绑定方法时,有写小括号,则需要手动把event对象传过去$event,$event可以传多个,但是建议只传一个,一般写在第1位或最后1位(占位)

3、 event可以用它来完成dom数据的获取
知识点:

一般的自定义属性获取:
evt.target.getAttribute('uname')
h5新增的属性数据写法可以这样获取:
evt.target.dataset.uname

@keyup=“onEnter”:键盘事件。

<div id="app">
    {{message}}
    <input type="text" name="" id="" @keyup="onEnter">
</div>
<script>
    var vm = new Vue({
        el: "#app",
        data: function () {
            return {
                message: "车到山前必有路"
            }
        },
        methods: {
            change() {
                setTimeout(() => {
                    this.message = "我一定会回来的";
                }, 2000)
            },
            onEnter(e) {
                if(e.keyCode == 13){/* 键盘事件的key码 */
                    console.log(e.target.value);
                    this.message = e.target.value;
                }
            }
        }
    })
</script>

Todos案例;

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>todolist</title>
    <script src="./vue.js"></script>
</head>

<body>
    <div id="app">
        <input type="text" placeholder="请输入内容" @keyup="onEnter">
        <hr>
        <ul>
            <li v-if="todos.length == 0">无任务</li>
            <li v-else v-for="(item,index) in todos" :key="item.id">
                <span>{{item.id}}--{{item.message}}</span>
                <button @click="onClick(index)">删除</button>
            </li>
        </ul>
    </div>
    <script>
        var vm = new Vue({
            el: "#app",
            data: function () {
                return {
                    todos: [{
                        id: Date.now(),
                        message: "我爱你"
                    }]
                }
            },
            methods: {
                onClick(index) {/* 可以使用 vue中提供的变异方法splice来完成,用此方法它会触发视图更新 */
                    this.todos.splice(index, 1)
                },
                del(id) {/* 通过id来删除数据 */
                    this.todos = this.todos.filter(item => item.id != id)
                },
                onEnter(e) {
                    if (e.keyCode == 13) {
                        /* 键盘事件的key码 */
                        this.todos.push({
                            id: Date.now(),
                            message: e.target.value
                        }); /* 变异方法,改变引起试图响应 */
                        e.target.value = '' /* 清空 */
                    }
                }
            }
        })
    </script>
</body>

</html>

事件修饰符

用来处理事件的特定行为

<!-- 阻止冒泡 -->
<button @click.stop="doThis"></button>

<!-- 阻止默认行为 -->
<a @click.prevent="doThis"></a>

<!-- 只执行一次 -->
<div @click.once="incr()">自增一下</div>

<!-- 绑定的元素本身触发时才触发回调 -->
<ul @click.self="incr()">
	<li>你好世界</li>
</ul>

<!--  串联修饰符 -->
<button @click.stop.prevent="doThis"></button>

按键修饰符

在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为 v-on 在监听键盘事件时添加按键修饰符。

<div id="app">
	<!-- 只有在 `key` 是 `Enter` 回车键的时候调用 -->
	<input placeholder="请输入内容" type="text" @keyup.alt.112="onEnter" >
</div>

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

你还可以通过全局 config.keyCodes 对象自定义按键修饰符别名:
// 可以使用 `v-on:keyup.f1`
Vue.config.keyCodes = {f2:113}
<input @keyup.f2="add()" value="aaaa">

动态绑定样式

class样式处理

class样式的动态添加,有这个对象和数组两种方式

  • 对象: {key它就是样式名称:布尔值【true生效,false不生效】}
  • 一般用于开关显示的样式,不太适合添加新的属性样式
  • 但是问题是这样只针对初始化时对象里面的布尔值做修改会让试图更新
  • 只能做当前数据的更改视图才会更新,后来的不更新。
    • 那么就有了新的一个方法: this.$set(this.titleClass, 'font30', true)
    • 动态给对象添加成员属性;
    • 以下是多种触发方式

this.titleClass = Object.assign({}, this.titleClass, { font30: true }
let titleClass = JSON.parse(JSON.stringify(this.titleClass))
titleClass.font30 = true
this.titleClass = titleClass
let obj = Object.assign(参数1地址和返回值地址是同一个地址)

  • 数组:[元素样式名称]
  • 一般对于追加新样式,使用数组
    • 给数组添加元素,元素就是样式名称,这样它会就追加样式
    • push unshift shift pop splice sort reverse 调用时都会让视图更新
<head>
	<script src="./js/vue.js"></script>
	<style>
	    .active {
	        color: red;
	    }
	
	    .font30 {
	        font-size: 30px;
	    }
	</style>
</head>

<body>
    <div id="app">
        <div :class="titleStyle">我是一个标题</div>
        <button @click="addStyle">添加样式</button>
    </div>
    <script>
        const vm = new Vue({
            el: '#app',
            data: {
                titleClass: {
                    active: false
                },
                titleStyle: []
            },
            methods: {
                addClass() {
                // 动态给对象添加成员属性
                this.$set(this.titleClass, 'font30', true)
// this.titleClass.active = !this.titleClass.active
// this.titleClass.active = true
// this.titleClass = { ...this.titleClass, font30: true }
//   let titleClass = JSON.parse(JSON.stringify(this.titleClass))
//   titleClass.font30 = true
//   this.titleClass = titleClass
// this.titleClass = Object.assign({}, this.titleClass, { font30: true })
// let obj =  Object.assign(参数1地址和返回值地址是同一个地址)
                },
                addStyle() {
                    // 给数组添加元素,元素就是样式名称,这样它会就追加样式
                    // push unshift shift pop splice sort reverse 调用时都会让视图更新
                    this.titleStyle.push('active')
                    this.titleStyle.push('font30')
                }
            }
        })
    </script>

</body>

</html>

绑定style

style样式的动态添加,对象和数组方式
和绑定calss类一样

对象
<div :style="{color:'blue',fontSize:'30px'}">我是一个标题</div>
数组
<div :style="[{color:'blue'},{fontSize:'30px'}]">我是一个标题</div>

v-model指令,受控 input表单

在没有使用v-model指令时,来通过data数据控制表单项中的值,还是麻烦滴
需要绑定属性和事件来完成 -- 受控组件
<input type="text" :value="username" @input="setUsername">
v-model它是一个语法糖,value和事件的综合体
<input type="text" v-model="username">

虽然是双向数据绑定,但是uesrname的数据优先级高于input本身,因为在触发input.value=''之后他是不会生效的,而uesrname值清空的话就会清空。
TODOs案例:

<body>
    <div id="app">
        <input type="text" placeholder="请输入内容" v-model="message" @keyup.enter="onEnter">
        <hr>
        <ul>
            <li v-if="todos.length == 0">无任务</li>
            <li v-else v-for="(item,index) in todos" :key="item.id">
                <span>{{item.id}}--{{item.message}}</span>
                <button @click="onClick(index)">删除</button>
            </li>
        </ul>
    </div>
    <script>
        var vm = new Vue({
            el: "#app",
            data: function () {
                return {
                    todos: [],
                    message:'',
                }
            },
            methods: {
                onClick(index) {/* 可以使用 vue中提供的变异方法splice来完成,用此方法它会触发视图更新 */
                    this.todos.splice(index, 1)
                }
                onEnter(e) {            
                        this.todos.push({
                            id: Date.now(), 
                            message:this.message
                        }); /* 变异方法,改变引起视图更新 */
                        this.message =''
                }
            }
        })
    </script>
</body>

单个,多个,全选框

v-model:单个:布尔值

单个复选框,定义的数据类型为布尔类型 true选中,false未选中
单个复选框一定要用布尔类型
<input type="checkbox" v-model="checked">

click事件可以用,但它是的状态有太过提前,用onchange事件,改变后来获取
<input type="checkbox" @click="clickFn">
<input type="checkbox" @change="clickFn">

v-model:多个:数组类型绑定,必须加value

<body>
    <div id="app">
            <ul>
                <li>
                    <input type="checkbox" value="html" v-model="lessons">html
                </li>
                <li>
                    <input type="checkbox" value="css" v-model="lessons">css
                </li>
                <li>
                    <input type="checkbox" value="js" v-model="lessons">js
                </li>
            </ul>
            <hr>
            <div>{{lessons}}</div>
        </div>
    </div>

    <script>
        const vm = new Vue({
            el: '#app',
            data: {
                lessons: ["js"]
            },
            methods: {}
        })
    </script>

</body>

在这里插入图片描述
全选案例;

<body>
    <div id="app">
        <label for="">全选<input type="checkbox" @change="onChange" v-model="checked"></label>
        <hr>
            <ul>
                <li>
                    <input type="checkbox" value="html" v-model="lessons" @change="seeions">html
                </li>
                <li>
                    <input type="checkbox" value="css" v-model="lessons"  @change="seeions">css
                </li>
                <li>
                    <input type="checkbox" value="js" v-model="lessons"  @change="seeions">js
                </li>
            </ul>
            <hr>
            <div>{{lessons}}</div>
        </div>
    </div>

    <script>
        const vm = new Vue({
            el: '#app',
            data: {
                lessons: ["js"],
                checked:false
            },
            methods: {
                onChange(){
                    if(this.checked){
                        this.lessons = ["js","css","html"]
                    }else{
                        this.lessons = []
                    }
                },
                seeions(){
                    if(this.lessons.length == 3) this.checked = true;
                    else this.checked = false;     
                }
            }
        })
    </script>

</body>

单选和下拉

单选:定义的数据类型为字符串,也必须要value属性。
下拉:字符串,value初始化绑定。

<body>
    <div id="app">
       
        <h1>{{sex}}-{{city}}</h1>
        <label for=""><input type="radio" value="男士" v-model="sex">男士</label>
        <label for=""><input type="radio" value="女士" v-model="sex">女士</label>
        <hr>
        <select name="" id="" v-model="city">
            <option value="上海">上海</option>
            <option value="天津">天津</option>
            <option value="起飞">起飞</option>
            <option value="北京">北京</option>
        </select>
    </div>

    <script>
        const vm = new Vue({
            el: '#app',
            data: {
              sex:"男士",
              city:"北京"
            },
            methods: {
               
            }
        })
    </script>

</body>

v-model修饰符

延迟更新,去空格,转为数组

延时更新数据源中的数据
<input v-model.lazy="title">
去空格 trim
<input v-model.trim="title">
转为数值 number
<input type="number" v-model.number="m">+<input type="number" v-model.number="n">={{m+n}}

购物车持久化

在这里插入图片描述

非持久化:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./vue.js"></script>
    <style>
        tr,td{
            text-align: center;
        }
    </style>
</head>
<body>

    <div id="app">
        <table border="1" width="600">
            <tr>
                <th>序号</th>
                <th>名称</th>
                <th>单价</th>
                <th>数量</th>
                <th>操作</th>
            </tr>
            <tr v-for="item,index in product">
                <td>{{index+1}}</td>
                <td>{{item.name}}</td>
                <td>{{item.price}}</td>
                <td><button @click="change(1,index)">+</button><input v-model="item.num"><button @click="change(-1,index)">-</button></td>
                <td><button @click="del(index)">删除</button></td>
            </tr>
        </table>
        <hr>
        <h3>
            合计:
            {{totalPrice()}}
        </h3>
      
    </div>

    <script>
        new Vue({
            el:"#app",
            data:function(){
                return {
                    product:[{ id: 1, name: '小米12pro', price: 1, num: 1 }, { id: 2, name: '华为手机', price: 2, num: 1 },{ id: 3, name: '水果手机', price: 3, num: 1 }] 
    
                }
            },
            methods:{
                totalPrice(){
                   return  this.product.reduce((v,{price,num})=>v += price*num,0);/* 解构 */
                },
                change(n,index){
                    this.product[index].num += n
                },
                del(index){
                    this.product.splice(index,1);
                }
            }
        })
    </script>
</body>
</html>

持久化数据:

<head>
    <script src="./vue.js"></script>
    <style>
        tr,td{
            text-align: center;
        }
    </style>
</head>
<body>

    <div id="app">
        <table border="1" width="600">
            <tr>
                <th>序号</th>
                <th>名称</th>
                <th>单价</th>
                <th>数量</th>
                <th>操作</th>
            </tr>
            <tr v-for="item,index in product">
                <td>{{index+1}}</td>
                <td>{{item.name}}</td>
                <td>{{item.price}}</td>
                <td><button @click="change(1,index)">+</button><input v-model="item.num"><button @click="change(-1,index)">-</button></td>
                <td><button @click="del(index)">删除</button></td>
            </tr>
        </table>
        <hr>
        <h3>
            合计:
            {{totalPrice()}}
        </h3>
      
    </div>

    <script>
        function getData(){
            return !window.localStorage.getItem("product") ?[{ id: 1, name: '小米12pro', price: 1, num: 1 }, 
            { id: 2, name: '华为手机', price: 2, num: 1 },
            { id: 3, name: '水果手机', price: 3, num: 1 }] : JSON.parse(window.localStorage.getItem("product"))
        }
        function setData(product){
            localStorage.setItem("product",JSON.stringify(product))
        }
        new Vue({
            el:"#app",
            data:function(){
                return {
                    product: getData(),
    
                }
            },
            methods:{
                totalPrice(){
                   return  this.product.reduce((v,{price,num})=>v += price*num,0);/* 解构 */
                },
                change(n,index){
                    this.product[index].num += n
                },
                del(index){
                    this.product.splice(index,1);
                    setData(this.product)
                }
            }
        })

    </script>
</body>
</html>

自定义指令-表单验证

全局定义,所有的组件或vue的实例都会生效,可以使用。
对象写法,它提供5个钩子(插口)函数:也是它的生命周期
语法:Vue.directive('指令名称,不需要写v-开头',对象或函数)
注意单词的拼写:

Vue.directive('red', {
      // bind 第一次绑定到元素时调用
      bind(el, bindings) {
        console.log('bind')
        el.style.cssText = `color:red;font-size:30px`
      },
      // inserted
      inserted(el, bindings) {
        console.log('inserted');
      },
      // update
      update(el, bindings) {
        console.log('update');
      },
      // componentUpdate
      componentUpdated(el, bindings) {
        console.log('componentUpdated');
      },
      // unbind
      unbind(el, bindings) {
        console.log('unbind');
      },

相关文章:

  • 01_JSON的理解
  • 3D感知技术(3)双目立体视觉测距
  • spring学习第二天_Spring Ioc(1)
  • 22-08-30 西安JUC(03) Callable接口、阻塞队列4套方法、ThreadPool线程池
  • React(8)-组件ref
  • 2022/8/30
  • picoCTF - Day 1 - Warm up
  • 前端面试题之组件
  • 自己动手写编译器:词法解析的系统化研究
  • 【程序员面试金典】01.02. 判定是否互为字符重排
  • go实现剑指offer
  • 【Go-Lua】Golang嵌入Lua代码——gopher-lua
  • yolov5+shufflenet轻量化目标检测
  • 【BurpSuite】插件开发学习之J2EEScan(上)-被动扫描
  • java计算机毕业设计企业公开招聘系统源码+数据库+系统+lw文档+mybatis+运行部署
  • 网络传输文件的问题
  • Angular数据绑定机制
  • docker-consul
  • Java应用性能调优
  • java中的hashCode
  • Markdown 语法简单说明
  • Spring Cloud Alibaba迁移指南(一):一行代码从 Hystrix 迁移到 Sentinel
  • ⭐ Unity 开发bug —— 打包后shader失效或者bug (我这里用Shader做两张图片的合并发现了问题)
  • yii2权限控制rbac之rule详细讲解
  • 对超线程几个不同角度的解释
  • 解决jsp引用其他项目时出现的 cannot be resolved to a type错误
  • 前端js -- this指向总结。
  • 区块链技术特点之去中心化特性
  • 全栈开发——Linux
  • 一加3T解锁OEM、刷入TWRP、第三方ROM以及ROOT
  • 终端用户监控:真实用户监控还是模拟监控?
  • 关于Android全面屏虚拟导航栏的适配总结
  • ​一文看懂数据清洗:缺失值、异常值和重复值的处理
  • # Swust 12th acm 邀请赛# [ A ] A+B problem [题解]
  • #我与Java虚拟机的故事#连载03:面试过的百度,滴滴,快手都问了这些问题
  • (7)STL算法之交换赋值
  • (delphi11最新学习资料) Object Pascal 学习笔记---第2章第五节(日期和时间)
  • (二)linux使用docker容器运行mysql
  • (二)Pytorch快速搭建神经网络模型实现气温预测回归(代码+详细注解)
  • (附源码)springboot建达集团公司平台 毕业设计 141538
  • (附源码)计算机毕业设计SSM教师教学质量评价系统
  • (三)终结任务
  • (一) springboot详细介绍
  • (转)mysql使用Navicat 导出和导入数据库
  • *2 echo、printf、mkdir命令的应用
  • .bat批处理(九):替换带有等号=的字符串的子串
  • .net 7 上传文件踩坑
  • .net on S60 ---- Net60 1.1发布 支持VS2008以及新的特性
  • .NET 命令行参数包含应用程序路径吗?
  • .netcore如何运行环境安装到Linux服务器
  • .NET业务框架的构建
  • .skip() 和 .only() 的使用
  • /bin/bash^M: bad interpreter: No such file or directory
  • @data注解_SpringBoot 使用WebSocket打造在线聊天室(基于注解)
  • @GetMapping和@RequestMapping的区别