Vue学习笔记三

一、Vue监测数据原理

1、更新data数据时的一个问题

如下代码所示,某些情况下更改data中的属性值,页面不会发生变化 

<body>
    <div id="root">
        <h2>人员列表</h2>
        <button @click="update">更新马冬梅信息</button>
        <ul>
            <li v-for="p in persons" :key="p.id">
                姓名:{{p.name}},年龄:{{p.age}},性别:{{p.sex}}
            </li>
        </ul>
    </div>
</body>

<script type="text/javascript">
Vue.config.productionTip = false;

const vm = new Vue({
    el: '#root',
    data: {
        persons: [
            {id:'001',name:'马冬梅',age:18,sex:'女'},
            {id:'002',name:'周杰伦',age:19,sex:'男'},
            {id:'003',name:'周冬雨',age:20,sex:'女'},
            {id:'004',name:'温兆伦',age:21,sex:'男'}
        ]
    },
    methods: {
        update() {
            // 下面这3行会使页面发生变化
            // this.persons[0].name = '马老师';
            // this.persons[0].age = 50;
            // this.persons[0].sex = '男';

            // 下面这一行不会使页面发生变化
            this.persons[0] = {id:'001',name:'马老师',age:50,sex:'男'};
        }
    }
})
</script>

2、Vue.set添加属性

<body>
    <div id="root">
        <button @click.once = "addSex">添加性别</button>
        <button @click.once = "addNumber">添加数量</button>
        <h2>学校名:{{name}}</h2>
        <h2>地址:{{name}}</h2>
        <h2>学生姓名:{{school.name}}</h2>
        <h2>学生年纪:{{school.age}}</h2>
        <h2>学生性别:{{school.sex}}</h2>
    </div>
</body>

<script type="text/javascript">
    Vue.config.productionTip = false;
    
    const vm = new Vue({
        el: '#root',
        data: {
            name:'尚硅谷',
            address: '北京',
            school: {
                name: '张三',
                age: 20
            }
        },
        methods: {
            addSex() {
                Vue.set(this.school, 'sex', '男');
            },
            // 下面这个会报错,不能直接往data中加属性,只能给data中的对象加属性
            addNumber() {
                Vue.set(this, 'number', 20);
            }
        }
    })
    </script>

3、vm监测数据总结

vm中的属性有响应式的get和set方法,当发生修改时会调用set方法,并在set方法中生成新的虚拟vm对象,并和原来的进行比较,有区别的地方会进行更改,所以我们可以看到页面上的变化。但上面章节1中,直接将数组中的某个对象替换,而这一操作是没有set方法的,所以不会有效果

如下所示,persons是数组,persons自身有get、set方法。但数组中的每个对象自身没有get、set方法。而对象中的每个属性又有get、set方法,所以会出现上面章节1的结果

而如果要对数组进行操作,必须使用push、splice、pop、shift、unshift等方法才行,如下所示就会有效果,因为vm对这些方法进行了重构 

    methods: {
        update() {
            // 下面这3行会使页面发生变化
            // this.persons[0].name = '马老师';
            // this.persons[0].age = 50;
            // this.persons[0].sex = '男';

            // 下面这一行不会使页面发生变化
            // this.persons[0] = {id:'001',name:'马老师',age:50,sex:'男'};

            // 下面这一行会使页面发生变化
            this.persons.splice(0, 1, {id:'001',name:'马老师',age:50,sex:'男'});
        }
    }

 二、收集表单数据

<body>
    <div id="root">
        <form @submit.prevent="upload">
            <label for="account">账号:</label><input type="text" id="account" v-model.trim="userInfo.account"><br/><br/>
            <label for="pwd">密码:</label><input type="password" id="pwd" v-model="userInfo.pwd"><br/><br/>
            <label for="age">年龄:</label><input type="number" id="age" v-model.number="userInfo.age"><br/><br/>
            性别:
            <input type="radio" name="sex" v-model="userInfo.sex" value="male">男
            <input type="radio" name="sex" v-model="userInfo.sex" value="female">女
            <br/><br/>
            爱好:
            <input type="checkbox" name="hobby" v-model="userInfo.hobby" value="study">学习
            <input type="checkbox" name="hobby" v-model="userInfo.hobby" value="game">打游戏
            <input type="checkbox" name="hobby" v-model="userInfo.hobby" value="eat">吃饭
            <br/><br/>
            所属校区:
            <select v-model="userInfo.city">
                <option value="">请选择校区</option>
                <option value="biejing">北京</option>
                <option value="shanghai">上海</option>
                <option value="guangzhou">广州</option>
            </select>
            <br/><br/>
            其他信息:
            <textarea v-model="userInfo.other"></textarea><br/><br/>
            <input type="checkbox" v-model="userInfo.agree">阅读并接受<a href="https://www.baidu.com" target="_blank">《用户协议》</a><br/><br/>
            <button>提交</button><br/>
        </form>
    </div>
