Vue2.0学习总结

文章目录

  • 入门呢案例分析
  • 模板语法
  • 数据绑定
  • el与data的两种写法
  • MVVM模型
  • 数据代理
  • 事件处理
    • 事件的基本使用
    • Vue中事件的修饰符
    • 键盘事件
  • 计算属性
  • 监视属性
    • 深度监视
  • 绑定样式
  • 条件渲染
  • 列表排序
      • Vue监测数据原理
  • Vue数据监视
  • 收集表单数据
  • v-指令
    • v-once
    • v-pre
  • 自定义指令
  • Vue生命周期
  • 非单文件组件
    • 基本使用
    • 组件注意事项
    • 组件的嵌套
    • VueComponnet
    • 原型与原型链
    • 一个重要的内置关系
  • 单文件组件
    • render函数
  • 组件自定义事件
  • 全局事件总线
    • 消息订阅与发布
    • Vue动画
    • 配置代理
  • 插槽
      • 作用域插槽
  • 创建Vue脚手架
    • ref属性
    • props属性
    • mixin(混入)
    • plugin(插件)
    • scoped样式
  • vuex
  • 路由
    • 路由器的两种工作模式
    • 路由器的两种工作模式

入门呢案例分析

 <div id="app">
        <h1>你好,我是{{name}}</h1>
 </div>
    <script>
        // Vue.config.productionTip = false;
        const x = new Vue({
            el: '#app', //el指定当前Vue为实例化哪个对象
            data() {
                return {
                    name: '张三',
                    age: 20
                };
            },
        });
    </script>
//分析,一个容器交给一个vue实例去处理,他们之间的关系是一一对应,他们分别对应第一个
//{{}}之间可以写入的是什么,{{}}里边只可以写js代码0】
//(1)表达式 a a+b x==y?'a':'b'
//(2)js代码 if(){}  for(){}

总结

  • Vue实例和容器时一一对应的关系,并且会配合着组件一起使用
  • {{xxx}}中的xxx要写js表达式,且xxx可以自动读取data中的所有属性;
  • 一旦data中的数据发生改变,那么模板中用到该数据的地方也会自动更新

模板语法

Vue模板语法分为2大类:

  1. 插值语法
    • 功能:用于解析标签体内容
    • 写法:{{xxx}},xxx时js表达式,而且可以直接读取到data中所有属性
  2. 指令语法
    • 功能:用于解析标签(包括啊:标签属性,标签内容,绑定事件)
    • 举例:v-bind:href=“xxx“简写为:href=“xxx”,xxx同样要写js表达式,且可以直接读取道data中的所有属性
    • 备注:Vue中有很多的指令,且形式都是v-???开头,在此举得例子时v-bind

数据绑定

<div id="root">
        单向绑定:<input type="text" v-bind:value="school.name">
        双向绑定:<input type="text" v-model:value="school.name">
            简写
        单向绑定:<input type="text" :value="school.name">
        双向绑定:<input type="text" v-model="school.name">
 </div>
    <script>
        // Vue.config.productionTip = false;
        const x = new Vue({
            el: '#root', //el指定当前Vue为实例化哪个对象
            data() {
                return {
                    uname: '张三',
                    age: 20,
                    url: "https://www.baidu.com/",
                    school: {
                        name: '河南科技学院'
                    }
                };
            },
        });
    </script>

Vue中有两种数据绑定

  • 单向绑定(v-bind):数据只能重data流向页面
  • 双向绑定(v-model):数据不仅可以从data流向页面,还可以从页面流向data
    • 备注
      1. 双向绑定一般用在表单类元素上(如:input,select等)
      2. v-model:value可以简写成v-model,因为v-model默认收集的就是value值

el与data的两种写法

  1. el有两种写法

    • .new Vue时配置el属性
    • 先创建Vue实例,随后再通过vm.$mount(‘#app’)指定el的值
  2. data有两种写法

    • 对象式

    • 函数式

      如何选择:目前用哪种都可以,在学习函数组件时,data必须要用函数式,否则会报错

  3. 一个重要原则

    由Vue管理的函数一定不要用箭头函数,箭头函数没有自己的this

MVVM模型

  • M:模型(Model)
  • V:视图(View)
  • VM:视图模型(ViewModel):Vue实例对象

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YT8rVA4B-1666772187950)(img/image-20220906213326911.png)]

数据代理

let number = 13;
        let person = {
            name: '张三',
            sex: '男',
            adress: '郑州'
        }
        Object.defineProperty(person, 'age', {
            // value: 19,
            // enumerable: true, //控制属性是否可可以枚举,默认值式false
            // writable: true, //控制属性是否可以被修改,默认值式false
            // configurable: true //控制属性是否被删除

            //get函数,当读取person的age属性时,get函数自动会被调用
            get() {
                return number
            },
            //set函数,当修改person的age属性时,set函数自动会被调用
            set(value) {
                number = value;
                console.log('有人修改了person的age值是' + value);
            }
        })
        console.log(person);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CmqzKqIH-1666772187951)(img/image-20220907092507149.png)]

  • 将obj2添加属性x,值为objx的值,当修改obj2的值时自动修改obj中的x值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nH42stzQ-1666772187952)(img/image-20220907153424087.png)]

事件处理

