Vue-基础语法(二)

Vue常用特性

一、表单基本操作

1、获取单选框中的值(value属性)

  • 通过v-model双向绑定

    1、 两个单选框需要同时通过v-model 双向绑定一个值(其实绑定的就是value属性值)
    2、 每一个单选框必须要有value属性,且value 值不能一样
    3、 当某一个单选框选中的时候 v-model 会用当前的 value值 修改绑定的数据

<!-- 
    gender 的值就是选中的值,我们只需要实时监控他的值就可以了
-->
<input type="radio" id="male" value="1" v-model='gender'>
<label for="male">男</label>
<input type="radio" id="female" value="2" v-model='gender'>
<label for="female">女</label>
<script>
    new Vue({
        data: {
            // 默认会让当前的 value 值为 2 的单选框选中
            gender: 2,
        },
    })
</script>

2、获取复选框中的值

  • 通过v-model

  • 和获取单选框中的值一样

  • 复选框 checkbox 这种的组合时 data 中的 hobby 我们要定义成 数组,否则无法实现多选

    1、 复选框需要同时通过v-model 双向绑定 一个值
    2、 每一个复选框必须要有value属性 且value 值不能一样
    3、 当某一个复选框选中的时候 v-model 会将当前的 value值 改变 data 中的 数据

<!-- 
    hobby 的值就是选中的值,我们只需要实时监控他的值就可以了
-->
<div>
    <span>爱好:</span>
    <input type="checkbox" id="ball" value="1" v-model='hobby'>
    <label for="ball">篮球</label>
    <input type="checkbox" id="sing" value="2" v-model='hobby'>
    <label for="sing">唱歌</label>
    <input type="checkbox" id="code" value="3" v-model='hobby'>
    <label for="code">写代码</label>
</div>
<script>
    new Vue({
        data: {
            // 默认会让当前的 value 值为 2 和 3 的复选框选中
            hobby: ['2', '3'],
        },
    })
</script>

3、获取下拉框和文本框中的值

  • 通过v-model

    1、 需要给select 通过v-model 双向绑定 一个值
    2、 每一个option 必须要有value属性 且value 值不能一样
    3、 当某一个option选中的时候 v-model 会将当前的 value值 改变 data 中的 数据

<div>
    <span>职业:</span>
    <!--
        occupation 的值就是选中的值,我们只需要实时监控他的值就可以了
    -->
    <!-- multiple  多选 -->
    <select v-model='occupation' multiple>
                <option value="0">请选择职业...</option>
                <option value="1">教师</option>
                <option value="2">软件工程师</option>
                <option value="3">律师</option>
            </select>
    <!-- textarea 是 一个双标签   不需要绑定value 属性的  -->
    <textarea v-model='desc'></textarea>
</div>
<script>
    new Vue({
        data: {
            // 默认会让当前的 value 值为 2 和 3 的下拉框选中
            occupation: ['2', '3'],
            desc: 'nihao'
        },
    })
</script>

4、表单修饰符

  • .number 转换为数值
    • 注意点:
    • 当开始输入非数字的字符串时,因为Vue无法将字符串转换成数值,所以属性值将实时更新成相同的字符串。即使后面输入数字,也将被视作字符串。
  • .trim 自动过滤用户输入的首尾空白字符
    • 只能去掉首尾的 不能去除中间的空格
  • .lazy 将input事件切换成change事件
    • .lazy 修饰符延迟了同步更新属性值的时机。即将原本绑定在 input 事件的同步逻辑转变为绑定在 change 事件上
    • 在失去焦点 或者 按下回车键时才更新
    <!-- 自动将用户的输入值转为数值类型 -->
    <input v-model.number="age" type="number">

    <!--自动过滤用户输入的首尾空白字符   -->
    <input v-model.trim="msg">

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

5、自定义指令

  • 内置指令不能满足我们特殊的需求
  • Vue允许我们自定义指令

