Vue数据的变更操作与表单数据的收集【6】

目录

1.数据的变更操作

案例:

plain 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        button {
            margin-top: 10px;
        }

    </style>
</head>


<body>
<div id="root">
    <h3>姓名:{{person.name}}</h3>
    <h3>年龄:{{person.age}}</h3>
    <h3>爱好:</h3>
    <ul>
        <li v-for="(item,index) in person.hobby" :key="index">
            {{item}}
        </li>
    </ul>
    <h3>朋友:</h3>
    <ul>
        <li v-for="(item,index) in person.friends" :key="index">
            {{item.name}}--{{item.age}}
        </li>

    </ul>
</div>
<script src="vue/vue.js"></script>
<script type="text/javascript">
    let vm = new Vue({
        data() {
            return {
                person: {
                    name: '张三',
                    age: 26,
                    hobby: ['测试数据1', '测试数据2', '测试数据3'],
                    friends: [
                        {name: '李四', age: 35},
                        {name: '王武', age: 27}
                    ]
                }
            }
        }
    }).$mount('#root')


</script>


</body>
</html>   
复制代码
  在上面案例中Vue示例有一些基础属性,我们通过一些指令,将其渲染到页面上

现在我们有一些需求,需要对上述Vue实例中的数据进行变更

需求1:给person对象添加sex属性,值为'男';
plain 复制代码
//添加一个按钮,绑定事件
<button @click="addSex">新增性别属性</button> 
plain 复制代码
//在Vue实例中添加methods对象,定义上面事件的回调函数
 methods: {
            addSex() {
                //注意不能直接对person对象添加sex属性,因为Vue识别不到
                //Vue.set(this.person,'sex','男')
                this.$set(this.person, 'sex', '男')
            }
    }

测试:

复制代码
通过测试结果发现,我们将sex属性成功添加到了person对象中,同时也成功地渲染到了页面。

但有个问题需要注意,在进行属性添加时,应使用上面地两种方式,而不能直接使用js中**对象名.属性名='值'**地语法。

因为,这样只是把sex属性添加到了person对象中,而没有把数据添加到Vue实例所复制地对象中,因此在页面渲染时,自然不会把新增地属性渲染出来;

需求2:对person地age属性进行++操作
plain 复制代码
//准备功能按钮,绑定事件(注意++或--操作直接可以绑定,不用再在methods中定义回调函数)
<button @click="person.age++">年龄++</button>

需求3:新增一位朋友到首位
plain 复制代码
//准备功能按钮,绑定事件
 <button @click="addfirstfriend">新增一位朋友到首位</button>
plain 复制代码
//定义回调函数
 methods: {
   addfirstfriend() {
                this.person.friends.unshift({name: '赵6', age: 33})
            }
    }

需求4:修改第一位朋友的姓名为赵六
plain 复制代码
//准备功能按钮,绑定事件
 <button @click="updatefriend">修改第一位朋友姓名为赵六</button> 
plain 复制代码
//定义回调函数
 methods: {
   updatefriend() {
                this.person.friends[0].name = '赵六'
            },
    }

需求5:追加一个爱好--'学习'
plain 复制代码
 //准备功能按钮,绑定事件
<button @click="addhobby">追加学习爱好</button>
plain 复制代码
//定义回调函数
 methods: {
   addhobby(){
                this.person.hobby.push('学习')
            },
    }

需求6:将第一个爱好修改为学习:
plain 复制代码
 //准备功能按钮,绑定事件
<button @click="updatehobby">修改第一个爱好为学习</button>
plain 复制代码
//定义回调函数
 methods: {
  updatehobby(){
                //不能直接覆盖,需要调用数组原生方法
                this.person.hobby.splice(0,1,'学习')
            },
    }

注意:在对数组元素进行变更时,不能直接使用=进行覆盖,而应该使用数组的原生方法进行操作;

原因解释:

复制代码
在 Vue 中,数据是响应式的。当一个组件实例被创建时,Vue 会对其`data`选项中的数据进行遍历,通过`Object.defineProperty`(在 Vue 3 中是通过`Proxy`)来进行数据劫持。这意味着 Vue 能够追踪数据的变化,当数据发生改变时,会自动更新与之绑定的 DOM 元素。

 当使用`=`直接覆盖一个数组元素时,实际上是切断了 Vue 对原始数组的响应式追踪。因为 Vue 的响应式系统并不知道这个数组新的元素的存在,它只对最初定义在`data`中的数组进行了劫持。

 当对数组中的一个元素的单个属性进行变更(使用`=`覆盖)时,实际上是触发了这个属性对应的`setter`函数。因为 Vue 已经对这个属性进行了数据劫持,所以`setter`会通知响应式系统数据发生了变化。(参考需求4)