<div id="app">
        <h1>开始练习</h1>
        <button @click="showInfo1">点我提示信息(不传参)</button>
        <!-- 采用占位符号$ -->
        <button @click="showInfo2(18,$event)">点我提示信息(传参)</button>
    </div>
    <script>
        new Vue({
            el: '#app',
            data() {
                return {
                    property: 'value',
                };
            },
            methods: {
                showInfo1(event) {
                    console.log(event.target);
                },
                showInfo2(number, e) {
                    console.log(number, e.target);
                }
            }
        })
    </script>

事件的基本使用

  1. 使用v-on:xxx或者@xxx绑定事件,其中xxx时事件名
  2. 时间的回调需要配置子methods中,最总会在vm中
  3. methods中配置的函数不要使用箭头函数!否则this就不是vm了
  4. methods中配置的函数,都是被Vue所管理的函数,this的指向时vm或者组件实例对象
  5. @click="demo"和@click="demo($event)"效果是一样的,但后者可以传参

Vue中事件的修饰符

Vue常用的事件修饰符,修饰符可以连续写

  • prevent:阻止默认事件(常用)
  • stop:阻止事件冒泡(常用)
  • once:事件只触发一次
  • capture:使用事件捕获模式
  • self:只有event.target是当前操作的元素时才触发事件
  • passive:事件的默认行为立即执行,无需等待回调函数执行完毕
    <div id="app">
        <h1>开始练习</h1>
        <!-- 阻止事件默认行为,a标签的默认行为是跳转 -->
        <a href="http://www.baidu.com" @click.prevent="a">点我进行页面跳转</a>

        <!-- 阻止事件冒泡 -->
        <div class="box1" @click.stop="showMsg(1)">
            div1
            <div class="box2" @click="showMsg(2)">
                div2
            </div>
        </div>
        <!-- 事件只触发一次 -->
        <div id="demo" @click="showInfo">
            <button @click.once="showInfo">点击触发事件</button>
        </div>
        <!-- 使用事件捕获模式 -->
        <div class="box1" @click.="showMsg(1)">
            div1
            <div class="box2" @click="showMsg(2)">
                div2
            </div>
        </div>
        <!-- 使用事件捕获模式 -->
        <div class="box1" @click.capture="showMsg(1)">
            div1
            <div class="box2" @click="showMsg(2)">
                div2
            </div>
        </div>
        <!-- 点击div1才触发 -->
        <div class="box1" @click.self="showMsg(1)">
            div1
            <div class="box2" @click="showMsg(2)">
                div2
            </div>
        </div>
        <!-- 两种滑动滚轮的方式,scroll和wheel;
        scoll默认事件和回调函数一起执行
        wheel是执行回调函数后执行默认事件   
        -->
        <ul class="ull" @scroll="move">
            <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
        </ul>
    </div>
    <script>
        new Vue({
            el: '#app',
            data() {
                return {
                    property: 'value',
                };
            },
            methods: {
                a() {
                    alert('我可以跳转到百度')
                },
                showInfo(event) {
                    alert('Hello World ')
                },
                showMsg(number) {
                    alert('输出的值是' + number)
                },
                move() {
                    console.log('滚动了');
                }

            }
        })
    </script>

键盘事件

    <div id="app">
        <h1>开始练习</h1>
        <input type="text" placeholder="按下回车提示输入信息"             @keyup.enter="showInfo">//事件按键,只有按下回车键才会触发
    </div>
    <script>
        new Vue({
            el: '#app',
            data() {
                return {
                    property: 'value',
                };
            },
            methods: {
                showInfo(e) {
                    console.log(e.key, e.keyCode);
                }

            }
        })
    </script>

Vue中常见的按键别名:

回车(enter)
删除(delete)
退出(esc)
空格(space)
换行(tab)
上(up)
下(down)
左(left)
右(right)

计算属性

    <div id="app">
        <h1>开始练习</h1>
        姓:<input type="text" v-model="fistName"><br/><br/> 名:
        <input type="text" v-model="lastName"><br/><br/> 全名:
        <span>{{fullName}}</span>
    </div>
    <script>
        const vm = new Vue({
            el: '#app',
            data() { //只要data中的数据改变,vue一定会重新解析模板
                return {
                    fistName: '张',
                    lastName: '三'
                };
            },
            // 计算属性
            computed: {
                fullName: {
                    //get有什么用,当有人调用或者修改fullName中的属性时会调用
                    get() {
                        console.log('get被调用了');
                        return this.fistName + '-' + this.lastName;
                    },
                    //当修改fullName属性时,set方法被调用
                    set(value) {
                        console.log('set方法被调用');
                        let arr = value.split('-');
                        this.fistName = arr[0];
                        this.lastName = arr[1];
                    }
                }
            }
        })
    </script>

计算属性:

  • 定义:要用的属性不存在,要通过已有的属性计算得来
  • 原理:底层借助了Objcet.defineproperty方法提供的getter和setter
  • get函数什么时候执行?
    1. 当读取时会执行一次
    2. 当依赖的数据发生改变时会被再次调用
  • 优势:与methods相比,内部有缓存机制(复用),效率高,调试方便
  • 备注:
    1. 计算属性终会出现在vm上,直接读取使用即可(不能读取其中的get方法)
    2. 如果计算属性要被修改,那必须写set函数去影响修改,且set中要引起计算时以来的数据发生改变

监视属性

