Vue基础(下)

83 阅读6分钟

} }, methods: { changeWeather() { this.isHot = !this.isHot } }, // 第一种监视属性的写法 // watch:{ // isHot:{ // // immediate的作用是初始化时就调用handler // immediate:true,
// /* // handler什么时候调用?当isHot发生改变时, // 并且调用时会返回修改前的值以及修改后的值 // */ // handler(newValue, oldValue){ // console.log("ishot被监视了",newValue, oldValue) // } // } // } })

// 第二种监视属性的写法, 通过此方法监视时注意要在监视属性上加上引号
vm.$watch('isHot', {
    immediate: true,
    handler(newValue, oldValue) {
        console.log("ishot被监视了", newValue, oldValue)
    }
})
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 9.2.3 天气案例–深度监视 天气案例

今天天气很{{info}}

切换天气

为a加1 a的值为: {{num.a}}

为b加1 a的值为: {{num.b}}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 9.2.4 监视的简写形式 监视简写的前提时只使用handler一个属性,deep、immediate等均不使用 天气案例_监视属性_简写

今天天气很{{info}}

切换天气
<script type="text/javascript">
	Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
	
	const vm = new Vue({
		el:'#root',
		data:{
			isHot:true,
		},
		computed:{
			info(){
				return this.isHot ? '炎热' : '凉爽'
			}
		},
		methods: {
			changeWeather(){
				this.isHot = !this.isHot
			}
		},
		watch:{
			//正常写法
			/* isHot:{
				// immediate:true, //初始化时让handler调用一下
				// deep:true,//深度监视
				handler(newValue,oldValue){
					console.log('isHot被修改了',newValue,oldValue)
				}
			}, */
			//简写
			/* isHot(newValue,oldValue){
				console.log('isHot被修改了',newValue,oldValue,this)
			} */
		}
	})

	//正常写法
	/* vm.$watch('isHot',{
		immediate:true, //初始化时让handler调用一下
		deep:true,//深度监视
		handler(newValue,oldValue){
			console.log('isHot被修改了',newValue,oldValue)
		}
	}) */

	//简写
	/* vm.$watch('isHot',function(newValue,oldValue){
		console.log('isHot被修改了',newValue,oldValue,this)
	}) */

</script>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 9.3 watch与computed的比较 姓名案例_watch实现
姓:

名:

全名:{{fullName}}

<script type="text/javascript">
	Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

	const vm = new Vue({
		el:'#root',
		data:{
			firstName:'张',
			lastName:'三',
			fullName:'张-三'
		},
		watch:{
			firstName(val){
				setTimeout(()=>{
					console.log(this)
					this.fullName = val + '-' + this.lastName
				},1000);
			},
			lastName(val){
				this.fullName = this.firstName + '-' + val
			}
		}
	})
</script>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 10. class与style绑定 绑定样式 .basic { width: 400px; height: 100px; border: 1px solid black; } .happy { border: 4px solid red;

; background-color: rgba(255, 255, 0, 0.644); background: linear-gradient(30deg, yellow, pink, orange, yellow); }

    .sad {
        border: 4px dashed rgb(2, 197, 2);
        background-color: gray;
    }

    .normal {
        background-color: skyblue;
    }

    .atguigu1 {
        background-color: yellowgreen;
    }

    .atguigu2 {
        font-size: 30px;
        text-shadow: 2px 2px 10px red;
    }

    .atguigu3 {
        border-radius: 20px;
    }
</style>
{{ name }}
    <!-- 绑定class样式 --- 数组写法,适用于:要绑定的样式个数不确定,名字也不确定 -->
    <div class="basic" v-bind:class="classArr">{{ name }}</div>

    <!-- 绑定class样式 --- 对象写法,适用于:要绑定的样式个数确定,名字不确定,但要动态决定用不用 -->
    <div class="basic" :class="classObj">{{ name }}</div>
    <!-- 绑定class样式 --- 对象写法: -->
    <div class="basic" :style="styleObj">{{ name }}</div>

    <!-- 绑定class样式 --- 数组写法: -->
    <div class="basic" :style="styleArr">{{ name }}</div>
</div>

<script>
    Vue.config.productTip = false;

    new Vue({
        el: "#root",
        data: {
            name: "zhangsan",
            mood: "normal",
            classArr: ['atguigu1', 'atguigu2', 'atguigu13'],
            classObj: {
                atguigu1: false,
                atguigu2: true
            },
            styleObj: {
                backgroundColor: "red"
            },
            styleObj2: {
                fontSize: '40px',
                color: 'blue',
            },
            styleArr: [{
                fontSize: '40px',
                color: 'blue',
            }, {
                backgroundColor: "red"
            }]
        },
        methods: {
            changeClass() {
                this.mood = "sad"
            }
        }
    })
