Vue2笔记

Vue React Angular 前端三大框架
    组件(是对UI结构的复用)

一.Vue概述
    1.什么是Vue
        是一套用于构建用户界面的前端框架
        (1)构建用户界面
            用vue 往html 页面中填充数据
        (2)框架
            框架是一套现成的解决方案
            程序员只能遵守框架的规范去编写自己的业务功能
    2.Vue 的特性
        (1)数据驱动视图
        (2)双向数据绑定
        数据就是指:ajax 从服务器请求回来的数据
        1.数据驱动视图
            vue 会监听数据的变化,从而自动重新渲染页面结构
            -------------------------------------------------------
            页面解构 <---(自动渲染) Vue监听数据的变化 <--- 页面所依赖的数据
            -------------------------------------------------------
            好处:
                当页面数据发生变化时,页面会自动重新渲染
            注意:
                数据驱动视图是单向的数据绑定
        2.双向数据绑定
            在填写表单时,双向数据绑定可以在不操作DOM 的前提下,自动把用户填写的内容同步到数据源中
            from 表单负责采集数据,Ajax 负责提交数据

            js 数据的变化,会被自动渲染到页面上
            页面上表单采集的数据发生变化的时候,会被vue 自动获取到,并更新到js 数据中
            ------------------------------------------------------
                     <- 自动渲染            <- 变化
            页面解构  -----------   Vue   ----------- 页面所依赖的数据
                     值发生变化 ->          自动同步 ->
            ------------------------------------------------------
            好处:
                开发者不再需要手动操作DOM 元素,来获取表单元素最新的值
        3.MVVM
            MVVM 是vue 实现数据驱动视图和双向数据绑定的核心原理
            把每个HTML 页面都拆分成了这三个部分
            MVVM 指的是Model、View、和ViewModel
                Model:表示当前页面渲染时所依赖的数据源(如:用Ajax 拿到的数据)
                    具体指:data(){}
                View:表示当前页面所渲染的DOM 结构
                    具体指:el:'#app'
                ViewModel:表示vue 的实例,它是MVVM 的核心
                    具体指:const vm = new Vue(new 出来的vue 实例对象)
                    
            
            ViewModel:
                ViewModel 是MVVM 的核心
                是它把当前页面的数据源(Model)和页面解构(View)连接在了一起
                    -------------------------------------------------
                            <- 自动更新              <- 监听数据源变化
                    View --------------- ViewModel ---------------- Model
                        监听DOM 变化 ->               自动同步 ->
                    -------------------------------------------------
                当数据源发生变化时,会被ViewModel 监听到,VM会根据最新的数据源自动更新页面的结构
                当表单元素的值发生变化时,也会被VM 监听到,VM会把变化过后最新的值自动同步到Model 数据源中

二.Vue 的基本使用
    示例:
        <body>
            <!-- 希望vue 可以控制下面这个div,把数据填充到div 中 -->
            <div id="app">{{ username }}</div>

            <!-- 1. 导入vue 的库文件 -->
            <script src="../js/vue.js"></script>

            <!-- 在window 全局就有了Vue 这个构造函数 -->

            <!-- 2. 创建vue 的实例对象 -->
            <script>
                // 创建vue 的实例对象
                const vm = new Vue({
                    // el 属性是固定的写法,表示当前vm 实例要控制页面上的哪个区域 接收的值是一个选择器
                    el: '#app',
                    // data 对象就是要渲染到页面上的数据
                    data: {
                        username: 'zhangsan'
                    }
                })
            </script>
        </body>

三.Vue 的调试工具
    1.安装vue-devtools 调试工具
        Chrome 浏览器在线安装vue-devtools:
            http://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd
        FireFox 浏览器在线安装vue-devtools:
            http://addons.mozilla.org/zh-CN/firefox/addon/vue-js-devtools/