需求7:过滤学习爱好
plain 复制代码
 //准备功能按钮,绑定事件
<button @click="filterhobby">过滤学习爱好</button>
plain 复制代码
//定义回调函数
filterhobby(){
                this.person.hobby= this.person.hobby.filter((item)=>{
                    return !(item !='学习');
                })
            }

总结:

1.Vue会监视data中所有层次的数据

  1. 如何监测对象中的数据
plain 复制代码
    1. 通过settter实现监视,并且要在new Vue实例 传入要监测的数据
    2. 对象中后追加的属性,Vue默认不作出响应式处理的
    3. Vue.set(目标对象,属性名,值)  /   this.$set(目标对象,属性名,值)

3.如何监测数组中的数据通过包裹数组更新元素的方式实现的:

复制代码
1.调用原生方法的对应的方法对数组进行更新

 2.重新解析模板,更新页面

2.表单数据收集:

案例:

复制代码
  构建一个form表单,用户输入数据后收集这些数据进行控制台展示
plain 复制代码
 <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--2.准备一个容器-->
<div id="root">
     //阻止表单提交
    <form  @submit.prevent="demo">
          //构建输入框用于用户输入账号密码及年龄
          //使用v-model指令双向绑定数据
        账号:<input type="text" v-model.trim="userInfo.account"/> <br/>
        密码:<input type="password" v-model="userInfo.password"/><br/>
        年龄:<input type="number" v-model.number="userInfo.age"/><br/>
        性别:
         //构建两个单项选择器,用于用户选择性别并将其绑定到userInfo对象的sex属性上
         //动态绑定了值为 0,表示选择 "男" 时,这个单选按钮的值为 0,如果data中用户的性别为0时
          //即表示男性为默认选项
        <label>男: <input type="radio" name="sex" :value="0"  v-model="userInfo.sex"/></label>
        <label>女: <input type="radio" name="sex" :value="1" v-model="userInfo.sex"/></label><br/>
        爱好:
         //构建多选框,用于用户选择爱好,并将其绑定到userInfo对象的hobby属性上
        <label><input type="checkbox"  v-model="userInfo.hobby" value="2"/>游戏</label>
        <label><input type="checkbox"  v-model="userInfo.hobby" value="3"/>吃饭</label>
        <label><input type="checkbox"  v-model="userInfo.hobby" value="4"/>篮球</label><br/>
        地区:
         //构建下拉选择框,用于用户选择地区,并绑定到userInfo的city属性中
        <select  v-model="userInfo.city">
            <option value="">请选择</option>
            <option value="北京">北京</option>
            <option value="西安">西安</option>
            <option value="上海">上海</option>
        </select><br/>
        其他信息:
        <!--  lazy 在失去焦点后收集数据   number:将字符串转换为数字  trim 取出前后空格在收集    -->
        <textarea rows="10" cols="20" v-model.lazy="userInfo.other">
        </textarea><br/>
        <label><input type="checkbox" v-model="userInfo.agree"/>阅读并接收<a href="#">《用户协议》</a></label>
        <br/>
        <button type="submit">提交</button>
    </form>
</div>
<!--1.引入Vue js 文件-->
<script src="vue/vue.js"></script>
<script type="text/javascript">
    //3.创建Vue对象
    let vm = new Vue({
        data() {
            return {
             //构建对象,用于绑定用户输入的信息,当选择框的value值与此对象默认的值相同时,
              //此值即表示了选择框上的默认值
                userInfo: {
                    account: '',
                    password: '',
                    age: 18,
                    sex: 0,
                    hobby: ['2'],
                    city: '北京',
                    other: '',
                    agree: false
                }
            }
        },
        methods: {
           //阻止调单提交事件的回调函数
            demo() {
                console.log(JSON.stringify(this.userInfo))

            }
        }
    }).$mount("#root");
</script>
</body>
</html>
  
复制代码
先展示form表单界面

用户输入信息,并点击提交

此时在控制台看查看用户输入的信息

3.过滤器:

1.案例:

plain 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<!--2.准备一个容器-->
<div id="root">
  <h1>时间</h1>
  <h2>当前时间戳:{{time}}</h2>
   //如果有多个过滤规则,可以依次往后拼接,值会从前往后依次传递,直到最终的结果进行渲染
  <h2>转换后的时间:{{time | timeFormater}}</h2>
  <h2>转换后的时间:{{time | timeFormater | timeFormaterStr}}</h2>
