第一章--Vue核心02

第一章–Vue核心02

1、列表渲染

1.1、基本列表

v-for

  1. 遍历数组
  2. 遍历对象
  3. 遍历字符串
  4. 遍历指定次数
<!--容器-->
<div id="hello">
    <ul>
<!--        遍历数组-->
        <li v-for="(p,index) in persons" :key="index">{{p.name}}---{{p.age}}---{{index}}</li>
<!--        遍历对象-->
        <li v-for="(value,k) in car" :key="index">{{k}}-{{value}}</li>
    </ul>
</div>
<script type="text/javascript">
    Vue.config.productionTip = false //阻止vue在启动时生成生产提示
    // 实例
    const vue = new Vue({
        el: '#hello', // 指定实例为哪个容器服务
        data(){
            return{
                persons:[
                    {id:'01',name:'张三',age:2},
                    {id:'02',name:'张三',age:2},
                    {id:'03',name:'张三',age:2},
                ],
                car:{
                    name: '奥迪',
                    price: '112'
                }
            }
        }
    });
    // vue.$mount('#hello')

</script>

1.2、key的原理

key给节点作为标识

初始数据—》初始虚拟DOM—》将虚拟DOM转为真实DOM

虚拟DOM对比算法
请添加图片描述

请添加图片描述

<!--容器-->
<div id="hello">
    <ul>
<!--        遍历数组-->
        <button @click.once="add">添加一个人</button>
        <li v-for="(p,index) in persons" :key="index">{{p.name}}---{{p.age}}---{{index}}<input type="text"></li>
        <li v-for="(p,index) in persons" :key="p.id">{{p.name}}---{{p.age}}---{{index}}<input type="text"></li>
    </ul>
</div>
<script type="text/javascript">
    Vue.config.productionTip = false //阻止vue在启动时生成生产提示
    // 实例
    const vue = new Vue({
        el: '#hello', // 指定实例为哪个容器服务
        data(){
            return{
                persons:[
                    {id:'01',name:'张三',age:2},
                    {id:'02',name:'张三',age:2},
                    {id:'03',name:'张三',age:2},
                ],
                car:{
                    name: '奥迪',
                    price: '112'
                }
            }
        },
        methods:{
            add(){
                const p = {id:'04',name:'王五',age:2}
                // The unshift() method adds one or more elements to the beginning of an array and returns the new length of the array.
                this.persons.unshift(p)
            }
        }
    });
    // vue.$mount('#hello')

</script>
  1. key的作用:key是虚拟DOM对象的表示,数据发生变化时,Vue根据新数据生成新的虚拟DOM,然后会有新虚拟DOM和旧虚拟DOM的差异比较
  2. 比较规则:
    1. 旧虚拟DOM中找到了与新虚拟DOM相同的key
      1. DOM内容没变,直接使用之前的
      2. DOM内容变化,生成新的真实DOM,替换之前的
    2. 没有新的key
      1. 创建真实DOM,渲染到页面
  3. index作为key的问题
    1. 对数据进行:逆序添加和删除会破坏顺序操作。产生没必要的真实DOM更新(界面效率低)
    2. 结构中包含真实的输入类DOM:产生错误DOM更新,界面出错
  4. 开发中最好使用数据的唯一标识作为key

1.3、列表过滤

  1. watch实现
  2. computed实现,更简单方便
<!--容器-->
<div id="hello">
    <input type="text" placeholder="输入名字" v-model="keyword">
    <ul>
<!--        遍历数组-->
        <button @click.once="add">添加一个人</button>
        <li v-for="(p,index) in filpersons" :key="index">{{p.name}}---{{p.age}}---{{index}}<input type="text"></li>
<!--        <li v-for="(p,index) in filpersons" :key="p.id">{{p.name}}-&#45;&#45;{{p.age}}-&#45;&#45;{{index}}<input type="text"></li>-->
    </ul>