四.Vue 指令
    指令是vue 提供的模板语法,用于辅助开发者渲染页面的基本结构
    按照不同的用途分为6类:
        (1)内容渲染指令
        (2)属性绑定指令
        (3)事件绑定指令
        (4)双向绑定指令
        (5)条件渲染指令
        (6)列表渲染指令
    
    在vue 提供的模板渲染语法中,除了支持绑定简单的数据之外,还支持Javascript 表达式的运算
        示例:
            {{number + 1}}
            {{ok? 'Yes':'No'}}
            {{message.split('').reverse().join('')}}
            <div v-bind:id="'list-' + id"></div>

    1.内容渲染指令
        用来渲染DOM 元素的文本内容
        (1)v-text
            示例:
                <div v-text="username">姓名</div>     // 输出结果: zhangsan   // 没有姓名俩字
                // 把username 的值渲染到p 标签内部
                data: {
                    username: 'zhangsan',
                }
            缺点:会覆盖元素内部原有的内容
        (2){{}}
            又叫插值表达式,专门用来解决v-text 覆盖默认文本内容的问题
            是内容的占位符,不会覆盖原有的内容
            示例:
                <div>姓名:{{username}}</div>
                data: {
                    username: 'zhangsan',
                }
            注意:
                插值表达式只能用在元素的内容节点中,不能用在元素的属性节点中
        (3)v-html
            由于v-text 和插值表达式只能渲染纯文本内容
            v-html 可以渲染带有HTML 标签的字符串为真正的HTML 内容
            示例:
                <div v-html="info"></div>
                data: {
                    info: '<h4 style="color: red;font-weight: bold">嗯嗯嗯</h4>'
                }
    2.属性绑定指令
        v-bind:     
            为元素的属性动态绑定属性值
            简写为:  :
        示例:
            <input type="text" v-bind:placeholder="tips">
            data: {
                tips: '请输入用户名'
            }   
        注意:
            在使用v-bind 属性绑定期间,如果绑定内容需要进行动态拼接,则字符串的外面应该包裹单引号
                示例:
                    <div v-bind:id="'list-' + id"></div>
                    data{
                        id: 3
                    }
    3.事件绑定指令
        1.  v-on:
                为DOM元素绑定事件监听
                简写为: @
            语法:
                v-on:事件名称="事件处理函数名称"
            示例:
                <button @click="add(2)">+2</button>
                // data 对象就是要渲染到页面上的数据
                data: {
                    count: 0
                },
                // methods 的作用,就是定义事件的处理函数
                methods: {
                    // add: function(){
                    //     console.log('ok');
                    // }
                    // 简写为:
                    add(n){
                        console.log('ok');
                        this.count += n;
                    }
                }
            // 如果在方法中要修改data 中的数据,可以通过this 访问到

        2.  事件对象 $event
            vue 提供了内置变量 $event, 它就是原生DOM 的事件对象e
            示例:
                1.无参数时
                    add()        // 默认e 指向$event,不需要手动声明
                2.有参数时
                    add(1,$event)  -> add(n,e){}   // $event 用e 接收
            
                    
            e.target  指向当前对象
        3. 事件修饰符
            如:
                原生DOM中:event.preventDefault() (阻止事件默认行为)和 event.stopPropagation() (阻止事件冒泡)
            五个事件修饰符:
                ----------------------------------------------------
                .prevent            阻止默认行为(例如:阻止a链接的跳转、阻止表单的提交等)
                .stop               阻止事件冒泡
                .capture            以捕获模式触发当前的事件处理函数
                .once               绑定的事件只触发一次
                .self               只有在event.target 是当前元素自身时触发事件处理函数
            示例:
                .prevent:
                    <a href="http://www.baidu.com" @click.prevent="show">跳转到百度</a>
                .stop:
                    <button @click.stop="btnHandler">按钮</button>
        4.按键修饰符
            1.只有在'key' 是 'Esc' 时调用'vm.clearInput()'
            <input type="text" @keyup.esc="clearInput">
            2.只有在'key' 是 'Enter' 时调用'vm.commitAjax()'
            <input type="text" @keyup.enter="commitAjax">
    4.双向绑定指令
        1.v-model
            双向数据绑定指令,用来在不操作DOM 的前提下,获取表单的数据
            示例:
                双向数据绑定:v-model
                    <input type="text" v-model="username">
                    // data -> view & view -> data
                数据驱动视图:v-bind:
                    <input type="text" :value="username">
                    // data -> view
            注意:
                v-model 指令只能修饰表单控件
                如:
                    1.input
                        type="radio"
                        type="checkbox"    
                        ...
                    2.textarea
                    3.select
        2.v-model 指令的修饰符
            .number     自动将用户的输入值转换为数值类型    <input v-model.number="age">
            .trim       自动过滤用户输入的首尾空白字符      <input v-model.trim="msg">
            .lazy       在"change"时而非"input"时更新     <input v-model.lazy="msg"
            示例:
                <input type="text" v-model.number="n1">
    5.条件渲染指令
        条件渲染指令用来按需控制DOM 的显示与隐藏
        1.v-if  
            原理:
                每次动态创建或移除元素,实现元素的显示和隐藏
            v-else:
                v-else 指令必须配合v-if 指令一起使用,否则不被识别
            v-else-if:
                v-else-if 指令必须配合v-if 指令一起使用,否则不被识别

        2.v-show   
            原理:
                动态为元素添加或移除 display:none; 样式,来实现元素的显示和隐藏
        注意:
            如果要频繁切换元素的显示状态,用v-show 性能会更好
            如果刚进入页面的时候,某些元素默认不需要被展示,而且后期这个元素很可能也不需要被展示出来,此时用v-if 性能更好
            在实际开发中,绝大多数情况下,不用考虑性能问题,直接使用v-if 就好了
    6.列表渲染指令
        v-for 用来基于一个数组来循环渲染一个列表结构
            语法格式: item in items
                items 是待循环的数组
                item 是被循环的每一项
        v-for 指令还支持一个可选的第二个参数,即当前项的索引
            语法格式:  (item,index) in items
        规定:
            只要用到了v-for 指令,那么一定要绑定一个:key 属性,且尽量把id 作为key 的值
            1.key 的值只能是 字符串 或 数字 类型
            2.key 的值不能重复
            3.建议把数据项id 属性的值作为key 的值(因为id 属性的值具有唯一性)
            4.使用index 的值当做key 的值没有任何意义(因为index 的值不具有唯一性)
            5.建议使用v-for 指令时一定要指定key 的值(既提升性能,又放置列表状态紊乱)
        
        示例:
            <tr v-for="(item,index) in list" :key="item.id" :title="item.name + index">
        品牌列表案例:
            1.  // 点击链接删除对应的商品
                remove(id){
                    this.list = this.list.filter(item => item.id !== id)
                }
        