Vue.directive() 注册全局指令

    
      使用自定义的指令,只需在对应的元素中,加上'v-'的前缀形成类似于内部指令'v-if','v-text'的形式。 
    
    <input type="text" v-focus>
    <script>
         注意点: 
           1、 在自定义指令中  如果以驼峰命名的方式定义 如  Vue.directive('focusA',function(){}) 
           2、 在HTML中使用的时候 只能通过 v-focus-a 来使用 

        // 注册一个全局自定义指令 v-focus
        Vue.directive('focus', {
            // 当绑定元素插入到 DOM 中。 其中 el为 dom元素
            inserted: function(el) {
                // 聚焦元素
                el.focus();
            }
        });
        new Vue({  
            el: '#app'
        });
    </script>

Vue.directive() 注册全局指令 带参数

bind声明周期:
只调用一次, 指令第一次绑定到元素时调用。 标签还没渲染到页面上,不可以使用js特效。在这里可以进行一次性的初始化设置。
el 为当前自定义指令的DOM元素
binding 为自定义的函数形参 通过自定义属性传递过来的值 存在 binding.value 里面 binding.name 是指令名

inserted生命周期:
插入这个指令的标签一ing显示到页面上,可以写js特效

update生命周期:
插入这个指令的标签一ing显示到页面上,可以写js特效

    <input type="text" v-color='test'>
    <script type="text/javascript">

        Vue.directive('color', {
            bind: function(el, binding) {
                // 根据指令的参数设置背景色
                el.style.backgroundColor = binding.value.color;
            },
            inserted: function(el) {
                // 聚焦元素
                el.focus();
            }
        });

        var vm = new Vue({
            el: '#app',
            data: {
                test: {
                    color: 'blue'
                }
            }
        });
    </script>

自定义指令局部指令

  • 局部指令,需要定义在 vm实例的 directives 的选项 用法和全局用法一样
  • 局部指令只能在当前组件(vm实例)里面使用
  • 当全局指令和局部指令同名时以局部指令为准
    <input type="text" v-color='msg'>
    <input type="text" v-focus>
    <script type="text/javascript">
        /*
             自定义指令-局部指令
           */
        var vm = new Vue({
            el: '#app',
            data: {
                msg: {
                    color: 'red'
                }
            },
            //局部指令,需要定义在  directives 的选项
            directives: {
                color: {
                    bind: function(el, binding) {
                        el.style.backgroundColor = binding.value.color;
                    }
                },
                focus: {
                    inserted: function(el) {
                        el.focus();
                    }
                }
            }
        });
    </script>

钩子函数

钩子函数

钩子函数参数

钩子函数参数

总结:

钩子函数 调用时期 特点
bind
inserted
update

6、计算属性 computed

  • 模板中放入太多的逻辑会让模板过重且难以维护 使用计算属性可以让模板 更加的简洁

  • 当多次调用computed里的 计算属性(方法) 的时候 ,只要里面的 引用的 data中的数据值不改变,他会把第一次计算的结果直接返回,直到data 中的数据值改变,计算属性才会重新发生计算。

  • 计算属性是基于它们的响应式依赖(data中的数据)进行 缓存 的,比较耗时的操作可以节省性能

  • computed 比较适合对多个变量或者对象进行处理后返回一个结果值,也就是说多个变量中的某一个值发生了变化则我们监控的这个值也就会发生变化

<div id="app">
   
    <div>{{reverseString}}</div>
    <div>{{reverseString}}</div>
    多次调用methods中的方法的时候,每次都会重新调用
    <div>{{reverseMessage()}}</div>
    <div>{{reverseMessage()}}</div>