<div id="app">
        <h1>开始练习</h1>
        <h2>今天天气很{{weather}}</h2>
        <button @click="changWeather">点击我更改天气</button>
</div>
    <script>
        new Vue({
            el: '#app',
            data() {
                return {
                    isHot: true
                }
            },
            computed: {
                weather: function() {
                    return this.isHot ? '炎热' : '凉爽'
                }
            },
            methods: {
                changWeather() {
                    this.isHot = !this.isHot
                }
            },
            //配置监视,完整形式
            watch: {
                //当isHot别修改时触发函数
                isHot: {
                    immediate:true,//初始化时让handler调用一下
                    deep:true,//深度监视
                    handler() {
                        console.log('isHot被修改了');
                    }
                }
            }
            //简写监视
             watch: {
                //如果配置项中只有handler,可以用简写
                isHot(newValue,oldValue){
                    console.log('isHot被修改了');
                }
            }
        })
    </script>

监视属性watch:

  • 当监视的属性发生变化时,回调函数自动调用,进行相关操作
  • 监视的属性必须存在,才能进行监视!!
  • 监视的两种写法:
    1. new Vue时传入watch配置
    2. 通过vm.$watch监视

深度监视

<div id="app">
        <h1>开始练习</h1>
        <h2>
            a的值是:{{number.a}}
        </h2>
        <button @click="number.a++">点我让a++</button>
        <h2>
            b的值是:{{number.b}}
        </h2>
        <button @click="number.b++">点我让b++</button>
    </div>
    <script>
        new Vue({
            el: '#app',
            data() {
                return {
                    number: {
                        a: 1,
                        b: 2
                    }
                }
            },
            //配置监视
            watch: {
                //当isHot别修改时触发函数
                'number.a': {
                    //监视多级结构中所有属性的变化
                    deep: true,
                    handler() {
                        console.log('a改变了');
                    }
                }
            }
        })
    </script>

深度监视:

  • vue中watch默认不见时对象内部的改变(一层)
  • 配置的deep:true可以监视对象内部值的改变

备注:

  • vue自身可以监视对象内部值的改变,但Vue提供的watch默认不可以
  • 使用warch时根据数据的具体结构,决定是否采用深度监视

computed 和 watch之间的区别:

  1. computed能完成的功能,watch都能够完成
  2. watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作

两个小原则:

  1. 所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm或者组件实例对象
  2. 所用不被Vue所管理的函数(定时器的回调函数,ajax的回调函数等,Promise的回调函数),最好写成箭头函数,这样this的指针才能是vm或者组件实例对象

绑定样式

<div id="app">
        <h1>开始练习</h1>
        <input type="text" :value="fullName"><br>
        <button @click="changMood">点击更换姓名</button>
        <!--class绑定样式字符串法,适用于:样式的类名不确定,需要动态指定  -->
        <div class="basic" :class="color" @click="changeColor">点击更换颜色</div>
        <!-- class绑定样式数组法,适用于要绑定的个数不确定,名字也不确定 -->
        <div class="basic" :class="arr" >更换颜色</div>
        <!-- class绑定样式对象法,适用于要绑定的个数不确定,名字也不确定 -->
        <div class="basic" :class="classObj" >更换颜色</div>
        <!-- style绑定样式对象法,适用于要绑定的个数不确定,名字也不确定 -->
        <div class="basic" :style="styleObj" >更换颜色</div>

    </div>
    <script>
        const vm = new Vue({
            el: '#app',
            data() { 
                return {
                    fullName: '张三',
                    color: 'normal',
                    arr: ['style1', 'style2', 'style3'],
                    classObj: {
                        style1: false,
                        style2: false
                    },
                    styleObj: {
                        //根据系统的改变,系统的有font-size等
                        fontSize: '50px',
                        backgroundColor: 'yellow',
                        fontColor: 'gray'
                    }
                }
            },
            methods: {
                changMood() {
                    this.fullName = '王五'
                },
                changeColor() {
                    const arr = ['happy', 'sad', 'normal']
                    let index = Math.floor(Math.random() * 3)
                    this.color = arr[index];
                },
            }

        })
    </script>

条件渲染

<div id="app">
        <h1>开始练习</h1>
        <h2>a={{a}}</h2>
        <button @click="a++">点击我实现a++</button>
        <h2 v-show="false">我来自{{adress}}1</h2>
        <!-- 中间结构不能够打断 -->
        <h2 v-if="a==1">第一</h2>
        <h2 v-else-if="a==2">第二</h2>
        <h2 v-else-if="a==3">第三</h2>
        <h2 v-else>第四</h2>
        <!-- template只能和v-if配合使用 -->
        <template v-if="n==1">
            <h3>北京</h3>
            <h3>上海</h3>
            <h3>广州</h3>
        </template>

    </div>
    <script>
        const vm = new Vue({
            el: '#app',
            data() {
                return {
                    adress: '河南省',
                    a: 0
                }
            },
        })
    </script>
  • v-if
    1. v-if;v-else-if;v-else;中间不能够打断
    2. 适用于切换频率不高的场景
    3. 特点:不展示DOM元素(如果为false,页面没有)
  • v-show
    1. 写法:v-show="“表达式”
    2. 适用于切换频率不高的场景
    3. 特点:不展示DOM元素,仅仅是使样式隐藏掉