五.过滤器
    Vue 3 中已删除过滤器的使用
    1.过滤器的基本使用
        过滤器(Filters)常用于文本的格式化
        过滤器用在两个地方:插值表达式 和 v-bind 属性绑定
        过滤器本质上是个函数
        过滤器应该被添加在JavaScript 表达式的底部,由管道符进行调用
        管道符: |      管道符作用:表示要调用过滤器函数
        过滤器的作用: 将 | 前面的值 传给 | 后面的过滤器函数,并返回过滤后的值
        示例:
            1.在双花括号中通过“管道符” 调用capitalize 过滤器,对message 的值进行格式化
                <p>{{ message | capitalize}}</p>
            2.在 v-bind 中通过“管道符” 调用formatId 过滤器,对rawId 的值进行格式化
                <div v-bind:id="rawId | formatId"></div>
        注意:  
            1.过滤器要定义到filters 节点下,本质是一个函数
            2.在过滤器函数中,一定要有return 值
            3.在过滤器的形参中,就可以获取到管道符前面待处理的那个值
    2.使用Vue.filter 定义全局过滤器
        1.私有过滤器
            定义到Vue 实例中的filters 节点下的过滤器都是私有过滤器
        2.全局过滤器
            语法:
                Vue.filter('capitailize',(str) => {
                    return str.charAt(0).toUpperCase() + str.slice(1) + '~~'
                })
            参数:
                第一个参数:是全局过滤器的'名字'
                第二个参数:是全局过滤器的'处理函数'
                形参 str 接收 | 前的实参
            注意:
                如果全局过滤器和私有过滤器名字一致,按照就近原则,调用私有过滤器
    3.连续调用多个过滤器
        {{ message | filterA | filterB}}
    4.为过滤器传递参数
        {{ message | filterA(arg1,arg2)}}
        Vur.filter('filterA',(msg,arg1,arg2) => {})
        注意:
            第一个参数永远是“管道符”前面待处理的值
            第二个参数开始,才是调用过滤器时传递过来的arg1 和 arg2 参数

六.侦听器
    watch 侦听器:监视数据的变化,从而针对数据的变化做特定的操作
    语法:
        data: { username: '' },
        watch: {
            // 监听username 的值的变化
            // newVal 是“变化之后的新值”,oldVal 是“变化之前的旧值”
            username(newVal,oldVal){
                console.log(newVal,oldVal)
            }
        }
    侦听器的格式:
        1.方法格式的侦听器:
            缺点:
                1.无法在刚进入页面的时候,自动触发
                2.如果侦听的是一个对象,当对象中的属性发生了变化,不会触发侦听器
        2.对象格式的侦听器:
            好处:
                1.可以通过 immediate 选项,在刚进页面的时候,让侦听器自动触发一次
                2.可以通过 deep 选项,让侦听器深度监听对象中每个属性的变化

