条件渲染\列表渲染\key原理\列表过滤\列表排序\Vue检测数据原理\总结Vue数据检测

目录

一.条件渲染

1.v-if

2.v-show

二.列表渲染

三.Key原理

四.列表过滤

五.列表排序

六.Vue监测数据原理

1.更新时的一个问题

2.Vue监测数据原理——对象

 3.Vue.set方法 

4.Vue监测数据原理——数组

​ 七.总结Vue数据监测


一.条件渲染

1.v-if

写法:

(1)v-if=“表达式”

(2)v-else-if=“表达式”

(3)v-else=“表达式”

适用于:切换频率较低的场景

特点:不展示DOM元素直接被移除

注意:v-if可以和:v-else-if\v-else一起用,但邀请结构不能被打断

2.v-show

写法:v-show=“表达式”

适用于:切换频率较高的场景

特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉

3.备注:使用v-if时,元素可能无法获取到,而使用v-show一定可以获取到

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8"/>
		<title>初识vue</title>
		<script type="text/javascript" src="../js/vue.js">
			alert("这是我的第一行JS代码")
			document.write("看我出不出来")
		</script>
	</head>
	<body>
        <!-- 容器 -->
        <div id="root">
            <h2>{{n}}</h2>
            <button @click="n++">点我加1</button>
            <!-- 使用v-show做条件渲染 -->
            <!-- <h2 v-show="false">hello{{name}}</h2>
            <h2 v-show="1 ===1">hello{{name}}</h2> -->
            <!-- 使用v-if做条件渲染 -->
            <!-- <h2 v-if="false">hello{{name}}</h2>
            <h2 v-if="1 ===1">hello{{name}}</h2> -->
            <!-- v-else和v-else-if -->
            <!-- <div v-if="n===1">A</div>
            <div v-else-if="n===2">B</div>
            <div v-else-if="n===3">C</div>
            <div v-else>哈哈</div> -->
            <template v-if="n===1">
                <h2>你好</h2>
                <h2>哈哈</h2>
                <h2>嗯嗯</h2>
            </template>
        </div>
        
		<script type="text/javascript" >
        Vue.config.productionTip = false
        const vm = new Vue({
            el:'#root',
            data:{
                name:'atguigu',
                a:false,
                n:0
            },
        })
        console.log(vm)
       
        </script>
	</body>
</html>

二.列表渲染

v-for指令

1。用于展示列表数据

2.语法:v-for="(item,index) in xxx" :key="yyy"

3.可遍历:数组、对象、字符串(很少)、指定次数(很少)

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8"/>
		<title>姓名案例</title>
		<script type="text/javascript" src="../js/vue.js">
		</script>
	</head>
	<body>
        <!-- 容器 -->
        <div id="root">
            <!-- 遍历数组(用的多) -->
            <ul>
                <!-- <li v-for="p in persons" :key="p.id">
                    {{p.name}}-{{p.age}}
                </li> -->
                <li v-for="(p,index) in persons" :key="index">
                    {{p.name}}-{{p.age}}
                </li>
            </ul>
            <!-- 遍历对象 -->
            <ul>
                <li v-for="(val,key) in car" :key="key">
                    {{key}}-{{val}}
                </li>
            </ul>
            <!-- 遍历字符串(用得少) -->
            <ul>
                <li v-for="(char,index) in str" :key="index">
                    {{char}}-{{index}}
                </li>
            </ul>
            <!-- 遍历指定次数(用得少) -->
            <ul>
                <li v-for="(number,index) in 5" :key="index">
                    {{index}}-{{number}}
                </li>
            </ul>
        </div>
        
		<script type="text/javascript" >
        Vue.config.productionTip = false
        new Vue({
            el:'#root',
            data:{
                persons:[
                {id:'001',name:'张三',age:'18'},
                {id:'002',name:'李四',age:'19'},
                {id:'003',name:'王五',age:'20'}
                ],
                car:{
                    name:"aodiA8",
                    price:"70wan",
                    color:"black"
                },
                str:'hello'
            }
        })
        </script>
	</body>
</html>

in也可以改为of

最好写上小括号

三.Key原理

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8"/>
		<title>姓名案例</title>
		<script type="text/javascript" src="../js/vue.js">
		</script>
	</head>
	<body>
        <!-- 容器 -->
        <div id="root">
            <!-- 遍历数组(用的多) -->
            <button @click="add">增加老刘</button>
            <ul>
                <li v-for="(p,index) in persons" :key="index">
                    {{p.name}}-{{p.age}}
                    <input type="text">
                </li>
            </ul>
           
        </div>
        
		<script type="text/javascript" >
        Vue.config.productionTip = false
        new Vue({
            el:'#root',
            data:{
                persons:[
                {id:'001',name:'张三',age:'18'},
                {id:'002',name:'李四',age:'19'},
                {id:'003',name:'王五',age:'20'}
                ],
                car:{
                    name:"aodiA8",
                    price:"70wan",
                    color:"black"
                },
                str:'hello'
            },
            methods:{
                add(){
                    const p = {id:'004',name:'老刘',age:'21'}
                    this.persons.unshift(p)
                }
            }
        })
        </script>
	</body>