react、vue、中的key什么用

  1. 虚拟DOM中key的作用

    • key是DOM的对象标识,当数据发生改变时vue会根据【新数据】生成【新的虚拟DOM】
  2. 新虚拟DOM与旧虚拟DOM对比原则

    • 旧的虚拟DOM找新虚拟DOM相同的key:
      1. 若虚拟DOM没有内容变化,直接使用之前的真实DOM
      2. 若虚拟DOM内容改变了,则生成新的真实DOM,随后替换页面中之前的真实DOM
    • 旧的DOM未找到新虚拟DOM相同的key
      1. 创建新的真实DOM,让后渲染页面
  3. 用index和key可能引发的问题

    • 若对数据进行:逆序添加、逆序删除等破坏顺序的操作:

      会产生没有必要的真实DOM更新==>界面效果没问题,但效率低

    • 如果结构还包含输入类的DOM:

      会产生错误DOM更新==》界面有问题

  4. 开发中如何选用key?

    • 最好使用每条数据的唯一标识作为key,如id,手机号,身份证号码,学号等唯一标识

列表排序

<div id="app">
        <h1>开始测试</h1>
        <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 in filPersons">
                {{p.name}}--{{p.age}}
            </li>
        </ul>
    </div>
    <script>
        new Vue({
            el: '#app',
            data() {
                return {
                    keyWord: '',
                    sortType: 0,
                    persons: [
                        {id: '001',name: '周杰伦',age: 23}, 
                        {id: '002',name: '张望伦',age: 18}, 
                        {id: '003',name: '张三丰',age: 35}, 
                        {id: '003',name: '周找天',age: 19}
                    ],
                }
            },
            //computed实现
            computed: {
                filPersons() {
                    const arr = this.persons.filter((p) => {
                        return p.name.indexOf(this.keyWord) != -1
                    })
                    if (this.sortType) {
                        arr.sort((p1, p2) => {
                            return this.sortType == 2 ? p1.age - p2.age : p2.age - p1.age
                        })
                    }
                    return arr
                }
            },
        })
    </script>

Vue监测数据原理

数据更改==》set()调用,set里写了个调用重新解析模板==》生成新的虚拟DOM==》新旧虚拟DOM对比==》生成真实页面

Vue数据监视

  • vue会监视data中所有层次的数据

  • 如何仅是对象中的数据

    1. 通过setter实现监视,要在 new Vue时加入监视的数据
      • 对象中后追加的属性,Vue默认不做处理
      • 如果给后添加的属性做响应式,使用API
        • Vue.set(target, propertyName, value) Vue.set(this.student, ‘sex’, ‘男’)
        • vm. s e t ( t a r g e t , p r o p e r t y N a m e , v a l u e ) t h i s . set(target, propertyName, value) this. set(target,propertyName,value)this.set(this.student, ‘sex’, ‘男’)
  • 如何检测数组中的数据

    通过包裹数组更新元素的方式实现

    1. 调用原生对应的方法对数组进行更新
    2. 重新解析模板,进行更新页面
  • Vue中修改数组中某个元素一定用到如下方法:

    API:push(),pop(),shift(),unshift(),splice(),sort(),reverse()

    Vue.set()或者vm.$set()

收集表单数据

<div id="app">
        <form @submit.prevent="demo">
            <label for="account">账号</label><input type="text" id="account" v-model.trim="account">
            <label for="ps">密码</label><input type="text" id="ps" v-model="password">
            <label for="age">年龄</label><input type="number" id="age" v-model.number="age">
             性别:
             男<input type="radio" name="sex" value="male" v-model="sex"><input type="radio" name="sex" value="female" v-model="sex">
            爱好: 
			学习<input type="checkbox" v-model="hobby" value="study"> 
             打游戏<input type="checkbox" v-model="hobby" value="game">
             吃饭<input type="checkbox" v-model="hobby" value="eat">  
            所属校区
            <select v-model="city">
              <option value="beijing" >北京</option>
              <option value="shenzhen" >深圳</option>
              <option value="wuhan" >武汉</option>
            </select><br><br> 其他信息
            <textarea v-model.lazy="other"></textarea> 
            <input type="checkbox" v-model="agree">
            阅读并接受<a href="http://www.baidu.com">《用户协议》</a>
            <button>提交</button>
        </form>
    </div>
    <script>
        const vm = new Vue({
            el: '#app',
            data() {
                return {
                    account: '',
                    password: '',
                    age: '',
                    sex: '',
                    hobby: [],
                    city: 'beijing',
                    other: '',
                    agree: ''
                }
            },
            methods: {
                demo() {
                    console.log(JSON.stringify(this._data));
                }
            },
        })
    </script>
  • 若: , 则v-model收 集的是value值,用户输入的就是value值。

  • 若: , 则v-model收 集的是value值,且要给标签配置value值。

  • 若:

    1.没有配置input的value属性,那么收集的就是checked (勾选or未勾选,是布尔值)

    2.配置input的value属性:

    • (1 )v - model的初始值是非数组,那么收集的就是checked (勾选or未勾选,是布尔值)

    • (2 )v- model的初始值是数组,那么收集的的就是value组成的数组

    备注: v-model的 三个修饰符:

    • lazy:失去焦点再收集数据

    • number:输入字符串转为有效的数字

    • trim:输入首尾空格过