七.计算属性
    计算属性指的是通过一系列运算之后,最终得到的一个属性值
    这个动态计算出来的属性值可以被模板结构或methods 方法使用
    所有的计算属性都要定义到computed 节点之下
    特点:
        1.计算属性在定义的时候,要定义成“方法格式”
        2.在使用计算属性的时候,当普通的属性使用即可
    好处:
        1.实现了代码复用
        2.只要计算属性中依赖的数据源变化了,则计算属性会自动重新求值

八.vue-cli
    vue-cli 是Vue.js 开发的标准工具,简化了webpack 创建工程化的Vue 项目的过程
    中文官网:https://cli.vuejs.org/zh/
    
    安装:
        npm install -g @vue/cli
    使用:
        1.vue create 项目的名称
        2.Manually select features (手动选择要安装的功能)
        3.CSS Pre-processors  (css 预处理器 less)  不装Linter
        4. 2.x
        5.Less
        6.In dedicated config files  (把Babel、Eslint 等插件的配置项,放到自己独立的配置文件中)
        7.n (不存已选项)
    
    vue 项目中src 目录的构成:
        1.assets 文件夹:存放项目中用到的静态资源文件
            例如:css 样式表、图片资源
        2.components 文件夹:程序员封装的、可复用的组件,都要放到components 目录下
        3.main.js :是项目的入口文件,整个项目的运行,要先执行main.js
        4.App.vue :是项目的根组件
    vue 项目的运行流程:
        通过main.js 把App.js 渲染到index.html 的指定区域中
        其中:
            1.App.vue 用来编写待渲染的模板结构
            2.index.html 中需要预留一个el 区域
            3.main.js 把App.vue 渲染到了index.html 所预留的区域中

九.vue 组件
    1.什么是组件化开发
        组件化开发:根据封装的思想,把页面上可重用的UI解构封装为组件,从而方便项目的开发和维护
        (是对UI结构的封装和复用)
    2.vue 中的组件化开发
        组件的后缀名 .vue
    3.vue 组件的三个组成部分
        1. template -> 组件的模板结构
        2. script -> 组件的JavaScript 行为
        3. style -> 组件的样式
    4.组件之间的父子关系
        如:在App.vue 中使用Left.vue 组件
            步骤1.使用import 语法导入需要的组件( @表示src 文件夹 )
                import Left from '@/components/Left.vue'
            步骤2.使用components 节点注册组件
                export default {
                    components: {
                        Left
                    }
                }
            步骤3.以标签形式使用刚才注册的组件
                <div class="box">
                    <left></left>
                </div>
        注意:
            通过components 注册的是私有子组件   
    5.注册全局组件:
        在vue 项目的main.js 入口文件中,通过vue.components() 方法,可以注册全局组件
        示例:
            // 导入需要全局注册的组件
            import Count from '@/components/Count.vue'
            // 参数1:字符串格式,表示是组件的“注册名称”
            // 参数2:需要被全局注册的那个组件
            Vue.component('MyCount',Count)
    6.组件的props
        提高组件的复用性
        1.props 组件的自定义属性
            props 是组件的自定义属性,在封装通用组件时,使用props 可以提高组件的复用性
            注意:
                props 的自定义属性值是只读的,不能直接修改props 的值
            示例:
                props:['自定义属性名'],
                <MyCount :init="9"></MyCount>
                <!-- init="6" 字符串的6 -->
                <!-- :init="6" 数值型的6 -->
        2.props 中的default 默认值
            // 如果外界使用Count 组件的时候,没有传递init 属性,则默认值生效
            export default{
                props: {
                    init: {
                        // 用default 属性定义属性的默认值
                        default: 0
                    }
                }
            }
        3.props 的type值类型
            在声明自定义属性时,可以通过type 来定义属性的值类型:
            示例:
                export default{
                    props: {
                        init:{
                            // 用default 属性定义属性的默认值
                            default: 0,
                            // 用type 属性定义属性的值类型
                            // 如果传递过来的值不符合此类型,则会在终端报错
                            type: Number
                            // Boolean、Array、String、Object
                        }
                    }
                }
        4.props 的required 必填项校验
            props: {
                init: {
                    // 用default 属性定义属性的默认值
                    default: 0,
                    // init 的值类型必须是Number 数字
                    type: Number,
                    // 必填项校验
                    required: true
                }
            },
    7.组件之间的样式冲突问题
        默认情况下,写在.vue 组件中的样式会全局生效,容易造成组件之间的样式冲突问题
        原因:
            1.单页面应用程序中,所有组件的DOM 结构,都是基于唯一的index.html 页面呈现的
            2.每个组件中的样式,都会影响index.html 页面中的DOM 元素
        如何解决样式冲突问题:
            <style lang="less" scoped></style>
            scoped 属性可以为当前组件添加特有属性,来区分不同的组件
            
        在父组件中修改子组件中的样式:
            /deep/ h5{ color:red }
            // 当使用第三方组件库的时候,如果有修改第三方组件默认样式的需求,需要用到/deep/