</div>
<script type="text/javascript">
    计算属性与方法的区别: 计算属性是基于依赖进行缓存的, 而方法不缓存
    var vm = new Vue({
        el: '#app',
        data: {
            msg: 'Nihao',
            num: 100
        },
        methods: {
            reverseMessage: function() {
                console.log('methods')
                return this.msg.split('').reverse().join('');
            }
        },
        //computed  属性 定义 和 data 已经 methods 平级 
        computed: {
            //  reverseString   这个是我们自己定义的名字 
            reverseString: function() {
                console.log('computed')
                var total = 0;
                //  当data 中的 num 的值改变的时候  reverseString  会自动发生计算  
                for (var i = 0; i <= this.num; i++) {
                    total += i;
                }
                // 这里一定要有return 否则 调用 reverseString 的 时候无法拿到结果    
                return total;
            }
        }
    });
</script>

7、侦听器 watch

  • 使用watch来响应数据的变化
  • 一般用于异步或者开销较大的操作
  • watch 中的属性 一定是data 中 已经存在的数据
  • 当需要监听一个对象的改变时,普通的watch方法无法监听到对象内部属性的改变,只有data中的数据才能够监听到变化,此时就需要deep属性对对象进行深度监听
<div id="app">
    <div>
        <span>名:</span>
        <span>
            <input type="text" v-model='firstName'>
        </span>
    </div>
    <div>
        <span>姓:</span>
        <span>
    <input type="text" v-model='lastName'>
  </span>
    </div>
    <div>{{fullName}}</div>
</div>
<script type="text/javascript">
    /*
       侦听器
    */
    var vm = new Vue({
        el: '#app',
        data: {
            firstName: 'Jim',
            lastName: 'Green',
            // fullName: 'Jim Green'
        },
         //watch  属性 定义 和 data 已经 methods 平级 
        watch: {
            //   注意:  这里firstName  对应着data 中的 firstName 
            //   当 firstName 值 改变的时候  会自动触发 watch
            firstName: function(val) {
                this.fullName = val + ' ' + this.lastName;
            },
            //   注意:  这里 lastName 对应着data 中的 lastName 
            lastName: function(val) {
                this.fullName = this.firstName + ' ' + val;
            }
        }
    });
</script>

8、过滤器

  • Vue.js允许自定义过滤器,可被用于一些常见的文本格式化。
  • 过滤器可以用在两个地方:双花括号插值和v-bind表达式。
  • 过滤器应该被添加在JavaScript表达式的尾部,由“管道”符号指示
  • 支持级联操作
  • 过滤器不改变真正的data,而只是改变渲染的结果,并返回过滤后的版本
  • 全局注册时是filter,没有s的。而局部过滤器是filters,是有s的
<div id="app">
    <input type="text" v-model='msg'>
    <!-- upper 被定义为接收单个参数的过滤器函数,表达式  msg  的值将作为参数传入到函数中 -->
    <div>{{msg | upper}}</div>
    <!--  
      支持级联操作
      upper  被定义为接收单个参数的过滤器函数,表达式msg 的值将作为参数传入到函数中。
      然后继续调用同样被定义为接收单个参数的过滤器 lower ,将upper 的结果传递到lower中
    -->
    <div>{{msg | upper | lower}}</div>
    <div :abc='msg | upper'>测试数据</div>
</div>
<script type="text/javascript">
    //  lower  为全局过滤器     
    Vue.filter('lower', function(val) {
        return val.charAt(0).toLowerCase() + val.slice(1);
    });
    var vm = new Vue({
        el: '#app',
        data: {
            msg: ''
        },
        //filters  属性 定义 和 data 已经 methods 平级 
        //  定义filters 中的过滤器为局部过滤器 
        filters: {
            //   upper  自定义的过滤器名字 
            //    upper 被定义为接收单个参数的过滤器函数,表达式  msg  的值将作为参数传入到函数中
            upper: function(val) {
                //  过滤器中一定要有返回值 这样外界使用过滤器的时候才能拿到结果
                return val.charAt(0).toUpperCase() + val.slice(1);
            }
        }
    });
</script>

过滤器中传递参数