</script>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 11. 条件渲染 条件渲染
		2.v-show
			写法:v-show="表达式"
				适用于:切换频率较高的场景。
				特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉
							
		3.备注:使用v-if的时,元素可能无法获取到,而使用v-show一定可以获取到。
	 -->
	<!-- 准备好一个容器-->
	<div id="root">

		<h2>当前的n值是:{{n}}</h2>
		<button @click="n++">点我n+1</button>

		<!-- 使用v-show做条件渲染 -->
		<!-- <h2 v-show="false">欢迎来到{{name}}</h2> -->
		<!-- <h2 v-show="1 === 1">欢迎来到{{name}}</h2> -->

		<!-- 使用v-if做条件渲染 -->
		<!-- <h2 v-if="false">欢迎来到{{name}}</h2> -->
		<!-- <h2 v-if="1 === 1">欢迎来到{{name}}</h2> -->

		<!-- v-else和v-else-if -->
		<!-- 
        <div v-if="n === 1">Angular</div>
		<div v-else-if="n === 2">React</div>
		<div v-else-if="n === 3">Vue</div>
		<div v-else>哈哈</div> 
        -->

		<!-- v-if与template的配合使用,但是template不能和v-show配合使用 -->
		<template v-show="n === 1">
			<h2>你好</h2>
			<h2>张三</h2>
			<h2>北京</h2>
		</template>

	</div>
</body>

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

	const vm = new Vue({
		el:'#root',
		data:{
			name:'张三',
			n:0
		}
	})
</script>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 12. 列表渲染 12.1 列表渲染简介 列表渲染
  • {{s.id}} - {{s.name}} - {{s.age}}


  •     new Vue({
            el: '#root',
            data: {
                persons: [
                    { id: '001', name: '张三', age: 18 },
                    { id: '002', name: '李四', age: 19 },
                    { id: '003', name: '王五', age: 20 }
                ]
            },
            methods: {
                add() {
                    const p = { id: '004', name: '老刘', age: 40 }
                    this.persons.unshift(p)
                }
            },
        })
    </script>
    
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 12.2.1 遍历列表时index作为key 假设初始数据只有三条,分别时张三、李四、王五,然后Vue会根据数据在内存中生成虚拟DOM,虚拟DOM中的节点含有key属性,key属性的值为index,随后会将虚拟DOM转换为真实DOM

    当有新数据添加时,比如逆序添加老刘到数据的最上方,那么Vue将改变后的数据形成虚拟DOM时也会将老刘这条数据放置到节点的最上方,Vue存在虚拟节点对比算法,如果有数据改变时就调用此算法让修改后的虚拟DOM与原虚拟DOM进行比较

    比较过程:由于老刘位于数据的最上方,因此其key的值为0,diff算法会寻找原虚拟DOM中key为0的节点,发现原DOM中的节点内容与新虚拟节点的DOM中的内容不一样,因此将虚拟节点转换成真实节点时会生成新的DOM,不会使用原来的虚拟DOM,但是input标签对比时发现是一样的,因此会复用原来的input节点,所以老刘后面的输入框内部会有张三的内容填充,当对比新虚拟DOM中的张三节点时,其key值为1,因此将两种key=1的节点对比时发现其内容不一样,因此也会再次新生成内容为张三的节点,在对比张三后面的input输入框时发现与原来的虚拟DOM是一样的,因此也会复用原来的输入框…当对比王五这个节点时发现其key的值为3,原虚拟DOM中没有key值为3的节点,因此会新生成王五节点以及后面的输入框

    通过上述分析可知,若使用index作为key的值,原本的虚拟DOM均不会使用,会新生成大量的新节点,造成效率降低

    12.2.2 遍历时使用id作为key 当使用id作为key值时,一旦数据有变化,使用diff算法对比新的虚拟DOM以及原来的虚拟DOM时,会根据key的值大量复用原来的虚拟dom,只会重新生成新增数据的节点,因此效率较高,且不会出现页面错乱的情况。

    12.3 列表过滤

    列表过滤

    人员列表

    • {{p.name}}-{{p.age}}-{{p.sex}}
    <script>
        // 使用watch监视实现
        Vue.config.productionTip = false
        // 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: '男' }
        //         ],
        //         filterPersons: []
        //     },
        //     watch: {
        //         keyword: {
        //             immediate:true,  // 最开始的时候就调用一下handler函数
        //             handler(val) {
        //                 this.filterPersons = this.persons.filter((p) => {
        //                     return p.name.indexOf(val) !== -1
        //                 })
        //             }
    
        //         }
        //     }
        // })
    
        // 使用计算属性实现
        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: {
                filterPersons() {
                    return this.persons.filter((p) => {
                        return p.name.indexOf(this.keyword) !== -1
                    })
                }
            }
        })
    </script>
    
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 12.3 列表排序 列表过滤

    人员列表

    年龄降序 年龄升序 原顺序
        <ul>
            <li v-for="(p,index) in filterPersons" :key="index">
                {{p.name}}-{{p.age}}-{{p.sex}}
            </li>
        </ul>
    </div>
    
    <script>
        
        Vue.config.productionTip = false