十.组件的生命周期
    生命周期:是指一个组件从创建 -> 运行 -> 销毁的整个阶段,强调的是一个时间段
    生命周期函数:是由vue 框架提供的内置函数,会伴随着组件的声明周期,自动按次序执行
        
    vue 实例的生命周期 (vue 组件的生命周期)
    (1)组件创建阶段:
        执行次数:只有1次

        new Vue()

        beforeCreate
        created:           
            初始化好了props、data、methods
            在这个阶段,发起Ajax 请求,去拿数据,组件的模板结构尚未生成,不能操作dom
        beforeMount
        mounted:
            第一次dom 结构渲染好
            在这里可以最早去操作dom元素
    (2)组件运行阶段:
        执行次数:[0,n)

        beforeUpdate
        updated
    (3)组件销毁阶段:
        执行次数:只有1次

        beforeDestroy
        destroyed
        
    webpack -> main.js -> App.vue -> Left.vue Right.vue -> Count.vue

    <MyCount></MyCount>  用这个组件 就相当于new 了个vue 实例

十一.组件之间的数据共享
    1.组件之间的最常见的关系
        父子关系、兄弟关系
    2.父组件向子组件共享数据
        父组件向子组件共享数据需要使用自定义属性:
            示例:
                // 父组件
                <Son :msg="message" :user="userinfo"></Son>
                data(){
                    return{
                        message: 'hello vue.js',
                        userinfo: { name:'zs', age: 20 }
                    }
                }
                // 子组件
                <template>
                    <div>
                        <h5>Son 组件</h5>
                        <p>父组件传递过来的 msg 的值是: {{ msg }}</p>
                        <p>父组件传递过来的 user 的值是: {{ user }}</p>
                    </div>                
                </template>
                props:['msg','user']
    3.子组件向父组件传值
        子组件向父组件共享数据要使用自定义事件
        示例:
            // 父组件
            <Son @numchange="getNewCount"></Son>
            export default{
                data(){
                    return {
                        countFromSon: 0
                    }
                }
            },
            methods{
                getNewCount(val){
                    this.countFromSon = val
                }
            }
            // 子组件
            export default{
                data(){
                    return{
                        count: 0
                    }
                },
                methods: {
                    add(){
                        this.count += 1
                        // 修改数据时,通过$emit() 触发自定义事件
                        this.$emit('numchange',this.count)
                    }
                }
            }
    4.兄弟组件之间的数据共享
        在vue2.x 中,兄弟组件之间通过 EventBus 进行数据共享
        步骤:
            1.创建eventBus.js 模板,向外共享一个Vue 的实例对象
            2.在数据发送方,调用bus.$emit('事件名称',要发送的数据) 方法触发自定义事件
            3.在数据接收方,调用bus.$on('事件名称',事件处理函数)方法注册一个自定义事件
        示例:
            // eventBus.js
                import Vue from 'vue'
                // 向外共享Vue 的实例
                export default new Vue()

            // 兄弟组件A (数据发送方)
                import bus from './eventBus.js'
                export default{
                    data(){
                        return {
                            msg: 'hello vue.js'
                        }
                    },
                    methods: {
                        sendMsg(){
                            bus.$emit('share',this.msg)
                        }
                    }
                }

            // 兄弟组件B (数据接收方)
                import bus from './eventBus.js'
                export default{
                    data(){
                        return{
                            msgFromLeft: ''
                        }
                    },
                    created(){
                        bus.$on('share',val => {
                            this.msgFromLeft = val
                        })
                    }
                }