<div id="box">
    
        filterA 被定义为接收三个参数的过滤器函数。
        其中 message 的值作为第一个参数,
        普通字符串 'arg1' 作为第二个参数,表达式 arg2 的值作为第三个参数。
    
    {{ message | filterA('arg1', 'arg2') }}
</div>
<script>
    在过滤器中 第一个参数 对应的是  管道符前面的数据   n  此时对应 message
    第2个参数  a 对应 实参  arg1 字符串
    第3个参数  b 对应 实参  arg2 字符串
    Vue.filter('filterA',function(n,a,b){
        if(n<10){
            return n+a;
        }else{
            return n+b;
        }
    });
    
    new Vue({
        el:"#box",
        data:{
            message: "哈哈哈"
        }
    })
</script>

9、生命周期

Vue实例从 创建销毁 的过程 ,这些过程中会伴随着一些函数的自调用。我们称这些函数为 钩子函数

常用的 钩子函数

钩子函数 函数调用时期 vm实例
beforeCreate: 实例初始化之后,数据观测和事件配置之前被调用 vm实例刚创建,此时data 和 methods 以及页面的DOM结构都没有初始化 什么都做不了
created: 实例创建完成后被立即调用 vm实例创建完毕,可以访问和操作相关属性,但是页面还没有渲染出来
beforeMount: 在挂载开始之前被调用 页面模板(虚拟dom)已经在内存中生成,但还没有渲染到页面上
mounted: el被新创建的vm.$el替换,并挂载到实例上去之后调用该钩子。 dom结构渲染完毕, 数据已经真实渲染到页面上,在这个钩子函数里面我们可以使用一些第三方的插件
beforeUpdate: 数据更新时调用,发生在虚拟DOM打补丁之前。 虚拟dom更新,但未同步到页面上,页面上数据还是旧的
updated: 由于数据更改导致的虚拟DOM重新渲染和打补丁,在这之后会调用该钩子。 页面上数据已经替换成最新的
beforeDestroy: 实例销毁之前调用 实例销毁之前,此时还可以访问实例的属性
destroyed: 实例销毁后调用 实例已销毁,页面切换时实例自动销毁

10、数组变异方法(修改数组数据会触发更新视图)

  • 在 Vue 中,直接修改对象属性的值无法触发响应式。当你直接修改了对象属性的值,你会发现,只有数据改了,但是页面内容并没有改变(例如:arr[0]="zs",视图不会更新)

  • 变异数组方法即保持数组方法原有功能不变的前提下对其进行功能拓展

  • 变异方法(修改原数组,触发视图更新):

    push() 往数组最后面添加一个元素,成功返回当前数组的长度
    pop() 删除数组的最后一个元素,成功返回删除元素的值
    shift() 删除数组的第一个元素,成功返回删除元素的值
    unshift() 往数组最前面添加一个元素,成功返回当前数组的长度
    splice() 有三个参数,第一个是想要删除的元素的下标(必选),第二个是想要删除的个 数(必选),第三个是删除 后想要在原位置替换的值
    sort() sort() 使数组按照字符编码默认从小到大排序,成功返回排序后的数组
    reverse() reverse() 将数组倒序,成功返回倒序后的数组

  • 替换数组(返回新数组,不修改原数组,不会触发视图更新):

    filter filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
    concat concat() 方法用于连接两个或多个数组。该方法不会改变现有的数组
    slice slice() 方法可从已有的数组中返回选定的元素。该方法并不会修改数组,而是返回一个子数组

  • 动态数组响应式数据
    vm.arr[0] = "zs" 使用索引修改数据不会触发视图更新
    使用1: Vue.set(vm.items,indexOfItem,newValue)
    使用2: Vue.$set(vm.items,indexOfItem,newValue)

    • Vue.set(a,b,c) 让 触发视图重新更新一遍,数据动态起来
    • a是要更改的数组/对象 、 b是数组的索引/对象的属性名、 c是要更改的值
  • some、filter、map、findIndex函数
    隐式迭代

推荐阅读更多精彩内容