</body>

<script type="text/javascript">
Vue.config.productionTip = false;

const vm = new Vue({
    el: '#root',
    data: {
        userInfo: {
            account: '',
            pwd: '',
            age: 18,
            sex: 'female',
            hobby: [],
            city: 'shanghai',
            other: '',
            agree: true
        }
    },
    methods: {
        upload() {
            console.log(JSON.stringify(this.userInfo));
        }
    }
})
</script>

三、内置指令

1、v-text

  • v-text会直接替换节点中所有内容,{{XXX}}不会
  • v-text无法识别html结构

2、v-html

  • v-html可以识别html结构
  • 有安全问题,动态渲染html容易导致XXS攻击

3、v-cloak

  • 是一个特殊属性,vue实例创建完毕并接管实例后,会删掉v-cloak属性
  • 使用css的属性display:none配合v-cloak可以解决网速慢时页面展示出{{XXX}}的问题
<head>
    <style>
        [v-cloak] {
            display: none;
        }
    </style>
</head>

<body>
    <div id="root">
        <h2 v-cloak>{{name}}</h2>
    </div>
</body>

4、v-once指令

v-once所在节点在初次渲染后,视为静态内容,以后数据的改变不会引起v-once结构的更新,可以用于优化性能

<body>
    <div id="root">
        <h2 v-once>初始化n值是:{{n}}</h2>
        <h2>当前n值是:{{n}}</h2>
        <button @click="n++">点我n+1</button>
    </div>
</body>

<script type="text/javascript">
Vue.config.productionTip = false;

new Vue({
    el: '#root',
    data: {
        n: 1
    }
})
</script>

5、v-pre指令

跳过其所在节点的编译过程,可利用它跳过没有vue语法的节点,加快编译

<body>
    <div id="root">
        <h2 v-pre>演示pre指令</h2>  <!-- 这一行vue就会直接跳过,不会判断是否需要编译 -->
        <h2 v-pre>当前n值是:{{n}}</h2>
        <button @click="n++">点我n+1</button>
    </div>
</body>

<script type="text/javascript">
Vue.config.productionTip = false;

new Vue({
    el: '#root',
    data: {
        n: 1
    }
})
</script>

四、自定义指令

1、自定义2个指令

  • v-big:n改变时,自动乘10
  • v-fbind:展示n的值,并自动获取光标 
<body>
    <div id="root">
        <h2>当前的n值是:<span v-text="n"></span></h2>
        <h2>放大10倍的n值是:<span v-big="n"></span></h2>
        <button @click="n++">点我n+1</button>
        <hr/>
        <input type="text" v-fbind:value="n">
    </div>
</body>

<script type="text/javascript">
Vue.config.productionTip = false;

new Vue({
    el: '#root',
    data: {
        n: 1
    },
    directives: {
        // 1、指令与元素成功绑定时,被调用
        // 2、指令所在的模板被重新解析时,被调用
        // 3、binding.value值就是v-big="n"中的n的值
        big(element, binding) {
            element.innerText = binding.value * 10;
        },
        fbind: {
            // 当指令与元素成功绑定时
            bind(element, binding) {
                element.value = binding.value;

            },
            // 指令所在元素被插入页面时
            inserted(element, binding) {
                element.focus();
            },
            // 指令所在模板被重新解析时
            update(element, binding) {
                element.value = binding.value;
                element.focus();
            }
        }
    }
})
</script>

五、生命周期

如下图所示,其中mounted和beforeDestroy最为重要 

 mounted和beforeDestroy样例,vm.$destroy会销毁vm实例,从而触发beforeDestroy

<div id="root">
  <h2 :style="{opacity}">欢迎学习Vue</h2>
  <button @click="opacity = 1">透明度设置为1</button>
  <button @click="stop">点我停止变换</button>
</div>

<script type="text/javascript">
  Vue.config.productionTip = false
  new Vue({
    el: '#root',
    data: {
      opacity: 1
    },
    methods: {
      stop() {
        this.$destroy()
      }
    },
    // Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕)调用mounted
    mounted() {
      console.log('mounted', this)
      this.timer = setInterval(() => {
        console.log('setInterval')
        this.opacity -= 0.01
        if (this.opacity <= 0) this.opacity = 1
      }, 16)
    },
    beforeDestroy() {
      clearInterval(this.timer)
      console.log('vm即将驾鹤西游了')
    },
  })
</script>

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值