vue 基础总结
    1.内容渲染指令:
        v-text      缺点: 覆盖元素中的默认内容
        {{}}        插值只能在元素的内容节点,无法用在属性节点
        v-html      用处:把带有HTML 标签的字符串,渲染为真正的DOM 元素
    2.属性绑定指令:
        v-bind:     简写为 :
    3.事件绑定指令:
        v-on:       简写为 @   
                    @click="show" 和 @click="show(参数)"       
                    内置的变量: $event   @click="show(3,$event)"
                    事件修饰符:prevent、stop
                    按键修饰符:.esc、.enter
    4.双向数据绑定指令:
        v-model     只能用在表单元素上
                    修饰符:.number、.trim、.lazy
    5.循环渲染指令:
        v-for       v-for="(item,index) in 数组"
                    :key="item.id"
                    拿索引当key 没有意义
    6.条件渲染指令:
        v-if        动态创建和移除元素
                    v-else-if
                    v-else
        v-show      动态添加和移除 display: none; 样式
    7.过滤器
        全局过滤器    Vue.filter('名字',function(过滤器前面的值){
                        return 结果
                    })
        私有过滤器    定义到组件的filters 节点下  
                    {{ message | dataFormat}}
    8.侦听器
        watch           方法格式(简单)        username(newVal,oldVal){}
                    对象格式               username: { handler(newVal,oldVal){}, deep:true, immediate:true }

    9.计算属性
        computed    在定义的时候要定义为function
                    在使用的时候,当做普通属性使用即可(在template 模板结构中使用、 在methods 方法中使用 this.计算属性的名字)
                    要return 一个计算的结果
                    只要任何一个依赖的数据项发生了变化,计算属性就会重新渲染

    10.vue-cli      
                    全局安装:npm install @vue/cli -g
                    创建项目:vue create 项目的名称
                    组件的构成:template(只能有唯一的节点)
                              script(export default{}   .vue中的data 必须是方法)
                              style(启用less 语法:lang="less"  防止组件之间样式冲突:scoped,    /deep/ 深度选择器在需要覆盖第三方组件样式的时候会用到)
                              
    11.自定义属性
        props       提高组件的复用性
                    格式:  
                           数组格式: props:['init']
                           对虾干格式: props:{ init: { type: Number, default: 0, required: true }}
                    props 是只读的,因此在项目开发中,不要直接修改它的值
                    把props 的值转存到data 中,就可以进行读写操作
    
    12.生命周期
                    概念:每个组件从创建 -> 运行 -> 销毁的整个阶段,强调的是一个时间段
                    生命周期函数:在生命周期的不同阶段,会按次序依次执行的函数,强调的是时间点
                    生命周期的三个阶段:
                        1.创建阶段
                            beforeCreate
                            created
                                发起Ajax最早的时机,请求数据
                            beforeMount
                            mounted
                                组件第一次被渲染到浏览器中
                                操作DOM 的最早的时机
                        2.运行阶段
                            beforeUpdate
                            updated
                                能够操作到最新的DOM 元素
                        3.销毁阶段
                            beforeDestroy
                            destroyed

    13.组件之间的数据共享
                    父 -> 子:自定义属性
                        子组件中:通过props 来定义属性
                        父组件中:负责把数据,通过v-bind: 绑定给子组件
                    子 -> 父:自定义事件
                        子组件中:调用this.$emit() 来触发自定义事件
                            参数1:字符串格式,表示自定义事件的名称
                            参数2:值,要发送给父组件的数据
                        父组件中:通过@ 来绑定自定义事件,并提供一个事件处理函数,通过事件处理函数的形参,接收到子组件传递过来的数据
                    兄弟组件之间的数据共享:eventBus
                        数据发送方:
                                  导入eventBus.js: import bus from './eventBus.js'
                                  bus.$emit('要触发的事件的名字',要发送的数据)
                        EventBus.js 模块:
                                  创建vue 的实例对象: new Vue()
                                  向外导出Vue 的实例对象: export default new Vue()
                        数据接收方:
                                  导入eventBus.js: import bus from './eventBus.js'
                                  bus.$on('要声明的自定义事件的名字',事件的处理函数)  
                                  通过事件处理函数的形参,可以接收到发送过来的数据
                                  在数据接收方的created 生命周期函数中,调用bus.$on() 方法

十二.ref 引用
    ref 用来在不依赖于jQuery 的情况下,获取DOM 元素或组件的引用
    示例:
        <h3 ref="myh1">App 根组件</h3>
        <button @click="showThis">打印this</button>
        methods: {
            showThis(){
                // 当前this 是App 组件的实例对象
                console.log(this.$refs.myh1);
                this.$refs.myh1.style.color="red"
            }
        }

    示例:
        <input type="text" v-if="inputVisible" @blur="showButton" ref="iptRef">
        <button v-else @click="showInput">展示输入框</button>
        showInput(){
        this.inputVisible = true   // 数据更新
        console.log(this.$refs.iptRef);  
        // 由于数据更新之后无法立即渲染dom
        // 此时 this.$refs.iptRef 的值为undefined
        },
    this.$nextTick(cb) 方法
        组件的$nextTick(cb) 方法,会把cb 回调推迟到下一个DOM 更新周期之后执行
    示例:
        this.$nextTick(() => {
            this.$refs.iptRef.focus()
        })
    