v-指令

v-once

  • v-once在初次动态渲染后就视为静态内容了

  • 以后数据的改变不会引起v-once所在结构的更新

v-pre

  • v-pre可以跳过节点的编译过程

  • 可以用它跳过:没用使用指令的语法,没用使用插值的语法节点,会加快编译

自定义指令

  • 需求1:定义一个v-big指令, 和v-text功能类似,但会把绑定的数值放大10倍。

  • 需求2:定义-一个v-fbind指令,和v-bind功能类似,但可以让其所绑定的input元素默认获取焦点。

  • 自定义指令总结:

    定义语法:

    1. 局部指令:

      new Vue({
      directives:{指令名:配置对象}
      })//或者
      new Vue({
      directives:{指令名,回调函数}
      })//或者
      

      2.全局指令:

    Vue.directive(指令名,配置对象)或Vue . directive(指令名,回调函数)

  • 配置对象中常用的3个回调:

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

    1. .指令定义时不加心,但使用时要)加Iv-;
    2. 指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名。

Vue生命周期

Vue2.0学习总结_第1张图片

div id="app">
        <h1>当前数字是:{{n}}</h1>
        <button @click="n++"></button>
    </div>
    <script>
        const vm = new Vue({
            el: '#app',
            //vue完成真实的解析并把真实的DOM元素放入页面之后,调用mounted
            data() {
                return {
                    n: 1,
                }
            },
            beforeCreate() {
                console.log('beforeCreate')
            },
            created() {
                console.log('created')
            },
            beforeMount() {
                console.log('beforeMount')
            },
            mounted() {
                console.log('mounted', this);

            },
            //数据和页面未保持同步
            beforeUpdate() {
                console.log('beforeUpdate');
            },
            updated() {
                console.log('updated');
            },
            //数据所做的所有操作不做更新
            beforeDestroy() {
                console.log('beforeDestroy');
            },
            destroyed() {
                console.log('destroyed');
            },
        })
    </script>

常用的生命周期函数

  • mounted:发送ajax请求,启动定时器,绑定自定义事件,订阅消息等【初始化操作】
  • beforeDestory:清除定时器,绑定自定义事件,取消订阅消息【收尾工作】

关于销毁Vue实例

  • 销毁后借助Vue的开发工具不会有任何信息
  • 销毁自定义事件会失效,但原生DOM事件依然有效
  • 一般不会在beforeDestroy操作数据,但即使操作了,也不会触发更新流程

非单文件组件

基本使用

Vue中使用组件的三大步骤

  • 定义组件
  • 注册组件
  • 使用组件
  1. 如何定义一个组件

    • 使用Vue.extend(options)创建,其中options和 new Vue(options)时传入的那个options几乎一样,但也有点不同:
      1. el不要写,为什么?最终所有的组件都要经过一个vm管理,有vm中的el决定哪一个服务器
      2. data必须写成函数,为什么?避免组件被复用时,数据存在引用的关系
    • 使用tmplate可以配置组件结构
  2. 如何注册组件?

    • 局部注册:靠new Vue的时候传入components选型
    • 全局注册:靠Vue.component(‘组件名’,组件)
  3. 编写组件标签

    <div id="app1">
            <h1>{{msg}}</h1>
            <hr>
             //第三步,调用组件
            <xuexiao></xuexiao>
            <hr>
            <div id="app2">
                <hello></hello>
            </div>
    </div>
            <script>
                //第一步,定义组件
                const school = Vue.extend({
                    template: `
                

    学校名称:{{schoolName}}

    学校地址:{{address}}

    `
    , data() { return { schoolName: '科技学院', address: '新乡', } }, }) //全局注册组件 Vue.component('hello', hello) new Vue({ el: '#app1', data() { return { msg: '你好啊' } }, components: { //第二步,配置组件 xuexiao: school, } }) </script>

组件注意事项

  • 关于组件名称
    • 一个单词写法
      1. 第一种首字母小写:school
      2. 第二种首字母大写:School
    • 多个单词组成
      1. 第一种写法(kebab-case命名):my-school
      2. 第二种写法(CameCase命名):MySchool(需要用Vue脚手架支持)
    • 备注
      1. 组件名尽可能回避HTML中已有的元素名称:例如H1,H2
      2. 可以使用name配置项指定组件在开发者工具中呈现的名字
  • 过于组件的标签
    • 第一种写法:
    • 第二种写法:
    • 备注:不适用脚手架,会导致后续组件不能渲染
  • 组件定义简写