</html>

当index作为列表渲染key,以上代码会有问题。需要改为id作为key

react和Vue中key有什么作用?(key的原理)

1.虚拟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是没有问题的。

四.列表过滤

1.收集用户输入

2.用用户输入进行匹配

写法1:watch

写法2:计算属性

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8"/>
		<title>姓名案例</title>
		<script type="text/javascript" src="../js/vue.js">
		</script>
	</head>
	<body>
        <!-- 容器 -->
        <div id="root">
            <!-- 遍历数组(用的多) -->
            <input type="text" placeholder="请输入名字" v-model="keyWord">
            <ul>
                <li v-for="(p,index) in filPersons" :key="index">
                    {{p.name}}-{{p.age}}--{{p.sex}}
                </li>
            </ul>
           
        </div>
        
		<script type="text/javascript" >
        Vue.config.productionTip = false
        //用watch实现
        /*new Vue({
            el:'#root',
            data:{
                keyWord:'',
                persons:[
                {id:'001',name:'马冬梅',age:'18',sex:'女'},
                {id:'002',name:'周冬雨',age:'19',sex:'女'},
                {id:'003',name:'周杰伦',age:'20',sex:'男'},
                {id:'003',name:'温兆伦',age:'21',sex:'男'}
                ],
                filPersons:[]
            },
           
            watch:{
                keyWord:{
                    immediate:true,
                    handler(val){
                        this.filPersons = this.persons.filter((p)=>{
                            return p.name.indexOf(val)!==-1
                        })
                    }
                }
            }
        })*/
        
        //用computed实现
        new Vue({
            el:'#root',
            data:{
                keyWord:'',
                persons:[
                {id:'001',name:'马冬梅',age:'18',sex:'女'},
                {id:'002',name:'周冬雨',age:'19',sex:'女'},
                {id:'003',name:'周杰伦',age:'20',sex:'男'},
                {id:'003',name:'温兆伦',age:'21',sex:'男'}
                ],
            },
           
            computed:{
                filPersons(){
                    return this.filPersons = this.persons.filter((p)=>{
                        return p.name.indexOf(this.keyWord)!==-1
                    })
                }
            }
        })
        </script>
	</body>
</html>

其中watch方法需要加immediate

计算属性方法,初始化会调一次,依赖的this.keyWord发生变化时也会调用

计算属性方法更方便

五.列表排序

其中,前减后未升序,后减前为降序

let arr =[1,3,2,6,4,5]
        arr.sort((a,b)=>{
            return b-a
        })
        console.log("@@",arr)
        //升序前减后,降序后减前

在computed中配置,把逻辑配在计算属性中,里面只要任何一个属性发生变化,整个计算属性都会重新计算。点击升序、降序,是在改sortType,每次修改sortType,计算属性重新计算

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8"/>
		<title>姓名案例</title>
		<script type="text/javascript" src="../js/vue.js">
		</script>
	</head>
	<body>
        <!-- 容器 -->
        <div id="root">
            <!-- 遍历数组(用的多) -->
            <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) in filPersons" :key="index">
                    {{p.name}}-{{p.age}}--{{p.sex}}
                </li>
            </ul>
           
        </div>
        
		<script type="text/javascript" >
        Vue.config.productionTip = false
        //用computed实现
        new Vue({
            el:'#root',
            data:{
                sortType:0,
                keyWord:'',
                persons:[
                {id:'001',name:'马冬梅',age:'30',sex:'女'},
                {id:'002',name:'周冬雨',age:'31',sex:'女'},
                {id:'003',name:'周杰伦',age:'18',sex:'男'},
                {id:'003',name:'温兆伦',age:'19',sex:'男'}
                ],
            },
           
            computed:{
                filPersons(){
                    const arr = this.filPersons = this.persons.filter((p)=>{
                        return p.name.indexOf(this.keyWord)!==-1
                    })
                    if(this.sortType ){
                        arr.sort((p1,p2)=>{
                            return this.sortType === 1 ? p2.age-p1.age :p1.age-p2.age
                        })
                    }
                    return arr
                }
            }
           
        })
        let arr =[1,3,2,6,4,5]
        arr.sort((a,b)=>{
            return b-a
        })
        console.log("@@",arr)
        //升序前减后,降序后减前
        </script>
	</body>
</html>

六.Vue监测数据原理

1.更新时的一个问题

需求:点击时添加一条数据

问题:

操作1:先刷新页面,点击按钮,再打开Vue检测工具。页面没有变,Vue监测工具改变