十三.购物车案例
    一.数组中的方法
        1.forEach()
            forEach 循环一旦开始,就无法在中间被停止,即从头循环到尾,效率较低
                const arr = ['小红','小黄','小绿']
                arr.forEach( (item,index) => {
                    if(item === '小绿'){
                        console.log(index);
                    }
                })
        2.some()
            从数组中找元素,用some 比较合适
            在找到对应的项之后,可以通过return true 固定的语法,来终止some 循环
                const arr = ['小红','小黄','小绿']
                arr.some( (item,index) => {
                    if( item === '小绿'){
                        console.log(index);
                        return true
                    }
                })
        3.every()
            数组中每一项都满足要求,则返回true
            const arr = [
                {id: 1,name: '西瓜',state: true},
                {id: 2,name: '榴莲',state: true},
                {id: 3,name: '草莓',state: true},
            ]
            // 判断数组中水果是否全部被选中
            const result = arr.every( item => item.state);
            console.log(result);       // true
        4.filter()
            // 需求,把购物车数组中已经勾选的水果总价累加起来
            const arr = [
                { id: 1, name: '西瓜', state: true , price: 10, count: 1},
                { id: 2, name: '榴莲', state: false , price: 80, count: 2},
                { id: 3, name: '草莓', state: true , price: 20, count: 3},
            ]
            let amt = 0     // 总价
            arr.filter(item => item.state).forEach(item => {
                amt += item.price * item.count
            })
            console.log(amt);
        5.reduce()
            // arr.filter(item => item.state).reduce((累加的结果,当前循环项) => {},初始值)
            const arr = [
                { id: 1, name: '西瓜', state: true, price: 10, count: 1 },
                { id: 2, name: '榴莲', state: false, price: 80, count: 2 },
                { id: 3, name: '草莓', state: true, price: 20, count: 3 },
            ]
            const result = arr.filter(item => item.state).reduce((amt,item) => {
                return amt += item.price * item.count  
            },0)
            // const result = arr.filter(item => item.state).reduce((amt,item) => amt += item.price * item.count,0)
            console.log(result);
    二. 安装与使用    
            npm i axios -S
            import axios from 'axios'
            1.安装并在App 中导入axios
            2.在methods 方法中,定义initCartList 函数请求列表数据
            3.在created 生命周期函数中,调用步骤2 封装的initCartList 函数

            只要请求回来的数据,在页面渲染期间要用到,必须转存到data 中
    三.装包  
        npm install
        npm i

十四.动态组件
    1.动态组件
        动态组件指的是动态切换组件的显示与隐藏
        vue 提供了内置的<component> 组件,专门用来实现动态组件的渲染
        语法:
            <keep-alive>
                <component :is="comName" ></component>
            </keep-alive>
            data() {
                return {
                // comName 表示要展示的组件的名字
                comName: 'Left'
                }
            },
    
        注意:
            1.component 标签是vue 内置的,作用:组件的占位符
            2.is 属性的值,表示要渲染的组件的名字
            3.is 属性的值,应该是组件在components 节点下的注册名称
            4.<keep-alive> 可以把内部的组件进行缓存,而不是销毁组件
    2.keep-alive
        keep-alive 对应的生命周期函数
            1.当组件被缓存时,会自动触发组件的 deactivated 生命周期函数
            2.当组件被激活时,会自动触发组件的 activated 生命周期函数
            3.当组件第一次被创建的时候,既会执行created 生命周期,也会执行activated 生命周期
            4.当组件被重新激活的时候,只会执行activated 生命周期,不会再触发created ,因为组件没有重新创建
        
        kepp-alive 的include 属性:
            <keep-alive include="Left,Right">
                <component :is="comName" ></component>
            </keep-alive>   
        kepp-alive 的exclude 属性:
            <keep-alive exclude="Right">
                <component :is="comName" ></component>
            </keep-alive>
        注意:
            1.keep-alive 可以把内部的组件进行缓存,而不是销毁组件
            2.在使用keep-alive 的时候,可以通过include 指定哪些组件需要被缓存
            3.或者,通过exclude 属性指定哪些组件不需要被缓存
            4.但是,不能同时使用 include 和 exclude 这两个属性
    3.组件的名称
        如果在声明组件的时候,没有为组件指定name 名称,则组件的名称默认就是注册时候的名称
        
        对比:
            1.组件的“注册名称“ 的主要应用场景: 以标签的形式,把注册好的组件渲染和使用到页面结构之中
            2.组件声明时候的 "name " 名称的主要应用场景,结合<keep-alive> 标签实现组件缓存功能,
                以及在调试工具看到组件的 name 名称