</div>
<script type="text/javascript">
    Vue.config.productionTip = false //阻止vue在启动时生成生产提示
    // 实例
    const vue = new Vue({
        el: '#hello', // 指定实例为哪个容器服务
        data(){
            return{
                keyword:'',
                persons:[
                    {id:'01',name:'张三',age:2},
                    {id:'02',name:'李四',age:2},
                    {id:'03',name:'王五',age:2},
                ],
                // filpersons: [],
                car:{
                    name: '奥迪',
                    price: '112'
                }
            }
        },
        methods:{
            add(){
                const p = {id:'04',name:'赵六',age:2}
                // The unshift() method adds one or more elements to the beginning of an array and returns the new length of the array.
                this.persons.unshift(p)
            }
        },
        // watch实现
        /*watch:{
            keyword:{
                immediate: true,
                handler(val){
                    this.filpersons = this.persons.filter((p)=>{
                        return p.name.indexOf(val) !== -1;
                    })
                }
            }
        }*/
        // computed实现
        computed:{
            filpersons(){
                return this.persons.filter((p)=>{
                    return p.name.indexOf(this.keyword) !== -1;
                })
            }
        }

    });
    // vue.$mount('#hello')

</script>

1.4、列表排序

使用一个字段标识:顺序 降序 升序

拿到过滤后的数组进行排序

<!--容器-->
<div id="hello">
    <input type="text" placeholder="输入名字" v-model="keyword">
    <button @click="sortType=0">原顺序</button>
    <button @click="sortType=1">降序</button>
    <button @click="sortType=2">升序</button>
    <ul>
<!--        遍历数组-->
        <button @click.once="add">添加一个人</button>
        <li v-for="(p,index) in filpersons" :key="index">{{p.name}}---{{p.age}}---{{index}}<input type="text"></li>
<!--        <li v-for="(p,index) in filpersons" :key="p.id">{{p.name}}-&#45;&#45;{{p.age}}-&#45;&#45;{{index}}<input type="text"></li>-->
    </ul>
</div>
<script type="text/javascript">
    Vue.config.productionTip = false //阻止vue在启动时生成生产提示
    // 实例
    const vue = new Vue({
        el: '#hello', // 指定实例为哪个容器服务
        data(){
            return{
                keyword:'',
                sortType: 0, // 0原顺序 1降序 2升序
                persons:[
                    {id:'01',name:'张三',age:2},
                    {id:'02',name:'李四',age:4},
                    {id:'03',name:'王五',age:1},
                ],
                // filpersons: [],
                car:{
                    name: '奥迪',
                    price: '112'
                }
            }
        },
        methods:{
            add(){
                const p = {id:'04',name:'赵六',age:2}
                // The unshift() method adds one or more elements to the beginning of an array and returns the new length of the array.
                this.persons.unshift(p)
            }
        },
        // watch实现
        /*watch:{
            keyword:{
                immediate: true,
                handler(val){
                    this.filpersons = this.persons.filter((p)=>{
                        return p.name.indexOf(val) !== -1;
                    })
                }
            }
        }*/
        // computed实现
        computed:{
            filpersons(){
                const arr = this.persons.filter((p)=>{
                    return p.name.indexOf(this.keyword) !== -1;
                })
                if(this.sortType){
                    // 降序
                    arr.sort((a,b)=>{
                        return this.sortType === 1?b.age-a.age:a.age-b.age;
                    })
                }
                return arr;
            }
        }

    });
    // vue.$mount('#hello')

</script>

1.5、Vue检测数据的原理

数据代理:

  1. 加工data
  2. vm._data=data

加一层,观察者对象

let person = {
    name: '张三',
    address: 'llli'
}
let obj = new Observer(person);
console.log(obj)
let vm = {}
vm._data = person = obj
function Observer(obj){
    const keys = Object.keys(obj)
    keys.forEach((k)=>{
        Object.defineProperty(this,k,{
            get(){
                return obj[k];
            },
            set(val){
                console.log('被修改了')
                obj[k] = val;
            }
        })
    })
}

Vue.set()

vm.$set()

vm._data.student = vm.student

<!--容器-->
<div id="hello">
    <h1>学生信息</h1>
    <h3>姓名:{{student.name}}</h3>
    <h3>年龄:{{student.age}}</h3>