操作2:先打开Vue监测工具,再刷新页面,点击按钮。页面没有变,Vue监测工具也没有改变

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8"/>
		<title>姓名案例</title>
		<script type="text/javascript" src="../js/vue.js">
		</script>
	</head>
	<body>
        <!-- 容器 -->
        <div id="root">
            <!-- 遍历数组(用的多) -->
           
            <button @click="updateMei">更改冬梅信息</button>
            <ul>
                <li v-for="(p,index) in persons" :key="index">
                    {{p.name}}-{{p.age}}--{{p.sex}}
                </li>
            </ul>
           
        </div>
        
		<script type="text/javascript" >
        Vue.config.productionTip = false
        //用computed实现
        const vm = new Vue({
            el:'#root',
            data:{
                persons:[
                {id:'001',name:'马冬梅',age:'30',sex:'女'},
                {id:'002',name:'周冬雨',age:'31',sex:'女'},
                {id:'003',name:'周杰伦',age:'18',sex:'男'},
                {id:'003',name:'温兆伦',age:'19',sex:'男'}
                ],
            },
            methods:{
                updateMei(){
                    //奏效
                    //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:'男'})
                
                }
            }
        })

        //升序前减后,降序后减前
        </script>
	</body>
</html>

说明:数组没有setter和getter,对数组操作使用Vue包裹后的方法

2.Vue监测数据原理——对象

第一步对data进行加工,第二步vm._data = data。加工完就可以响应式。修改name,就会引起set调用,就重新解析模板,生成新的虚拟DOM,新旧DOM对比,更新页面

模拟一个数据监测,但是只写到了对象的单层

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8"/>
		<title>姓名案例</title>
		<script type="text/javascript" src="../js/vue.js">
		</script>
	</head>
	<body>
        <!-- 容器 -->
        <div id="root">
            <!-- <h2>学校名称:{{name}}</h2>
            <h2>学校地址:{{address}}</h2> -->
        </div>
        
		<script type="text/javascript" >
       let data = {
           name:"尚硅谷",
           address:"北京"
       }
        //创建一个监视的实例对象,用于监视data中的属性变化
        const obs = new Observer(data)
        console.log(obs)
        //准备一个vm实例对象
        let vm ={}
        vm._data = data = obs
        function Observer(obj){
            const keys = Object.keys(obj)
            keys.forEach((k)=>{
                Object.defineProperty(this,k,{
                    get(){
                        return obj[k]
                    },
                    set(val){
                        obj[k]=val
                    }
                })
            })
        }
        </script>
	</body>
</html>

 3.Vue.set方法 

只能给data里面某一个对象追加属性,不能给data追加属性

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8"/>
		<title>姓名案例</title>
		<script type="text/javascript" src="../js/vue.js">
		</script>
	</head>
	<body>
        <!-- 容器 -->
        <div id="root">
            <h2>学校名称:{{name}}</h2>
            <h2>学校地址:{{address}}</h2>
            <hr/>
            <h2></h2>
            <button @click ="addSex">添加一个性别属性,默认男</button>
            <h2>姓名:{{student.name}}</h2>
            <h2 v-if ="student.sex">性别:{{student.sex}}</h2>
        </div>
        
		<script type="text/javascript" >
        Vue.config.productionTip = false
        const vm = new Vue({
            el:"#root",
            data:{
                name:"尚硅谷",
                address:"beijing",
                student:{
                    name:'tom',
                    age:{
                        rage:40,
                        sage:29
                    },
                    friends:[
                    {name:'jerry',age:'35'},
                    {name:'tony',age:36}
                    ]
                }
            },
            methods:{
                addSex(){
                    //Vue.set(this.student,'sex','男')
                    this.$set(this.student,'sex','男')
                }
            }
        })
        </script>
	</body>
</html>

说明:methods中的this指的就是Vm

4.Vue监测数据原理——数组

Vue不能监测根据数组所有值改变数据,因为数组里面每一个元素不是setter和getter实现

需求:修改数据

操作:

1.Vue包裹的数组方法,除了基本数组功能,还会解析模板......

2.set方法

 七.总结Vue数据监测

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

2.如何监测对象中的数据?

通过setter实现监视,且要在new Vue时就传入要监视的数据。

(1)对象中后追加的属性,Vue默认不做响应式处理

(2)如需给后添加的属性做响应式,请使用如下API

Vue.set(target.propertyname/index/value)或

vm.$set(target.propertyname/index/value)

3.如何监测数组中的数据?

通过包裹数组更新元素的方法实现,本质就是做了两件事:

(1)调用原生对应的方法对数组进行更新

(2)重新解析模板,进而更新页面

4.在Vue修改数组中的某个元素一定要用如下方法:

(1)使用这些API:push(),shift(),unshift(),split(),sort(),reverse()

(2)VUe.set()或vm.$set()

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值