十五.插槽
     <template v-slot: default>
         <p>Left 组件里面的插槽</p>
    </template>
    <slot name="default"></slot>
    
   注意:
        1.每个slot 插槽都有一个name 属性,来定义插槽名称,不写默认为 name="default"
        2.默认情况下,在使用组件的时候,提供的内容都会被填充到名字为default 的插槽中
        3.如果要把内容填充到指定名称的插槽中,需要使用v-slot: 这个指令
        4.v-slot: 后面要跟上插槽的名字
        5.v-slot: 只能用在<template>标签 或者是 组件标签上
        6.<template> 标签是一个虚拟的标签,只起到包裹的作用,不会被渲染为html 元素
        7.v-slot:  简写是 #

十六.自定义指令
    1.私有自定义指令
        directives: {
            // 定义名为color 的自定义指令 指向一个配置对象
            color: {
                // 当指令第一次被绑定到元素上的时候,会立即出发bind 函数
                // 形参中的el 表示当前指令所绑定到的那个dom 对象

                bind(el,binding){
                    el.style.color = binding.value
                },

                // dom 更新的时候会触发update
                update(el,binding){
                    el.style.color = binding.value
                },
            }
        }
        当color 和 update 中的代码一致时,可以简写为:
        directives: {
            color(el,binding){
                el.style.color = binding.value
            }
        }

    2.全局自定义指令
        在main.js 中声明:
            Vue.directive('color',function(el,binding){
                el.style.color = binding.value
            })

一.axios
    axios 是专注于数据请求的库
    中文官网:http://www.axios-js.com
    英文官网:http://www.npmjs.com/package/axios
    语法:
        axios({
            method: '请求的类型',
            url: '请求的url 地址',
            // URL 中的查询参数
            params: {},
            // 请求体参数
            data: {}
        }).then((result) => {
            // .then 用来指定请求成功之后的回调函数
            // 形参中的 result 是请求成功之后的结果

        })
    注意:
        调用axios 方法得到的返回值是 Promise 对象
        如果调用某个方法的返回值是Promise 实例,则前面可以添加await
        await 只能用在被async 修饰的方法中
    示例:
        一、通过axios 发起get 和 post 请求
            1.发起GET 请求
                document.querySelector('#btnGet').addEventListener('click',async function(){
                    // 解构赋值的时候,使用: 进行重命名
                    // 1.调用完axios 之后,使用async/await 进行简化
                    // 2.使用解构赋值,从axios 封装的大对象中,把data 属性解构出来
                    // 3.把解构出来的data 属性,使用: 进行重命名,一般都重命名为 { data: res }
                    const {data: res} = await axios({
                        method: 'GET',
                        url: 'http://www.liulongbin.top:3006/api/getbooks',
                    })
                    console.log(res);
                })
            2.发起POST 请求
                document.querySelector('#btnPost').addEventListener('click',async function(){
                    // 如果调用某个方法的返回值是Promise 实例,则前面可以添加await
                    // await 只能用在被async 修饰的方法中
                    const { data } = await axios({
                        method: 'POST',
                        url: 'http://www.liulongbin.top:3006/api/post',
                        data: {
                            name: 'zz',
                            age: 10
                        }
                    })
                    console.log(data);
                })

        二、直接使用get 和 post 发起请求
            1.发起get 请求
            <button id="btnGet">GET</button>
            document.querySelector('#btnGet').addEventListener('click',async function(){
                const { data: res } = await axios.get('http://www.liulongbin.top:3006/api/getbooks',{
                    params: { id: 1 }
                })
                console.log(res.data);
            })
            2.发起post 请求
            <button id="btnPost">POST</button>
            document.querySelector('#btnPost').addEventListener('click',async function(){
                const { data: res } = await axios.post('http://www.liulongbin.top:3006/api/post',
                    {name: 'zs',gender: '女'}
                )
            })

一.vue 组件库:
    element-ui
    vant

一.Eslint
    格式化代码

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值