vue-day03

155 阅读6分钟

1、列表渲染

<body>
    <!-- 
        v-for指令:
            1.用于展示列表数据
            2.语法:v-for="(item, index) in xxx" :key="yyy"
            3.可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)
    -->
    <!-- 准备好一个容器-->
    <div id="root">
        <!-- 遍历数组 -->
        <h2>人员列表(遍历数组)</h2>
        <ul>
            <li v-for="(p,index) of persons" :key="index">
                {{p.name}}-{{p.age}}
            </li>
        </ul>

        <!-- 遍历对象 -->
        <h2>汽车信息(遍历对象)</h2>
        <ul>
            <li v-for="(value,k) of car" :key="k">
                {{k}}-{{value}}
            </li>
        </ul>

        <!-- 遍历字符串 -->
        <h2>测试遍历字符串(用得少)</h2>
        <ul>
            <li v-for="(char,index) of str" :key="index">
                {{char}}-{{index}}
            </li>
        </ul>

        <!-- 遍历指定次数 -->
        <h2>测试遍历指定次数(用得少)</h2>
        <ul>
            <li v-for="(number,index) of 5" :key="index">
                {{index}}-{{number}}
            </li>
        </ul>
        </div>

<script>
    new Vue({
        el:'#root',
        data:{
            persons:[
                {id:'001',name:'张三',age:18},
                {id:'002',name:'李四',age:19},
                {id:'003',name:'王五',age:20}
            ],
            car:{
                name:'奥迪A8',
                price:'70万',
                color:'黑色'
            },
            str:'hello'
        }
    })
</script>

2、key作用与原理

<!-- 
面试题:react、vue中的key有什么作用?(key的内部原理)
1. 虚拟DOM中key的作用:
    key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】, 随后Vue
    进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:

2.对比规则:
    (1).旧虚拟DOM中找到了与新虚拟DOM相同的key:
        ①.若虚拟DOM中内容没变, 直接使用之前的真实DOM!
        ②.若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM。

    (2).旧虚拟DOM中未找到与新虚拟DOM相同的key
        创建新的真实DOM,随后渲染到到页面。

3. 用index作为key可能会引发的问题:
    1. 若对数据进行:逆序添加、逆序删除等破坏顺序操作:
        会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低。

    2. 如果结构中还包含输入类的DOM:
        会产生错误DOM更新 ==> 界面有问题。

4. 开发中如何选择key?:
    1.最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号、学号等唯一值。
    2.如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,
    使用index作为key是没有问题的。
-->

3、列表过滤(使用的是数组的filter方法)

let numbers = [1, 2, 3, 4, 5, 6];
let evenNumbers = numbers.filter(function(number) {
  return number % 2 === 0;
});
// evenNumbers现在是[2, 4, 6]
<!-- 准备好一个容器-->
<div id="root">
    <h2>人员列表</h2>
    <input type="text" placeholder="请输入名字" v-model="keyWord">
    <ul>
        <li v-for="(p,index) of filPerons" :key="index">
            {{p.name}}-{{p.age}}-{{p.sex}}
        </li>
    </ul>
</div>
<script>
    //用watch实现
    new Vue({
        el:'#root',
        data:{
            keyWord:'',
            persons:[
                {id:'001',name:'马冬梅',age:19,sex:'女'},
                {id:'002',name:'周冬雨',age:20,sex:'女'},
                {id:'003',name:'周杰伦',age:21,sex:'男'},
                {id:'004',name:'温兆伦',age:22,sex:'男'}
            ],
            filPerons:[]
        },
        watch:{
            keyWord:{
                immediate:true,
                handler(val){
                    this.filPerons = this.persons.filter((p)=>{
                        return p.name.indexOf(val) !== -1
                    })
                }
            }
        }
    }) 
</script>
<script>			
    //用computed实现
    new Vue({
        el:'#root',
        data:{
            keyWord:'',
            persons:[
                        {id:'001',name:'马冬梅',age:19,sex:'女'},
                        {id:'002',name:'周冬雨',age:20,sex:'女'},
                        {id:'003',name:'周杰伦',age:21,sex:'男'},
                        {id:'004',name:'温兆伦',age:22,sex:'男'}
                    ]
            },
            computed:{
                filPerons(){
                        return this.persons.filter((p)=>{
                                return p.name.indexOf(this.keyWord) !== -1
                        })
                }
        }
    }) 