<!--    <h3 v-show=this.show>性别:{{student.sex}}</h3>-->
    <h3 v-if="student.sex">性别:{{student.sex}}</h3>
    <h3>爱好:</h3>
    <ul>
        <li v-for="(h,index) in student.hobby">{{h}}</li>
    </ul>
    <h3>朋友:</h3>
    <ul>
        <li v-for="(f,index) in student.friend">{{f.name}}--{{f.age}}</li>
    </ul>

    <button @click="addSex">添加性别属性</button>
    <button @click="addFriend">添加朋友</button>
    <button @click="updateFirstFriendName">更新第一个朋友姓名</button>
</div>
<script type="text/javascript">
    Vue.config.productionTip = false //阻止vue在启动时生成生产提示
    new Vue({
        el: '#hello',
        data:{
            show:false,
            student:{
                name: '张三',
                age: 12,
                hobby: ['吃饭','睡觉','打豆豆'],
                friend: [
                    {name:'李四',age:12},
                    {name:'王麻子',age:23}
                ]
            }
        },
        methods:{
            addSex(){
                // Vue.set(this.student,'sex','男')
                this.$set(this.student,'sex','男')
                this.show = !this.show
            },
            addFriend(){
                this.student.friend.unshift({name:'往无',age:12})
            },
            updateFirstFriendName(){
                this.student.friend[0].name='找一'
            }

        }
    })

</script>
  1. vue会监视data中所有层次的数据
  2. 如何监视?通过setter实现,在new Vue是就传入要监测的数据
    1. 对象中后追加的属性,默认不做响应式处理
    2. 有两种方法添加属性
  3. 检测数组中的数据
    1. 调用原生对应的方法对数组进行更新
    2. 重新解析模板,更新页面
  4. vue修改数组中的元素
    1. 使用API:push pop等
    2. Vue.set()或vm.$set()

Vue.set()和vm.$set()不能给vm或vm的根数据对象添加属性

数据劫持

2、收集表单数据

<div id="root">
  <form>
    账号:<input type="text" v-model="userInfo.account"> <br/>
    密码:<input type="password" v-model="userInfo.password"> <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/>
    年龄:<input type="number" v-model.number="userInfo.age"> <br/>
  </form>
</div>
<script type="text/javascript">
  Vue.config.productionTip = false //阻止vue在启动时生成生产提示
  new Vue({
    el: '#root',
    data:{
      userInfo:{
        account:'',
        password:'',
        age:12,
        sex:'female'
      }

    }
  })
</script>
  1. input为text,v-model收集的是value值,用户输入的是value值
  2. input为radio v-model收集的是value值,且要给标签配置value值
  3. checkbox
    1. 没有配置input的value属性,收集的是checked 是布尔值
    2. v-model初始值是数组,收集value组成的数组
    3. v-model初始值是非数组,收集的是checked
  4. v-model的三个修饰符
    1. lazy 失去焦点后收集数据
    2. number 输入字符串转为有效数字
    3. trim 首尾空格过滤

3、过滤器

时间戳

BootCDN:第三方库网站

<p>{{str|splice}}</p>
filters:{
      splice(value){
        return value.slice(0,1)
      }
}

定义:对要显示的数据进行特定格式化后

语法:

  1. 注册过滤器:Vue.filter(name,callback)或new Vue{filters:{}}
  2. 使用过滤器:{{xxx|过滤器名}}或v-bind:属性=“xxx|过滤器名”

备注:

  1. 过滤器可以接收额外的参数,多个过滤器可以串联
  2. 并没有改变原本的数据,是产生新的对应的数据

4、内置指令

v-on v-bind

4.1、v-text

4.2、v-html

<!--容器-->
<div id="hello">
    <div v-html="str"></div>
</div>
<script type="text/javascript">
    Vue.config.productionTip = false //阻止vue在启动时生成生产提示
    // 实例
    const vue = new Vue({
        el: '#hello', // 指定实例为哪个容器服务
        data:{
            str: '<h1>你好</h1>'
        }
    });
    // vue.$mount('#hello')

