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 变量的值。
     
相关推荐
童先生16 分钟前
Nginx + Vue/React 前端 + API:防止路径混淆漏洞与跨域问题实战分享
前端·vue.js·nginx
黑夜照亮前行的路1 小时前
JavaScript 性能优化实战技术指南
javascript·性能优化
万少3 小时前
可可图片编辑 HarmonyOS 上架应用分享
前端·harmonyos
你的人类朋友3 小时前
git常见操作整理(持续更新)
前端·git·后端
无羡仙3 小时前
Webpack 核心实战:从零搭建支持热更新与 Babel 转译的现代前端环境
前端·webpack·前端框架
乐~~~3 小时前
el-date-picker type=daterange 日期范围限制
javascript·vue.js·elementui
你的人类朋友3 小时前
git中的Fast-Forward是什么?
前端·git·后端
初遇你时动了情3 小时前
uniapp vue3 ts自定义底部 tabbar菜单
前端·javascript·uni-app
JarvanMo4 小时前
天塌了?Flutter工程总监跑去苹果了?
前端