</script>

4、列表排序(搜索出结果之后,再进行排序)

<body>
    <!-- 准备好一个容器-->
    <div id="root">
        <h2>人员列表</h2>
        <input type="text" placeholder="请输入名字" v-model="keyWord">
        <button @click="sortType = 2">年龄升序</button>
        <button @click="sortType = 1">年龄降序</button>
        <button @click="sortType = 0">原顺序</button>
        <ul>
            <li v-for="(p,index) of filPerons" :key="p.id">
                {{p.name}}-{{p.age}}-{{p.sex}}
                <input type="text">
            </li>
        </ul>
    </div>
    <script>
        new Vue({
            el:'#root',
            data:{
                keyWord:'',
                sortType:0, //0原顺序 1降序 2升序
                persons:[
                            {id:'001',name:'马冬梅',age:30,sex:'女'},
                            {id:'002',name:'周冬雨',age:31,sex:'女'},
                            {id:'003',name:'周杰伦',age:18,sex:'男'},
                            {id:'004',name:'温兆伦',age:19,sex:'男'}
                        ]
                },
            computed:{
                    filPerons(){
                        const arr = this.persons.filter((p)=>{
                                return p.name.indexOf(this.keyWord) !== -1
                        })
                        //判断一下是否需要排序
                        if(this.sortType){
                            arr.sort((p1,p2)=>{
                                // 数组的sort方法可以改变原数组,此时的p1代表的是数组里面的一项
                                return this.sortType === 1 ? p2.age-p1.age : p1.age-p2.age
                                })
                            }
                        return arr
                    }
            }
        }) 
    </script>

5、对象。Vue.set()是Vue.js提供的一个全局方法,用于向响应式对象添加响应式属性。在Vue中,如果直接给一个对象添加新的属性,这个属性将不会是响应式的,也就是说当这个属性发生变化时,视图不会更新。为了解决这个问题,Vue提供了Vue.set()方法来手动将属性添加为响应式属性,这样当属性发生变化时,视图就会得到更新
这个方法接受三个参数:要添加属性的对象,属性名,属性值。

// 对象:响应式数据
Vue.set(vm.someObject, 'newProperty', 'someValue');
vm.$set(vm.someObject, 'newProperty', 'someValue')
// Vue官方文档:注意对象不能是Vue实例(vm),也不能是Vue实例的根数据对象(Vm._data)

6、改变原数组的API(7个):push(末尾添加一个数据)、pop(末尾删除一个数据)、shift(头部删除一个数据)、unshift(头部添加一个数据)、sort(进行排序,数组的首个字母按照从大到小的顺序排序)、reverse(数组的反转)、splice(用来删除或者是插入数据的)
数组.splice(开始索引,多少个,你要插入的数据)
只要调用了修改数组的方法,vue才会承认修改数组了,别的方法调用vue不认为改变了数组

7、总结vue监视数据:

Vue监视数据的原理:
    1. vue会监视data中所有层次的数据。

    2. 如何监测对象中的数据?
        通过setter实现监视,且要在new Vue时就传入要监测的数据。
                (1).对象中后追加的属性,Vue默认不做响应式处理
                (2).如需给后添加的属性做响应式,请使用如下APIVue.set(target,propertyName/index,value)或者vm.$set(target,propertyName/index,value)
                    
    3. 如何监测数组中的数据?
            通过包裹数组更新元素的方法实现,本质就是做了两件事:
                (1).调用原生对应的方法对数组进行更新。
                (2).重新解析模板,进而更新页面。

    4.Vue修改数组中的某个元素一定要用如下方法:
        1.使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
        2.Vue.set() 或 vm.$set()

    特别注意:Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象 添加属性!!!

8、收集表单数据

收集表单数据:
    若:<input type="text"/>,则v-model收集的是value值,用户输入的就是value值。
    若:<input type="radio"/>,则v-model收集的是value值,且要给标签配置value值。
    若:<input type="checkbox"/>
            1.没有配置input的value属性,那么收集的就是checked(勾选 or 未勾选,是布尔值)
            2.配置input的value属性:
                (1)v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,是布尔值)
                (2)v-model的初始值是数组,那么收集的的就是value组成的数组
    备注:v-model的三个修饰符:
        lazy:失去焦点再收集数据
        number:输入字符串转为有效的数字
        trim:输入首尾空格过滤