组件的嵌套

    <div id="app1">
        <app></app>
    </div>
    <script>
        const student = {
            name: 'student',
            template: `
            

学生姓名:{{studentName}}

`
, data() { return { studentName: '小明', } }, } const school = Vue.extend({ template: `

学校名称:{{schoolName}}

学校地址:{{address}}


`
, data() { return { schoolName: '科技学院', address: '新乡', } }, components: { student, } }) const app = Vue.extend({ template: `
`
, components: { school } }) new Vue({ el: '#app1', data() { return { msg: '你好啊' } }, components: { //school:school app } }) </script>

VueComponnet

  • school组件的本质时一个名为VueComponent的构造函数,且不是程序员定义的,时Vue.extend生成的

  • 我们只需要写或者,Vue解析时会帮助我们创建school组件的实例对象,即Vue帮我们执行的:new VueComponent(options)

  • 特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent!!!

  • 关于this的指向

    1. 组件配置中:

      data函数,methods中的函数,watch中的函数,computed中的函数 他们的this是VueComponent实例对象

    2. new Vue()配置中

      data函数,methods中的函数,watch中的函数,computed中的寒素,他们的this是Vue实例对象

  • vueComponent实例对象,简称vc

原型与原型链

        class Student {
            constructor(name, score) {
                this.name = name;
                this.score = score;
            }
            introduce() {
                console.log(`我是${this.name},考了${this.score}分。`);
            }
        }
        const student = new Student('张三', '99');
        console.log(student.__proto__ === Student.prototype);

实例对象(student)的隐式原型对象 === 构造函数(Student)的显示原型对象

统统指向原型对象

一个重要的内置关系

vue.component.prototype.(proto)==Vue.prototype
Vue2.0学习总结_第2张图片

结论:让VueComponent的实例对象(vc)可以使用Vue原型上的属性和方法

单文件组件




render函数

Vue.config.productionTip = false
    //使用vue的插件

new Vue({
    el: '#app',
    render: h => h(App),
    
//   render :q =>q('h1','你好啊')
    
//   render :createElentment =>createElement('h1','你好啊')
    
//    render :createElentment =>{
//         return createElement('h1','你好啊')
//    }
    
//    render(createElement){
//        return createElement('h1','你好啊')
//    }
})

组件自定义事件

  • 一种通信的方式:适用于子组件传给父组件

    注意:父传子props最方便

  • 使用场景:A是父组件,B是子组件,B想给A传数据那么需要在A中给B绑定自定义事件

  • 绑定自定义事件:

    1. 第一种方式,父组件中:

    2. 第二种方式,在父组件中

      <School ref="school" />
       mounted () {
          this.$refs.school.$on('dizhi', this.sendSchoolAddress)
        },
      
    3. 若想让自定义事件只触发一次可以用once修饰符,或者$once方法

  • 出发绑定事件:this.$emit(‘haha’,数据)

  • 解除绑定自定义事件this.$off(‘haha’)

  • 组件想使用原生的DOM事件(指原有的事件例如@click)需要使用native修饰符

全局事件总线

  • 安装全局事件总线

    //在main文件中
    new Vue({
        el: '#app',
        render: h => h(App),
        /* 
          在vue的实例对象对象上放置一个$bus来作为传输数据的对象
          $bus书写规范
        */
        beforeCreate() {
            Vue.prototype.$bus = this; //在vue的实例对象对象上放置一个$bus来作为传输数据的对象
        },
    })
    
  • 使用全局时间总线

    //绑定这个时间
    methods(){
        this.$bus.$emit('changeTodo', id)
    }
    //使用这个时间
    mounted(){
            this.$bus.$on('changeTodo', this.demo)
    }
     
    

消息订阅与发布

  • 安装第三方库 npm i pubsub-js

  • 引入: import pubsub from ‘pubsub-js’

    //发送数据
    sendStudentAge () {
          pubsub.publish('hello', 666)
    },
    //订阅(接受)数据
        mounted () {
        pubsub.subscribe('hello', (a, b) => {
          console.log('我是订阅函数,它的数据是' + a, b);
          console.log(this);
        })
      },
    

Vue动画

  • 元素准备样式

    • 元素进入

      v-enter:进入的起点

      v-enter-active:进入的过程

      v-enter-to:进入的终点

    • 元素的离开

      v-leave:进入的起点

      v-leave-active:进入的过程

      v-leave-to:进入的终点

  • 使用包裹过度的元素,并经行name配置

  • 如果有多个元素需要过度,则需要用,且每哥元素需要用key指定

配置代理

在vue.config.js中添加如下配置

    devServer: {
      proxy: {
        '/api': {//匹配有所以'/api'开头的路径
          target: 'http://localhost:8081',//代理请求的端口
          pathRewrite:{'^/api':''}//将第一个匹配的标识改为空
          ws: true,
          changeOrigin: true //告诉请求地址自己的路径,true代表和他的路径一样
        },
        '/foo': {
          target: ''
        }
      }
    }

插槽

在标签内部放入内容(默认插槽)

//输入内容 
<template>
  <div class="contain">
      //当需要指定位置的时候需要定义插槽标签
    <Category solt="center" title="美食" :listData="foods">
      <input type="text" value="我是小李子" />
    </Category>
  </div>
</template>

//告诉放置的位置,在Category中
<template>
  <div class="card">
    <h2>{{ title }}</h2>
    <ul>
      <li v-for="(item, index) in listData" :key="index">
        {{ item }}
      </li>
//定义插槽的名称,一一对应
      <slot name="center"></slot>
    </ul>
  </div>
</template>


作用域插槽

在components中

<template>
  <div class="card">
    <h2>{{ title }}</h2>
    <ul>
      <li v-for="(item, index) in listData" :key="index">
        {{ item }}
      </li>
      //从插槽中向调用插槽的传递数据
      <slot :games="games"></slot>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'Category',
  data() {
    return {
      games:['游戏1','游戏2','游戏3']
    }
  },
  props: ['title', 'listData']
}
</script>

调用插槽者

<template>
  <div class="contain">
    <Category title="美食" :listData="foods">
      <template scope='data'>//新版版为slot-scope
      <ul>
        <li v-for=" (g,index) in data.games" :key="index"></li>
      </ul>  
      </template>
    </Category>

  </div>
</template>

创建Vue脚手架

  • 下载node.js
  • 配置淘宝镜像
##窗口执行
npm install -g @vue/cli

Vue中的配置对象(以pages举例)

module.exports = {
  pages: {
    index: {
      // page 的入口
      entry: 'src/index/main.js',
      // 模板来源
      template: 'public/index.html',
      // 在 dist/index.html 的输出
      filename: 'index.html',
      // 当使用 title 选项时,
      // template 中的 title 标签需要是 <%= htmlWebpackPlugin.options.title %>
      title: 'Index Page',
      // 在这个页面中包含的块,默认情况下会包含
      // 提取出来的通用 chunk 和 vendor chunk。
      chunks: ['chunk-vendors', 'chunk-common', 'index']
    },
    // 当使用只有入口的字符串格式时,
    // 模板会被推导为 `public/subpage.html`
    // 并且如果找不到的话,就回退到 `public/index.html`。
    // 输出文件名会被推导为 `subpage.html`。
    subpage: 'src/subpage/main.js'
  }
}

ref属性

  1. 别用来给元素或子组件注册引用的信息(id的替换者)

  2. 应用在html标签上获取的真实DOM元素,应用在组件标签上的组件实例对象(vc)

  3. 使用方式

    打标识:

    或者…****

    获取:this.$refs.xxx

<template>
  <div>
    <h1 ref="title">点我展示上方元素</h1>
    <button @click="showDom">展示上方元素</button>
    <Add ref="add"></Add>
  </div>
</template>
<script>

import Add from './components/Add'

export default {
  name: 'App',
  components: { Add },
  methods: {
    showDom () {
      console.log(this.$refs.title);
      console.log(this.$refs);
      console.log(this.$refs.add);
    }
  },
}
</script>

props属性

//-------定义组件
<template>
  <div>
    <!-- 组件的结构 -->
    <h1>我的个人信息是</h1>
    <h2>学生名称:{{ name }}</h2>
    <h2>学生年龄:{{ age }}</h2>
    <h2>学生学校:{{ school }}</h2>
    ·
  </div>
</template> 
<script>
export default {
  name: 'student-name',
  // props: ['name', 'age', 'school'],第一种
  /*第二种   
  props: {
      name: String,
      age: Number,
      school: String
    }, */
  //对接受数据的同时对数据进行限制
  props: {
    name: {
      type: String,//类型String
      required: true,//必须要填写
    },
    age: {
      type: Number,
      default: 99
    },
    school: {
      type: String,//类型String
      required: true,//必须要填写
    }
  },
}
</script>
//----------使用组件
<template>
  <div>
    <student-name name="李华" :age="15" school="科技学院"></student-name>
  </div>
</template>
<script>
import StudentName from './components/Student.vue'
export default {
  name: 'App',
  components: {
    'student-name': StudentName
  }
}
</script>

功能:让组件接受外部传入的数据
备注:props是只读属性,Vue底层会检测你对props的修改,如果进行了修改,就会发出警报,若业务需要对数据的修改,那么请复制props的内容一份送到data中,让后去修改data中的数据

mixin(混入)

  • 功能:可以把多个组件共有的配置提供成一个混入对象

  • 使用方式:

    第一步定义混合
    {
    	data(){
    	
    	},
    	methods:{
    	
    	}
    }
    第二步使用混入
     (1)全局的混入,Vue.mixin(xx)
     (2)局部的混入,mixins:['xxx']
    
    //定义
    export const m = {
        methods: {
            showName() {
                alert(this.name)
            }
        },
        mounted() {
            console.log('你好啊')
        },
    }
    
    //使用
    <script>
    import { m,number } from "../mixin"
    export default {
      name: "xue-xiao",
      data () {
        return {
          // 传入的值不能修改
          name: "科技学院",
          address: "新乡市",
        }
      },
      mixins: [m,number]
    };
    </script>
    

plugin(插件)

  • 功能:用于增强Vue

  • 本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传入的数据。

    定义插件:

    export default {
        //shi'yong'hsi
        install(Vue, x) {
            console.log(x);//传入的参数,可以是多个
            Vue.filter('mySlice', function(value) {
                return value.slice(0, 5)
            })
            
            Vue.directive('fbind', {
            })
    
            //Vue混入方法
            Vue.mixin({
            })
            Vue.prototype.hello = () => {
            }
    
        }
    }
    

    使用插件

scoped样式

  • 多个模块中样式,当渲染时会进行汇总,此时如果模块中出现重复的样式名称则会冲突,代码采用就近原则按照后带入的为主
  • 作用:让样式是在局部生效,防止冲突
  • 写法>

vuex

概念:专门在Vue中实现集中式状态管理的一个Vue插件,对vue应用中多个组件的共享进行集中式的管理(读与写),依旧是一种通信的方式,且适用于任意组件间的通信

什么时候用(共享)

  • 多组件依赖于同一个状态
  • 来自不同组件的行为需要变更为同意状态

Vue2.0学习总结_第3张图片

路由

  • 使用路由

    //在main.js中
    import VueRouter from 'vue-router'
    import router from './router/index'//引入路由配置文件
    Vue.use(VueRouter)
    new Vue({
        el: '#app',
        render: (h) => h(App),
        router: router, //!!!!!
        beforeCreate() {
            Vue.prototype.$bus = this;
        }
    })
    
    
  • 配置路由(也可以用懒加载的方式)

    import VueRouter from 'vue-router'
    export default new VueRouter({
        routes: [
        	{//路由重定向
                path: '/',
                redirect: '/Login/User'
            },
            {
                path: '/Login',
                name: 'Login',
                component: Login,
                children: [{//子路由
                        path: 'User',
                        component: User
                    },
                    {
                        path: 'Register',//注意这里没有'/'
                        component: Register
                    },
                ]
            },
            {
                path: '/Todo/:name',
                name: 'Todo',
                component: Todo,
            },
        ]
    })
    
  • 路由标签

      <router-link to="/Login/User" class="select" active-class="active">登录区</router-link\>
    //标签最后会被解析为a标签
    //to为跳转的路径
    //active-class为选中当前路径标签所具有的样式
    <router-view></router-view>
    //可以展示选中标签中的nei'rong
    
  • 传递参数

    Params传参
    //一、声明式
    //子路由配置
    {
      path: '/child/:id',
      component: Child
    }
    //父路由组件
    <router-link :to="/child/123">进入Child路由</router-link>
    //二、编程式
    //子路由配置
    {
      path: '/child/:id',
      component: Child
    }
    //父路由编程式传参(一般通过事件触发)
    this.$router.push({
        path:'/child/${id}',//这里是es6表达方式
    })
    //三、对象传递(这种方式地址中不显示参数)
    <router-link :to="{name:'Child',params:{id:123}}">进入Child路由</router-link>
    //获取
    {{this.$route.params.id}}
    
    query传参
    //这种传参不需要更改路由配置
    //一、声明式
    {
      path: '/child',
      component: Child
    }
    <router-link :to="{path:'/child',query:{id:123}}">进入Child路由</router-link>
    //二、编程式
    this.$router.push({
        name:'Child',
        query:{
        	id:123
        }
    })
    //获取参数
    {{this.$route.query.id}}
    
  • 注意对象传参中path配query; name配params;!!!否则接收不到参数

  • 即使用params参数时,若使用to对象写法,则不能使用path配置项,必须使用name配置

  • 路由的两个钩子函数

    //路由仅有的两个钩子
    //当路由组件激活的时候触发(从没有到有)
    activated(){}
    //当路由组件失活的时候触发(从有到没有)
    deactivated(){}
    

路由器的两种工作模式

  • 对于一个url来说什么是hash值?——#以及后必拿的内容时hash值

  • hash值不会包含在http请求中,即:hash值不会带给服务器

  • hash模式:

    • 地址永远带着#号,不带美观
    • 若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法
    • 兼容性较好
  • history模式:

    • 地址干净,美观

    • 兼容性和hash模式相比略差

    • 应用部署上线时需要后端人员支持,解决页面服务器404的问题

       },
        {
            path: '/Todo/:name',
            name: 'Todo',
            component: Todo,
        },
      

      ]
      })

    
    
  • 路由标签

      <router-link to="/Login/User" class="select" active-class="active">登录区</router-link\>
    //标签最后会被解析为a标签
    //to为跳转的路径
    //active-class为选中当前路径标签所具有的样式
    <router-view></router-view>
    //可以展示选中标签中的nei'rong
    
  • 传递参数

    Params传参
    //一、声明式
    //子路由配置
    {
      path: '/child/:id',
      component: Child
    }
    //父路由组件
    <router-link :to="/child/123">进入Child路由</router-link>
    //二、编程式
    //子路由配置
    {
      path: '/child/:id',
      component: Child
    }
    //父路由编程式传参(一般通过事件触发)
    this.$router.push({
        path:'/child/${id}',//这里是es6表达方式
    })
    //三、对象传递(这种方式地址中不显示参数)
    <router-link :to="{name:'Child',params:{id:123}}">进入Child路由</router-link>
    //获取
    {{this.$route.params.id}}
    
    query传参
    //这种传参不需要更改路由配置
    //一、声明式
    {
      path: '/child',
      component: Child
    }
    <router-link :to="{path:'/child',query:{id:123}}">进入Child路由</router-link>
    //二、编程式
    this.$router.push({
        name:'Child',
        query:{
        	id:123
        }
    })
    //获取参数
    {{this.$route.query.id}}
    
  • 注意对象传参中path配query; name配params;!!!否则接收不到参数

  • 即使用params参数时,若使用to对象写法,则不能使用path配置项,必须使用name配置

  • 路由的两个钩子函数

    //路由仅有的两个钩子
    //当路由组件激活的时候触发(从没有到有)
    activated(){}
    //当路由组件失活的时候触发(从有到没有)
    deactivated(){}
    

路由器的两种工作模式

  • 对于一个url来说什么是hash值?——#以及后必拿的内容时hash值
  • hash值不会包含在http请求中,即:hash值不会带给服务器
  • hash模式:
    • 地址永远带着#号,不带美观
    • 若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法
    • 兼容性较好
  • history模式:
    • 地址干净,美观
    • 兼容性和hash模式相比略差
    • 应用部署上线时需要后端人员支持,解决页面服务器404的问题

你可能感兴趣的:(vue.js,学习,javascript)