</script>
  1. 向指定节点中渲染包含html结构的内容
  2. 与插值语法的区别
    1. v-html会替换节点中所有内容
    2. 可以识别html结构
  3. v-html有安全性问题
    1. 在网站上动态渲染节点容易导致XSS攻击
    2. 要在可信的内容上使用v-html,永远不要在用户提交的内容

4.3、v-cloak指令

阻塞

没有纸

  1. 本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删除v-cloak属性
  2. 使用css配合v-cloak可以解决网速较慢是页面显示出{{xxx}}的问题

4.4、v-once

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

4.5、v-pre指令

  1. 跳过节点的编译过程
  2. 可利用它跳过;没有使用指令语法,没有使用插值语法的节点,会加快编译

}
});
// vue.$mount(’#hello’)

```
  1. 向指定节点中渲染包含html结构的内容
  2. 与插值语法的区别
    1. v-html会替换节点中所有内容
    2. 可以识别html结构
  3. v-html有安全性问题
    1. 在网站上动态渲染节点容易导致XSS攻击
    2. 要在可信的内容上使用v-html,永远不要在用户提交的内容

4.3、v-cloak指令

阻塞

没有纸

  1. 本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删除v-cloak属性
  2. 使用css配合v-cloak可以解决网速较慢是页面显示出{{xxx}}的问题

4.4、v-once

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

4.5、v-pre指令

  1. 跳过节点的编译过程
  2. 可利用它跳过;没有使用指令语法,没有使用插值语法的节点,会加快编译

5、自定义指令

v-big

<!--容器-->
<div id="hello">
    <p>当前n的值是:{{n}}</p>
    <p>放大10倍后的值是:<span v-big="n"></span></p>
    <button @click="n++">点我n+1</button>
</div>
<script type="text/javascript">
    Vue.config.productionTip = false //阻止vue在启动时生成生产提示
    // 实例
    const vue = new Vue({
        el: '#hello', // 指定实例为哪个容器服务
        data:{
            n: 10,
        },
        directives:{
            big(element,binding){
                element.innerText = binding.value * 10
            }
        }

    });
    // vue.$mount('#hello')

</script>

big调用时机:1.指定与元素绑定时 2.指令所在模板被重新解析时

  1. 定义语法:

    1. 局部指令:new Vue({directives:{指令名:配置对象}}) new Vue({directives:{指令名:回调函数}})
    2. 全局指令:Vue.directive(指令名,配置对象)或Vue.directive(指令名,回调函数)
  2. 配置对象中常用的3个回调:

    1. .bind:指令与元素成功绑定时调用
    2. .inserted:指令所在元素被插入页面时调用
    3. .update:指令所在模板结构被重新解析时调用

6、生命周期

6.1、引出

  1. 名称:生命周期回调函数,生命周期函数,生命周期钩子
  2. Vue在关键时刻帮我们调用的一些特殊名称的函数
  3. 生命周期函数的名字不可更改,但是函数的具体内容是根据需求编写的
  4. 生命周期函数中的this指向是vm或者组件实例对象

6.2、挂载流程

  1. new Vue() 创建实例

  2. Init Events &LifeCycle 初始化:生命周期、时间,但数据代理还未开始

  3. beforeCreate 无法通过vm访问到data中的数据

  4. Init injections & reactivity 初始化:数据监测、数据代理

  5. Created 可以通过vm访问到data中的数据、methods中配置的方法

  6. 此阶段Vue开始解析模板,生成虚拟DOM(内存中),页面还不能显示解析好的内容

    1. Has el
    2. Has template option
  7. beforeMount 页面呈现的是未经Vue编译的DOM结构,所有对DOM的操作,最终都不奏效

  8. create vm.$el 将内存中的虚拟DOM转为真实DOM插入页面

  9. mounted

    1. 页面中呈现的是经过Vue编译的DOM
    2. 对DOM的操作均有效。至此初始化过程结束,一般在此进行:开启定时器、发送网络请求、订阅消息、绑定自定义时间、等初始化操作
  10. beforeUpdate 此时**数据是新的,但页面是旧的,**页面尚未和数据保持同步

  11. Virtual DOM re-render and patch 根据新数据,生成新的虚拟DOM,随后和旧的虚拟DOM进行比较,最终完成页面更新

  12. updated 数据是新的,页面也是新的,数据和页面同步

  13. 当vm.$destroy被调用时,完全销毁一个实例,清理它与其他实例的连接,解绑它的全部指令及自定义事件监听器(原生自定义事件依旧存在)

  14. beforeDestory vm中所有的data methods、指令等等,都处于可用状态,马上要执行销毁过程,一般在此阶段:关闭定时器、取消订阅消息、解绑自定义时间等收尾操作

  15. teardown watchers

  16. destroyed

<!--容器-->
<div id="hello">
    <p>当前n的值是:{{n}}</p>
    <button @click="add">点我n+1</button>
    <button @click="destroyEvent">点我销毁事件</button>
</div>
<script type="text/javascript">
    Vue.config.productionTip = false //阻止vue在启动时生成生产提示
    // 实例
    const vm = new Vue({
        el: '#hello', // 指定实例为哪个容器服务
        data:{
            n: 10,
        },
        methods:{
            add(){
                this.n++
            },
            destroyEvent(){
                console.log('destroyEvent...')
                this.$destroy();
            }
        },
        watch:{

        },
        beforeCreate(){
            console.log('beforeCreate')
            console.log(this)
            // debugger;
        },
        created(){
            // 数据检测 数据代理
            console.log(this)
            console.log('created')
        },
        beforeMount(){
            console.log('beforeMount')
            // 修改DOM 会发现不起作用,此时是虚拟DOM
            // debugger;
        },
        mounted(){
            // 注释掉el 修改template
            console.log('mounted')
        },
        beforeUpdate(){
            console.log('beforeUpdate')
            // 数据和页面还未更新
            // debugger;
        },
        updated(){
            console.log('updated')
        },
        beforeDestroy(){
            console.log("beforeDestroy")
            console.log(this.n)
        },
        destroyed(){
            console.log("destroyed")
        }


    })
    // vue.$mount('#hello')

</script>
  1. 将要创建
  2. 创建完毕
  3. 将要挂载
  4. 挂载完毕
  5. 将要更新
  6. 更新完毕
  7. 将要销毁
  8. 销毁完毕

常用:

  1. mounted 发送ajax其你去、启动定时器、绑定自定义时间、订阅消息等【初始化操作】
  2. beforeDestroy:清除定时器、解绑自定义时间、取消订阅消息等【收尾操作】

销毁Vue实例:

  1. 销毁后借助Vue开发者工具看不到任何信息
  2. 销毁后自定义时间会失效,但原生DOM事件依然有效
  3. 一般不会在beforeDestory操作数据,因为即时操作数据,也不会再触发更新流程
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很好,学习Vue3的第十四章节,应该是比较深入的内容了。这一章主要涉及了Vue3中的组合式API。 在Vue3中,组合式API是一种新的API风格,它允许我们以函数的方式编写Vue组件,并且提供更加灵活和强大的功能特性。相较于Vue2中的选项API,组合式API更加适合大型、复杂的应用场景。 在学习组合式API时,我们需要掌握以下几个核心概念: 1. `setup()`函数:`setup()`函数是组合式API的入口,它在组件实例创建之前执行,用于设置组件的响应式数据、方法等。 2. `ref()`函数与响应式数据:`ref()`函数用于创建响应式数据,它返回一个对象,包含一个`value`属性,该属性可以被修改,并且修改后会触发组件的重新渲染。 3. `reactive()`函数与响应式对象:`reactive()`函数用于创建响应式对象,它将一个普通对象转换为响应式对象,当对象的属性发生变化时,会触发组件的重新渲染。 4. `computed()`函数与计算属性:`computed()`函数用于创建计算属性,它接收一个函数作为参数,并返回一个响应式对象,当计算属性所依赖的数据发生变化时,会触发计算属性的重新计算。 5. `watch()`函数与监听器:`watch()`函数用于创建监听器,它可以监听响应式数据、计算属性等的变化,并执行相应的回调函数。 以上就是组合式API的核心概念,如果你想深入学习Vue3的组合式API,可以结合官方文档进行学习。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值