</div>
<!--1.引入Vue.js 和dayjs.js文件-->

<script src="vue/dayjs.min.js"></script>

<script src="vue/vue.js"></script>
<script type="text/javascript">
  //3.创建Vue对象
  let vm = new Vue({
    data() {
      return {
        //当前时间的时间戳
        time: 1732159777000
      }
    },
    filters: {
       //对data中的time属性的值进行格式过滤转换
      timeFormater(value, str = 'YYYY年MM月DD日 HH:mm:ss SSS') {
        console.log("执行了timeFormater")
        // 注意 value的类型
        return dayjs(value).format(str);
      },
      timeFormaterStr(value) {
        return value.substring(0, 11);
      }
    }
  })
  vm.$mount("#root");
</script>
</body>
</html>
  

4.vue中的内置指令

plain 复制代码
v-bind 单向数据绑定:
plain 复制代码
v-model 双向数据绑定
plain 复制代码
v-for 遍历 数组 对象 字符串 固定次数
plain 复制代码
v-on 绑定事件
plain 复制代码
v-if v-else-if  v-else 条件的渲染

v-show 条件的渲染  
plain 复制代码
v-text 通过此指令的value值覆盖原本的文本内容
 例: <h2 v-text="name+',hello'">这是默认值</h2>
   等价于<h2 >{{name}},hello</h2>
plain 复制代码
v-html:通过此指令会将一个字符串作为 HTML 内容插入到元素中
  例: <p v-html="str"></p>str 变量的值会被解析为 HTML 并显示在 <p> 元素内。
   注意:此指令存在安全问题,不建议使用。
       如果 str 的值是由用户输入或者来自不可信的数据源,那么可能会导致跨站脚本攻击(XSS)
plain 复制代码
v-cloak:指令主要用于解决在 Vue 实例初始化之前,插值表达式或指令显示在页面上可能导致的 "闪动"问题。
    例:<h3 v-cloak>{{name}}</h3>此标签通过指令来解决网络不佳时显示html元素语法到页面上的问题
plain 复制代码
v-once 指令会使元素及其子元素只渲染一次。
        在初始渲染后,无论数据如何变化,这个元素及其子元素都不会再次更新。
  例:<button v-once @click="count++">{{count}}++</button>
      当页面首次加载时,按钮上会显示 count 的初始值,并带有 ++ 字样。由于使用了 v-once,
      无论 count 的值在后续如何变化,按钮上的显示内容都不会更新。
      但是,每次点击按钮,count 的值确实会增加,只是按钮上的显示不会反映这个变化。
plain 复制代码
v-pre 指令会跳过这个元素及其子元素的编译过程。
  也就是说,这个元素中的内容会被原样输出,不会被 Vue 的模板编译器处理。
  例:<p v-pre>这是一段内容:{{name}}</p>中,
  <p> 元素中的内容 "这是一段内容:{{name}}" 会直接显示在页面上,
   不会将 {{name}} 作为插值表达式进行解析和替换为 name 变量的值。
     
相关推荐
无限聚核1 分钟前
抖音 certificate.prepare 之后怎么验券?和美团 msconsume 差在哪,无限聚核
前端·微信小程序
2603_9658966210 分钟前
Grid 网格布局|CSS 二维页面排版体系
前端·css
有味道的男人26 分钟前
搜好货平台关键词商品搜索接口:分页容错与商品数据轻量化提取方案
服务器·前端·javascript
lovingsoft1 小时前
Chrome Lighthouse 详解
前端·chrome
Qlly1 小时前
全栈工程师怎么接需求?从一句「加个功能」聊到能开发、能验收
前端·后端
马可家的菠萝1 小时前
你的微信“文件传输助手”,是不是已经成了第二个网盘?
前端·后端·架构
略略略啦1 小时前
Vibe Coding 基于Spec DD和TDD的实践指南
前端
shmily麻瓜小菜鸡2 小时前
前端实现图片与PDF文字识别敏感信息打码方案
前端·pdf·状态模式
打工仔折腾 AI2 小时前
LangChain 工具调用实战:从 Tool 定义到 Agent 执行链路拆解
java·前端·人工智能·后端·python·langchain·ai agent 实战
汉堡大王95272 小时前
单次输出拉到100万Token:拆完 Gemini 4 Argon 的续写协议,才看懂谷歌这7个月在憋什么
前端·人工智能·后端