代码演示如下:

<body>
    <!-- 准备好一个容器-->
    <div id="root">
        <form @submit.prevent="demo">
            账号:<input type="text" v-model.trim="userInfo.account"> <br/><br/>
            密码:<input type="password" v-model="userInfo.password"> <br/><br/>
            年龄:<input type="number" 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" v-model="userInfo.hobby" value="study">
            打游戏<input type="checkbox" v-model="userInfo.hobby" value="game">
            吃饭<input type="checkbox" v-model="userInfo.hobby" value="eat">
            <br/><br/>
            所属校区
            <select v-model="userInfo.city">
                    <option value="">请选择校区</option>
                    <option value="beijing">北京</option>
                    <option value="shanghai">上海</option>
                    <option value="shenzhen">深圳</option>
                    <option value="wuhan">武汉</option>
            </select>
            <br/><br/>
            其他信息:
            <textarea v-model.lazy="userInfo.other"></textarea> <br/><br/>
            <input type="checkbox" v-model="userInfo.agree">阅读并接受<a href="http://www.baidu.com">《用户协议》</a>
            <button>提交</button>
        </form>
    </div>
</body>
<script type="text/javascript">
    new Vue({
            el:'#root',
            data:{
                userInfo:{
                        account:'',
                        password:'',
                        age:18,
                        sex:'female',
                        hobby:[],  //数组的形式
                        city:'beijing',
                        other:'',
                        agree:''
                }
            },
            methods: {
                    demo(){
                        console.log(JSON.stringify(this.userInfo))
                    }
            }
    })
</script>

9、过滤器 在vue中,过滤器允许我们在数据呈现之前对其进行处理。这在需要格式化文档、日期、数字等数据时非常有用,可以使用全局过滤器或者局部过滤器来实现这一点。
全局过滤器可以在Vue实例化之前定义,以便在整个应用程序中使用。例子:

<body>
    <!-- 准备好一个容器-->
    <div id="root">
        <h2>显示格式化后的时间</h2>
        <!-- 计算属性实现 -->
        <h3>现在是:{{fmtTime}}</h3>
        <!-- methods实现 -->
        <h3>现在是:{{getFmtTime()}}</h3>
        <!-- 过滤器实现 过滤器的名字叫做timeFormater -->
        <!-- 要展示的数据,过滤器的名字 -->
        <h3>现在是:{{time | timeFormater}}</h3>
        <!-- 过滤器实现(传参) -->
        <!-- 多个过滤器之间可以串联 -->
        <!-- 首先把time传给timeFormater,处理之后的结果再传给mySlice -->
        <h3>现在是:{{time | timeFormater('YYYY_MM_DD') | mySlice}}</h3>
        <h3 :x="msg | mySlice">dlrb</h3>
    </div>
    <div id="root2">
        <h2>{{msg | mySlice}}</h2>
    </div>
</body>
<script>
    //全局过滤器
    Vue.filter('mySlice',function(value){
        return value.slice(0,4)
    })
    new Vue({
        el:'#root',
        data:{
            time:1621561377603, //时间戳
            msg:'你好'
        },
        computed: {
            fmtTime(){
                    return dayjs(this.time).format('YYYY年MM月DD日 HH:mm:ss')
            }
        },
        methods: {
            getFmtTime(){
                    return dayjs(this.time).format('YYYY年MM月DD日 HH:mm:ss')
            }
        },
        //局部过滤器
        filters:{
            // 过滤器的本质是一个函数
            // time | timeFormater:读取time,随后把time当作参数传给timeFormater函数
            timeFormater(value,str='YYYY年MM月DD日 HH:mm:ss'){
                    return dayjs(value).format(str)
            },
            mySlice(value){
                    return value.slice(0,4)
            }
        }
    })
    new Vue({
        el:'#root2',
        data:{
            msg:'hello,dilraba'
        }
    })
</script>
过滤器:
    定义:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)。
    语法:
        1.注册过滤器:Vue.filter(name,callback) 或 new Vue{filters:{}}
        2.使用过滤器:{{ xxx | 过滤器名}}  或  v-bind:属性 = "xxx | 过滤器名"
    备注:
        1.过滤器也可以接收额外参数、多个过滤器也可以串联
        2.并没有改变原本的数据, 是产生新的对应的数据