【Vue全家桶】--- 第一章:Vue核心

文章目录

  • Vue技术栈(全家桶)
  • 第一章:Vue核心
    • 1.1、`Vue`简介
      • 1.1.1、官网
      • 1.1.2、介绍与描述
      • 1.1.3、`Vue`的特点
      • 1.1.4、与其它js框架的关联
      • 1.1.5、Vue周边库
    • 1.2、`初识Vue`
    • 1.3、`模板语法`
      • 1.3.1、效果
      • 1.3.2、模板的理解
      • 1.3.3、`插值语法`
      • 1.3.4、`指令语法`
    • 1.4、`数据绑定`
      • 1.4.1、效果
      • 1.4.2、```单向数据绑定```
      • 1.4.3、`双向数据绑定`
      • 1.4.4、`data`与`el`的两种写法
    • 1.5、`MVVM`模型
    • 1.6、`数据代理`
    • 1.7、`事件处理`
      • 1.7.1、基本使用
      • 1.7.2、`绑定监听`
      • 1.7.3、`事件修饰符`
      • 1.7.4、`键盘事件`
    • 1.8、`计算属性`与`监视`
      • 1.8.1、效果
      • 1.8.2、计算属性-`computed`
      • 1.8.3、监视属性-`watch`
      • 1.8.4、`深度监视`
      • 1.8.5、`计算属性与监视区别`
    • 1.9、`class`与`style`绑定
      • 1.9.1、理解
      • 1.9.2、`class绑定`
      • 1.9.3、`style绑定`
    • 1.10、`条件渲染`
      • 1.10.1、条件渲染指令
      • 1.10.2、比较`v-if`与`v-show`
    • 1.11、`列表渲染`
      • 1.11.1、`列表显示指令`
      • 1.11.2、面试题:`key`实现原理
      • 1.11.3、`列表过滤`
      • 1.11.4、`Vue监视data中所有的层次的数据`
    • 1.12、`收集表单数据`
    • 1.13、`过滤器`
    • 1.14、`内置指令`与`自定义指令`
      • 1.14.1、常用内置指令
      • 1.14.2、`自定义指令`
    • 1.15、`Vue实例生命周期`
      • 1.15.1、`生命周期流程图`
      • 1.15.2、`Vue生命周期分析`
      • 1.15.3、`常用的生命周期方法`
      • 1.15.4、`销毁Vue实例`

Vue技术栈(全家桶)

第一章:Vue核心

1.1、Vue简介

1.1.1、官网

  1. 英文官网: https://vuejs.org/

  2. 中文官网: https://cn.vuejs.org/

1.1.2、介绍与描述

  1. 动态构建用户界面的渐进式 JavaScript 框架

  2. 作者: 尤雨溪

1.1.3、Vue的特点

  1. 遵循 MVVM 模式

  2. 编码简洁, 体积小, 运行效率高, 适合移动/PC 端开发

  3. 它本身只关注UI, 也可以引入其它第三方库开发项目

1.1.4、与其它js框架的关联

  1. 借鉴Angular 的模板数据绑定技术

  2. 借鉴React 的组件化虚拟 DOM 技术

1.1.5、Vue周边库

  1. vue-cli: vue 脚手架

  2. vue-resource

  3. axios

  4. vue-router: 路由

  5. vuex: 状态管理

  6. element-ui: 基于vue 的UI 组件库(PC 端)

​ ……

1.2、初识Vue

关闭生产提示:

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

【Vue全家桶】--- 第一章:Vue核心_第1张图片
【Vue全家桶】--- 第一章:Vue核心_第2张图片

例:

初识Vue:

1.想让Vue工作,必须创建一个Vue实例,却要传入一个配置对象

2.root容器里的代码依然符合HTML规范,只不过混入了一些特殊的Vue语法;

3.root容器里的代码被称为【Vue模板】

4.Vue实例和容器一一对应;

5.真实开发中只有一个Vue实例,并且会配合组件一起使用

6.{{xxx}}中要写js表达式,且xxx可以自动读取到data中所有的属性;

7.一旦data中的数据发生改变,那么模板中拿到的数据的地方也会自动更新;

注意区分:js表达式和js代码(语句)

1.表达式:一个表达式会生成一个值,可以方法任何需要的值的对方

(1) a

(2) a+b

(3) demo(1)

(4) x===y?‘a’:‘b’

2.js代码(语句)

(1) if(){}

(2) for(){}

<div id="root">
    <h1>hello,{{name}}h1>
div>

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

    //创建Vue实例
    const x = new Vue({// const x=  可以省略
        //el:document.getElementById('root');  经典写法
        el: '#root', //el用于指定当前Vue实例为那个容器服务,值通常为css选择器字符串
        //el:'.root'//表示选中class属性
        data: {  //data中用于存储数据,数据供el所指定的容器中使用,值我们暂时先写成一个对象
            name: '小王'
        }
    });
script>

1.3、模板语法

1.3.1、效果

<div class="root">
    <h1>插值语法h1>
    <h3>你好,{{name}}h3>
    <hr/>
    <h1>指令语法:h1>
    <a v-bind:href="url">点我去尚硅谷学习1a>
    <a :href="school.url" >点我去尚硅谷学习2a>
div>
<script type="text/javascript">
    Vue.config.productionTip = false;//设置为 false 以阻止 vue 在启动时生成生产提示。

    //创建Vue实例
    const x = new Vue({// const x=  可以省略
        //el:document.getElementById('root');  经典写法
        el: '.root', //el用于指定当前Vue实例为那个容器服务,值通常为css选择器字符串
        //el:'.root'//表示选中class属性
        data: {  //data中用于存储数据,数据供el所指定的容器中使用,值我们暂时先写成一个对象
            name: '小王Hello',
            url:'http://www.atguigu.com',
            school:{
                url:'http://www.atguigu.com'
            }
        }
    });
script>

【Vue全家桶】--- 第一章:Vue核心_第3张图片

1.3.2、模板的理解

html 中包含了一些JS 语法代码,语法分为两种,分别为:

  1. 插值语法(双大括号表达式)

  2. 指令(以v-开头)

1.3.3、插值语法

  1. 功能: 用于解析标签体内容

  2. 语法: {{xxx}} ,xxxx 会作为js 表达式解析

1.3.4、指令语法

1.功能: 解析标签属性、解析标签体内容、绑定事件

  1. 举例:v-bind:href=“xxx” 或简写成 :href=“xxx” ,xxx同样要写成js表达式

    且可以直接读取到data中的所有属性

  2. 说明:Vue中有很多指令,却形式都是v-???,此处我们只使用的是v-bind举个例子

1.4、数据绑定

分为 单向数据绑定、双向数据绑定

1.4.1、效果


单向数据的绑定:<input type="text" v-bind:value="name"><br>
双向数据的绑定:<input type="text" v-model:value="name"><br>

单向数据的绑定:<input type="text" :value="name"><br>
双向数据的绑定:<input type="text" v-model="name">


<script type="text/javascript">
    Vue.config.productionTip = false;//设置为 false 以阻止 vue 在启动时生成生产提示。
    new Vue({
        el: '#root',
        data: {
            name: '小王'
        }
    });
script>

【Vue全家桶】--- 第一章:Vue核心_第4张图片

1.4.2、单向数据绑定

  1. 语法:v-bind:href =“xxx” 或简写为 :href

  2. 特点:数据只能从data 流向页面

1.4.3、双向数据绑定

  1. 语法:v-mode:value=“xxx” 或简写为 v-model=“xxx”,因为v-model默认收集的是value的值

  2. 特点:数据不仅能从data 流向页面,还能从页面流向 data,双向绑定一般都应用在表单元素上(如:input、select等)

1.4.4、datael的两种写法

1.el有两种写法

(1)new Vue的时候配置el属性

(2)先创建一个Vue实例 “const v = new Vue({})”,而后再通过v.$mount("#root")指定el的值

2.data有两中写法

(1)对象式

(2)函数式

如何选择:目前写那个都可以,以后学习组件是,data必须使用函数式,否则会报错

3.一个重要原则

由Vue管理的函数,一定不要写箭头函数,一旦写成了箭头函数,this就不在是Vue实例了

el

//el的两种写法:
//        第一种常规 可以写成 new Vue({})
//        第二种使用v.$mount("#xxx");
const v =  new Vue({
    //el: '#root',
    data: {
        name: '小王'
    },
    success: (result) => {
        console.log('方法名 success', result);
    }
});
v.$mount("#root");//第二种写法 

data

//data的两种写法:
//     第一种:对象式
//     第二种:函数式  简化写法 data(){}
new Vue({
    el: '#root',
    //data的第一种写法:对象式
    /*  data: {

             }, */
    //data 的第二种写法:函数式 简化写法 data(){}
    data: function () {
        //console.log("@@@",this);
        return {
            name: '小王'
        }
    }
});

1.5、MVVM模型

  1. M:模型(Model) :对应data 中的数据

  2. V:视图(View) :模板

  3. VM:视图模型(ViewModel) : Vue 实例对象

【Vue全家桶】--- 第一章:Vue核心_第5张图片

观察发现:

1.data中的所有属性,最后都出现在vm身上。

2.vm身上所有的属性,及Vue原型上所有的属性,在Vue模板中都可以直接使用

测试1:{{$options}}

【Vue全家桶】--- 第一章:Vue核心_第6张图片

1.6、数据代理

Object.defineProperty

1.Vue中的数据代理:

​ 通过vm对象来代理data对象中的属性的操作(读/写)

2.Vue中的数据代理的好处:

​ 更加方便的操作data中的数据

3.基本原理:

​ 通过Object.defineProoperty()把data对象中所有的属性添加到vm上

​ 为每一个添加到vm上的属性,都指定一个getter/setter.

​ 在getter/setter内部去操作(读/写)data中对应的属性

【Vue全家桶】--- 第一章:Vue核心_第7张图片

例:

<script type="text/javascript">
    Vue.config.productionTip = false;//设置为 false 以阻止 vue 在启动时生成生产提示。
let number = 18;
let person = {
    name: '小王',
    sex: '男'
}
Object.defineProperty(person, 'age', {

    // value: 18,
    // enumerable: true, //控制属性是否可以枚举,默认值是false
    // writable:true, //控制器属性是否可以被修改,默认值是false
    // configurable:true//控制器属性是否可以被删除,默认值是false

    //当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
    get: function () {
        console.log("有人读取数据");
        return number
    },

    //当有人修改person的age属性时,gset函数(setter)就会被调用,且会收到修改的具体值
    set(value){
        console.log("有人修改了age属性,且值是:",value);
        number = value;
    }
});
console.log(person);
console.log(Object.keys(person));
/* for (const key in person) {
            console.log("@@@", person[key]);
        } */
</script>

1.7、事件处理

1.7.1、基本使用

​ 1.使用v-on:xxx@xxx绑定事件,其中xxx为事件名

​ 2.事件的回调需要配置在methods对象中,最终会在vm上

​ 3.methods中配置的函数,不要使用箭头函数!否则this就不是vm了

​ 4.methods中配置的函数,都是被Vue所管理的函数,this的指向是vm或组件实例对象

​ 5.@click = “demo” 和**@click = “demo($event)”**效果一直,但后者可以进行传参

事例:点击事件

<div id="root">
    <h1>欢迎来到{{name}}学习h1>
    <button v-on:click="showInfo1">点我提示信息1:不传参button>
    <button @click="showInfo2(66,$event)">点我提示信息2:传参button>
div>
<script type="text/javascript">
    Vue.config.productionTip = false;//设置为 false 以阻止 vue 在启动时生成生产提示。

    const vm = new Vue({
        el: '#root',
        data: {
            name: '尚硅谷'
        },
        methods: {
            //不传参
            showInfo1(event) {
                console.log(event.target.innerText);
                console.log(this);
                alert("同学你好")
            },
            //传参
            showInfo2(number,a) {
                // console.log(event.target.innerText);
                // console.log(this);
                console.log(number,a);
                alert("同学你好!!")
            }
        }
    });
script>

1.7.2、绑定监听

  1. v-on:xxx=“fun” (fun)方法名

  2. @xxx=“fun”

  3. @xxx=“fun(参数)”

  4. 默认事件形参: event

  5. 隐含属性对象: $event

1.7.3、事件修饰符

常规方式@click="xxx"

Vue方式@click.stop="xxx"

​ xxx:方法名 .stop:阻止事件冒泡的事件修饰符

Vue中的事件修饰符:

1.prevent:阻止默认事件(常用)

​ 例:@click.prevent="xxx"

​ 常规:@click=“xxx” e.preventDefault();//阻止默认行为

2.stop:阻止事件冒泡(常用)

​ 例:@click.stop="xxx"

​ 常规:@click=“xxx” e.stopPropagation();//阻止事件冒泡

3.once:事件只触发一次(常用)

​ 4.capture:使用事件的捕获模式

​ 5.self:只有event.target是当前操作的元素时才触发事件

​ 6.passive:事件默认行为立即执行,无需等待事件回调执行完毕

联合使用:

​ 例:@click.prevent.stop="xxx"

​ 表示先阻止默认行为,再阻止事件冒泡

例:

<div id="root">
    <h1>欢迎来到{{name}}学习h1>
    <a href="http://www.atguigu.com" @click="showInfo">点击提示信息a><br>
    
    <a href="http://www.atguigu.com" @click.prevent="showInfo">prevent:阻止默认事件(常用)a><br>

    
    <div class="demo1" @click="showInfo">
        <button @click.stop="showInfo">stop:阻止事件冒泡(常用)button>
    div>

    
    <button @click.once="showInfo">once:事件只触发一次(常用)button>

    
    
    <div class="box1" @click.capture="showMsg(1)">
        div1
        <div class="box2" @click="showMsg(2)">
            div2
        div>
    div>

    
    <div class="demo1" @click.self="showInfo">
        <button @click="showInfo">self:只有event.target是当前操作的元素时才触发事件button>
    div>

    
    
    <ul @wheel.passive="demo" class="list">
        <li>1li>
        <li>2li>
        <li>3li>
        <li>4li>
    ul>

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

    const vm = new Vue({
        el: '#root',
        data: {
            name: '尚硅谷'
        },
        methods: {
            showInfo(e) {
                //e.preventDefault();//阻止默认行为
                //e.stopPropagation();//阻止事件冒泡
                alert("同学你好");
                // console.log(e.target);
            },
            showMsg(msg) {
                console.log("同学你好" + msg)
            },
            demo(msg) {
                for (let index = 0; index < 1000; index++) {
                    console.log("#");

                }
                console.log("累坏了");
            }
        }
    });
script>

1.7.4、键盘事件

键盘事件:

@keydown:按下即触发

@keyup:按下松手触发

常规方式:使用键盘的keycode值

​ @keydown=“showInfo” 通过 if(e.keyCode!=13)来进行判断

​ 此时为”Enter”事件,

1.Vue中的常用的按键的别名:

​ 回车 => enter

​ 删除 => delete (捕获 ”删除” 和 ”退格” 键)

​ 退出 => esc

​ 空格 => space

​ 换行 => tab 本身比较特殊,可以切换焦点 ,@keyup不建议使用,可以使用@keydown.tab

​ 上 => up

​ 下 => down

​ 左 => left

​ 右 =>right

​ 2.Vue未提供别名的按键,可以使用按键原始的key的值进行绑定,但是注意要转换为 kebab-case(短横线命名)

​ 3.系统修饰键(特殊):Ctrl、alt、shift、meta(win键)

​ (1)配合keyup使用:按下修饰键的同时,再按下其它键,随后释放其他键,事件才被触发

​ (2)配合keydown使用:正常触发事件

​ 4.也可以使用keyCode去指定具体的按键(不推荐),不同键盘,按键的keyCode可能不同

​ 5.Vue.config.keyCodes.自定义键名 = 键码 ,可以去定制按键别名

@keydown.huiche=“showInfo” Vue.config.keyCodes.huiche = 13; //定义可一个别名按键

例:


<div id="root">
    <h1>欢迎来到{{name}}学习h1> 
    
    <input type="text" placeholder="按下回车提示输入" @keydown.huiche="showInfo">
div>
<script type="text/javascript">
    Vue.config.productionTip = false;//设置为 false 以阻止 vue 在启动时生成生产提示。
    Vue.config.keyCodes.huiche = 13; //定义可一个别名按键
    const vm = new Vue({
        el: '#root',
        data: {
            name: '尚硅谷'
        },
        methods: {
            showInfo(e) {
                // console.log(e.keyCode);//键盘上对应的code值
                /*   if(e.keyCode!=13){
                          return
                      } */
                //第二种方式:@keyup.enter
                //console.log(e.target.value);
                console.log(e.key)
            }
        }

    });
script>

1.8、计算属性监视

1.8.1、效果

问题:通过输入”姓”和”名”来组合成为”全名”

要求:”全名”是”姓”-”名” 实现动态变化

【Vue全家桶】--- 第一章:Vue核心_第8张图片

方式一:插值语法实现

缺点:需求过多时,不便于观察

<div id="root">
    性: <input type="text" v-model="firstName"><br><br>
    名: <input type="text" v-model="lastName"><br><br>
    
    姓名: <span>{{firstName.slice(0,3)}}-{{lastName}}span>
div>
<script type="text/javascript">
    Vue.config.productionTip = false;//设置为 false 以阻止 vue 在启动时生成生产提示。
    new Vue({
        el:'#root',
        data: {
            firstName:'张',
            lastName:'三'
        }
    });
script>

方式二:methods实现

注意:

  • methods中fullName的this属性指的是vm,如果fullName使用箭头函数,则this指windows

  • span标签中花括号内方法的名字必须带括号”()” ====》 {{fullName()}}

<div id="root">
    性: <input type="text" v-model="firstName"><br><br>
    名: <input type="text" v-model="lastName"><br><br>
    姓名: <span>{{fullName()}}span>
div>
<script type="text/javascript">
    Vue.config.productionTip = false;//设置为 false 以阻止 vue 在启动时生成生产提示。
    new Vue({
        el:'#root',
        data: {
            firstName:'张',
            lastName:'三'
        },
        methods:{
            fullName(){
                return this.firstName+'-'+this.lastName
            }
        }

    });
script>

方式三:计算属性实现

1.8.2、计算属性-computed

描述:

1.要显示的数据不存在,要通过计算的来

2.要在computed对象中定义计算属性

3.在页面中使用{{方法名}}(方法名后没有小括号”()”)来显示计算的结果

原理及优势:

1.原理:底层借助了Object.defineproperty方法提供的getter和setter

2.get函数什么时候执行?

​ (1)初次读取时会执行一次

​ (2)当依赖的数据发生改变时会被再次调用

get函数又什么作用?

​ 当有人读取fullName是,get就会被调用,且返回值作为fullName的值

set 什么时候调用?

​ 当fullName被修改时

3.优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便

4.备注:

​ (1)计算属性最终会在vm上,直接读取使用即可

​ (2)如果计算属性要被修改,那么必须写set函数去响应修改,且set中要引起计算式依赖的数据发生改变

普通写法与简写

普通写法:xxx方法名

computed:{
    xxx:{
        get(){
           return ....操作....
        },
        set(value){
        }
}

简写:xxx方法名

注意要点:

使用简写方式前提:确定不写”set”方法(不做修改),简写为xxx: function () {}默认执行方法名中内容,不需要有get方法。

里面更简写方式: xxx() {}

computed: {
    /*  xxx: function () {
                  return  .....
                } */
    xxx() {
        return .....
    }
}

例:

<div id="root">
    性: <input type="text" v-model="firstName"><br><br>
    名: <input type="text" v-model="lastName"><br><br>
    姓名: <span>{{fullName}}span><br><br>  //后面再有{{fullName}} 也是读取一遍,methods会反复取
    
div>
<script type="text/javascript">
    Vue.config.productionTip = false;//设置为 false 以阻止 vue 在启动时生成生产提示。
    const vm =  new Vue({
        el:'#root',
        data: {
            firstName:'张',
            lastName:'三'
        },
        //计算属性 拥有缓存,读取一次,然后从缓存中读取
        computed:{
            fullName:{
                //get 有什么作用?当有人读取fullName是,get就会被调用,且返回值作为fullName的值
                //get 什么时候被调用?1.初次读取fullName时  2.所依赖的数据发生改变时
                get(){
                    //console.log(this)  此处的this是vm
                    return this.firstName+'-'+this.lastName

                },
                //set 什么时候调用? 当fullName被修改时
                set(value){
                    console.log(value)
                    const arr = value.split('-')
                    this.firstName = arr[0]
                    this.lastName = arr[1]
                }
            }
        }

    });
script>

1.8.3、监视属性-watch

监视属性watch:

​ 1.当被监视的属性发生变化时,回调函数自动调用(handler),进行相关的操作

​ 2.监视的属性必须存在,才能进行监视!!

​ 3.监视的两种写法:

​ (1)new Vue时传入watch配置

​ (2)通过vm.$watch监视 ,特别注意:监视的data或computed中的方法需要加引号(’ ’)

immediate:true,//初始化时让handler调用一下

两种监视写法的简写模式:

**注意:**简写方式不能配置其中的属性。

如:immediate:true,//初始化时让handler调用一下

deep:true,//深度监视开启

第一种:

watch: {
   isHot(newValue,oldValue) {
       console.log("isHot被修改了",newValue,oldValue)
}

第二种:

vm.$watch('isHot',function (newValue, oldValue) {
   console.log("isHot被修改了", newValue, oldValue)
})

例子:通过button的点击事件,来改变”文字”

比如:”今天天气很凉爽” 点击后===》”今天天气很炎热”

【Vue全家桶】--- 第一章:Vue核心_第9张图片

方式一:使用computed计算属性值+methods点击事件

也可以使用三元运算符:

{{isHot?‘炎热’:‘凉爽’}}

<div id="root">
    
    <h2>今天天气很{{info}}h2>
    <button @click="changeWeather">切换天气button>
    
    
div>
<script type="text/javascript">
    Vue.config.productionTip = false;//设置为 false 以阻止 vue 在启动时生成生产提示。
    const vm =  new Vue({
        el:'#root',
        data: {
            isHot:true
        },
        //计算属性
        computed:{
            info(){
                return this.isHot?'炎热':'凉爽'
            }
        },
        //方法
        methods: {
            changeWeather(){
                this.isHot = !this.isHot
            }
        },

    });

script>

方式二:监视属性watch

:监视的两种写法

<div id="root">
    <h2>今天天气很{{info}}h2>
    <button @click="changeWeather">切换天气button>

div>
<script type="text/javascript">
    Vue.config.productionTip = false;//设置为 false 以阻止 vue 在启动时生成生产提示。
    const vm = new Vue({
        el: '#root',
        data: {
            isHot: true
        },
        computed: {
            info() {
                return this.isHot ? '炎热' : '凉爽'
            }
        },
        methods: {
            changeWeather() {
                this.isHot = !this.isHot
            }
        },
        //第一种方式
        /* watch:{
                isHot:{// 还可监视computed中的info方法
                    immediate:true,//初始化时让handler调用一下
                    //handler什么时候被调用?当isHot发生改变时
                    handler(newValue,oldValue){
                        console.log("isHot被修改了",newValue,oldValue)
                    }
                }
            } */

    });
    //第二种方式
    vm.$watch('isHot', {
        immediate: true,//初始化时让handler调用一下
        //handler什么时候被调用?当isHot发生改变时
        handler(newValue, oldValue) {
            console.log("isHot被修改了", newValue, oldValue)
        }
    })
script>

1.8.4、深度监视

深度监视:

​ (1)Vue中的watch默认不监视对象内部的变化(一层)

​ (2)配置deep:true可以监视对象内部值改变(多层)

​ 备注:

​ (1)Vue自身可以监视对象内部值的改变,但Vue提供的watch默认不可以

​ (2)使用watch是根据数据的具体结构,决定是否采用深度监视

例:

  • 监视多级结构中的某个属性的变化
  • 监视多级结构中所有属性的变化
<div id="root">
    <h2>今天天气很{{info}}h2>
    <button @click="changeWeather">切换天气button>
    <hr>
    <h3>a的值时:{{numbers.a}}h3>
    <button @click="numbers.a++">点我让a+1button>
    <hr>
    <h3>a的值时:{{numbers.b}}h3>
    <button @click="numbers.b++">点我让b+1button>
    <button @click="numbers={a:666,b:888}">彻底替换掉numbersbutton>
div>
<script type="text/javascript">
    Vue.config.productionTip = false;//设置为 false 以阻止 vue 在启动时生成生产提示。
    const vm = new Vue({
        el: '#root',
        data: {
            isHot: true,
            numbers:{
                a:1,
                b:1 
            }
        },
        computed: {
            info() {
                return this.isHot ? '炎热' : '凉爽'
            }
        },
        methods: {
            changeWeather() {
                this.isHot = !this.isHot
            }
        },
        watch:{

            //监视多级结构中的某个属性的变化
            /*  'numbers.a':{
                    handler(){
                        console.log("a被改变了")
                    }

                } */
            //监视多级结构中所有属性的变化
            numbers:{
                deep:true,//深度监视开启
                handler(){
                    console.log("numbers改变了")
                }
            }
        }

    });

script>

1.8.5、计算属性与监视区别

computed和watch之间的区别:

​ 1.computed能完成的功能,watch都可以完成

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

​ 两个重要的小原则:

​ 1.所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象

​ 2.所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数),最好写成箭头函数

例:实现1.8.1节的姓名案例

需求增加:在输入姓的时候,全名延迟一秒实现,此时只能使用watch监视实现

watch监视实现

<div id="root">
    性: <input type="text" v-model="firstName"><br><br>
    名: <input type="text" v-model="lastName"><br><br>
    姓名: <span>{{fullName}}span><br><br>
div>
<script type="text/javascript">
    Vue.config.productionTip = false;//设置为 false 以阻止 vue 在启动时生成生产提示。
    const vm = new Vue({
        el: '#root',
        data: {
            firstName: '张',
            lastName: '三',
            fullName:'张-三'//此处比计算属性多个fullName
        },
        watch:{
            firstName(newValue){ 
                //延迟一秒
                setTimeout(() => {
                    this.fullName = newValue+'-'+this.lastName 
                }, 1000);
            },
            lastName(newValue){
                this.fullName = this.firstName+'-'+newValue
            }
        }

    });
script>

1.9、classstyle绑定

1.9.1、理解

  1. 在应用界面中, 某个(些)元素的样式是变化的

  2. class/style 绑定就是专门用来实现动态样式效果的技术

1.9.2、class绑定

写法 :class = “xxx” xxx可以使字符串、对象、数组

  • 字符串写法适用于:类名不确定,要动态获取。 例:data中,下同==》xxx:‘格式’
  • 对象写法适用于:要绑定多个样式,个数不确定,名字也不确定。xxx:[‘格式1’,‘格式2’]
  • 数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定是否使用。xxx:{格式1:false,格式2:false}

1.9.3、style绑定

对象写法

  1. :style="{ color: activeColor, fontSize: fontSize + ‘px’ }"

​ 其中activeColor/fontSize 是data 属性

  1. :style=" styleObj"

data中 styleObj:{fontSize:’40px’}

数组写法

  1. :style=" [styleObj1,styleObj2]" data中 styleObj1:xxx,styleObj2:xxx

1.10、条件渲染

1.10.1、条件渲染指令

  1. v-if 与v-else-if、v-else

  2. v-show

1.10.2、比较v-ifv-show

1.v-if

​ 写法:

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

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

​ (3)v-else v-else不需要跟条件,有==无

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

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

​ 注意:v-if可以和v-else-if、v-else一起使用,但要求结构不能被破坏

​ 2.v-show

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

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

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

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

注意:template与只能和if的配合使用


<template v-if="n===1">
    <h2 >你好h2>
    <h2 >平顶山h2>
    <h2 >小王h2>
template>

1.11、列表渲染

【Vue全家桶】--- 第一章:Vue核心_第10张图片

1.11.1、列表显示指令

v-for指令

​ 1.用于展示列表数据

​ 2.语法:1️⃣ v-for="(p,index) in xxx" :key=“yyy” 或 v-for=“p in persons” :key=“p.id”

​ 2️⃣ in 可以换成of

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

代码事例:

<div id="root">
    
    <h2>人员列表h2>
    <ul>
        
        <li v-for="(p,index) in persons" :key="index">
            {{p.name}}-{{p.age}}--{{index}}
        li>
    ul>

    
    <h2>汽车信息h2>
    <ul>

        <li v-for="(value,k) in car" :key="k" >
            {{k}}--{{value}}
        li>
    ul>

    
    <h2>遍历字符串h2>
    <ul>

        <li v-for="(char,index) in str" :key="index" >
            {{char}}--{{index}}
        li>
    ul>

    
    <h2>遍历指定次数h2>
    <ul>

        <li v-for="(number,index) in 5" :key="index">
            {{number}}--{{index}}
        li>
    ul>
div>
<script type="text/javascript">
    Vue.config.productionTip = false;//设置为 false 以阻止 vue 在启动时生成生产提示。
    new Vue({
        el: '#root',
        data: {
            persons: [
                { id: '001', name: '张三', age: 10 },
                { id: '002', name: '李四', age: 12 },
                { id: '003', name: '王五', age: 13 }
            ],
            str:'hello',
            car: {
                name: '奥迪',
                price: '80w',
                color: '黑色'
            }
        }
    });
script>

1.11.2、面试题:key实现原理

面试题:react、vue中的key有什么作用?(key的内部原理)

​ 1.虚拟DOM中的key的作用:

​ key是虚拟机DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】

​ 随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:

​ 2.对比规则:

​ (1)旧虚拟DOM中找到了与新虚拟DOM相同的key:

​ 1.若虚拟DOM中内容没变,直接使用之前的真是DOM

​ 2.若虚拟DOM中内容变了,则生成新的真是DOM,随后替换掉页面中之前的真是DOM

​ (2)旧虚拟DOM中未找到与新虚拟DOM相同的key

​ 创建新的真是DOM,随后渲染到页面

​ 3.用index作为key可能引发的问题:

​ 1.若对数据进行:逆序添加,逆序删除等破坏顺序操作;

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

​ 2.如果结构中还包含输入类的DOM:

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

​ 4.开发中如何选择key?

​ 1.最后使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值

​ 2.如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示

​ 使用index作为key是没有问题

遍历列表时key的作用(index作为key)

【Vue全家桶】--- 第一章:Vue核心_第11张图片

遍历列表时key的作用(id作为key)

【Vue全家桶】--- 第一章:Vue核心_第12张图片

1.11.3、列表过滤

【Vue全家桶】--- 第一章:Vue核心_第13张图片

两种实现方式:使用watch实现、使用computed实现



<div id="root">
    
    <h2>人员列表h2>
    <input type="text" placeholder="请输入名字" v-model="keyWord">
    <ul>
        <li v-for="(p,index) in filPersons" :key="index">
            {{p.name}}-{{p.age}}--{{index}}
        li>
    ul>
div>
<script type="text/javascript">
    Vue.config.productionTip = false;//设置为 false 以阻止 vue 在启动时生成生产提示。
    //使用watch实现
    /*  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: '男' }
                 ],
                 filPersons: []
             },
             watch: {
                 keyWord: {
                     immediate:true,
                     handler(value) {
                         this.filPersons = this.persons.filter((p) => {
                             return p.name.indexOf(value) !== -1//判断是否包含,不包含则返回-1
                         })
                     }
                 }
             }
         }); */

    //用computed,优先使用
    new Vue({
        el: '#root',
        data: {
            keyWord: '',
            sortType: 0,//0代表原顺序,1代表降序,2代表升序 @click=""
            persons: [
                { id: '001', name: '马冬梅', age: 20, sex: '女' },
                { id: '002', name: '周冬雨', age: 19, sex: '女' },
                { id: '003', name: '周杰伦', age: 18, sex: '男' },
                { id: '004', name: '温兆伦', age: 22, sex: '男' }
            ]
        },
        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 === 1 ? p2.age - p1.age : p1.age - p2.age
                    })
                    console.log(arr)
                }
                return arr
            }
        }
    });
script>

1.11.4、Vue监视data中所有的层次的数据

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

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

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

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

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

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

​ Vue.set(taget,propertyName/index,value)或

​ vm.$set(target,propertyName/index,value)

​ 3.如何监视数组中的数据?

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

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

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

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

​ (1)是用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()

​ (2)Vue.set()或vm.$set()

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

例:

【Vue全家桶】--- 第一章:Vue核心_第14张图片

<div id="root">
    <h1>学生信息h1>

    <button @click="student.age++">年龄+1岁button><br/>
    <button @click="addSex">添加性别属性,默认值:男button><br/>
    <button @click="student.sex = '未知'">修改性别button><br/>
    <button @click="addFriend">在列表首位添加一个朋友button><br/>
    <button @click="updateFirstFriendName">修改第一个朋友的名字为:张三button><br/>
    <button @click="addHobby">添加一个爱好button><br/>
    <button @click="updateHobby">修改第一个爱好为:开车button><br/>
    <button @click="removeSmoke">过滤掉爱好中的抽烟button><br/>


    <h3>姓名:{{student.name}}h3>
    <h3>年龄:{{student.age}}h3>
    <h3 v-if="student.sex">性别:{{student.sex}}h3>
    <h3>爱好:h3>
    <ul>
        <li v-for="(h,index) in student.hobby" :key="index">
            {{h}}
        li>
    ul>
    <h3>朋友们:h3>
    <ul>
        <li v-for="(f,index) in student.friends" :key="index">
            {{f.name}}--{{f.age}}
        li>
    ul>
div>
<script type="text/javascript">
    Vue.config.productionTip = false;//设置为 false 以阻止 vue 在启动时生成生产提示。

    new Vue({
        el:'#root',
        data: {
            student: {
                name: '小王',
                age: 15,
                hobby: ['抽烟', '烫头', '喝酒'],
                friends: [
                    {name:'jerry',age:45},
                    {name:'tony',age:20}
                ]
            },
        },
        methods: {
            addSex(){
                //Vue.set(this.student,'sex',"男")
                this.$set(this.student,'sex',"男")
            },
            addFriend(){
                this.student.friends.unshift({name:'jack',age:44})
            },
            updateFirstFriendName(){
                this.student.friends[0].name = '张三'
            },
            addHobby(){
                this.student.hobby.push('学习')
            },
            updateHobby(){
                //this.student.hobby.splice(0,1,'开车')
                //Vue.set(this.student.hobby,0,'开车')
                this.$set(this.student.hobby,0,'开车')
            },
            removeSmoke(){
                this.student.hobby= this.student.hobby.filter((h)=>{
                    //函数体
                    return h!=='抽烟'
                })
            }
        },
    });

script>

1.12、收集表单数据

收集表单数据:

​ 若:,则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:失去焦点再收集数据 与textarea配合使用

例:

【Vue全家桶】--- 第一章:Vue核心_第15张图片

<div id="root">
    <form @submit.prevent="demo">
        <label for="account">账号:label>
        <input id="account" type="text" v-model.trim="userInfo.account"><br /><br />
        <label for="pwd">密码:label>
        <input id="pwd" type="text" v-model.trim="userInfo.pwd"><br /><br />
        年龄:<input type="number" v-model.number="userInfo.age"><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 /><br />
        爱好:
        学习<input type="checkbox" v-model="userInfo.hobby" value="study">
        打游戏<input type="checkbox" v-model="userInfo.hobby" value="game">
        吃饭<input type="checkbox" v-model="userInfo.hobby" value="eat"><br /><br />
        所属校区:
        <select v-model="userInfo.city">
            <option value="">请选择校区option>
            <option value="beijing">北京option>
            <option value="shanghai">上海option>
            <option value="shenzhen">深圳option>
            <option value="wuhan">武汉option>
        select><br /><br />
        其他信息:
        <textarea v-model.lazy="userInfo.other">textarea><br /><br />
        <input type="checkbox" v-model="userInfo.agree"> 阅读并接受<a href="http://www.baidu.com">《用户协议》a>
        <button>提交button>
    form>
div>
<script type="text/javascript">
    Vue.config.productionTip = false;//设置为 false 以阻止 vue 在启动时生成生产提示。
    new Vue({
        el: '#root',
        data: {
            userInfo: {
                account: '',
                pwd: '',
                age:'',
                sex: 'female',
                hobby: [],
                city: '',
                other: '',
                agree: ''
            }

        },
        methods: {
            demo() {

            }
        },
    });


script>

1.13、过滤器

过滤器:

​ 定义:对要显示的数据进行特定格式化后显示(适用于一些简单的逻辑的处理)

​ 语法:

​ 1.注册过滤器:Vue.filter(name,callback) 或 new Vue(filters:{})

​ 2.使用过滤器:{{ xxx | 过滤器名}} 或 v-bind:属性 = “xxx | 过滤器名”

​ 备注:

​ 1.过滤器也可以接收额外参数、多个过滤器也可以串联

​ 2.并没有改变原来的数据,是产生新的对应的数据

例:

【Vue全家桶】--- 第一章:Vue核心_第16张图片

<div id="root">
    <h2>显示格式后的数据h2>
    
    <h3>现在是:{{fmtTime}}h3>
    
    <h3>现在是:{{getFmtTime()}}h3>
    
    <h3>现在是:{{time | timeformater}}h3>

    
    <h3>现在是:{{time | timeformater('YYYY-MM-DD') | mySlice}}h3>

    
    <h3 :x="msg | mySlice">xiaowangh3>
div>
<div id="root2">
    <h2>{{msg | mySlice}}h2>
div>
<script type="text/javascript">
    Vue.config.productionTip = false;//设置为 false 以阻止 vue 在启动时生成生产提示。
    //全局过滤器(filter),必须定义在Vue之前,一次只能定义一个
    Vue.filter('mySlice',function(value){
        return value.slice(0, 4)
    })
    new Vue({
        el: '#root',
        data: {
            time: Date.now(),
            msg:'你好,小王'

        },
        computed: {
            fmtTime() {
                return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
            }
        },
        methods: {
            getFmtTime() {
                return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')

            }
        },
        //局部过滤器
        filters: {//如果传str,则使用传入的值,如果没有传入则使用str="YYYY-MM-DD HH:mm:ss"
            timeformater(value, str = "YYYY-MM-DD HH:mm:ss") {

                return dayjs(value).format(str)

            }/* ,
                    mySlice(value) {

                        return value.slice(0, 4)

                    } */
        }
    })
    new Vue({
        el: '#root2',
        data: {
            msg:'hello,小王'
        }
    });

script>

1.14、内置指令自定义指令

1.14.1、常用内置指令

前面学过的指令:

  1. v-bind:单项绑定解析表达式,可以简写成 :xxx
  2. v-model:双向数据绑定
  3. v-for:遍历数组、对象、字符串
  4. v-on:绑定事件监听,可简写为@
  5. v-if:条件渲染(动态控制节点是否存在)
  6. v-else:条件渲染(动态控制节点是否展示)
  7. v-show:条件渲染(动态控制节点是否展示)

8.v-text指令:

1.作用:向其所在的节点中渲染文本内容

2.与插值语法的区别:v-text会替换掉节点中的内容,{{xxx}}不会

9.v-html指令:

1.作用:指定节点中渲染包含HTML结构的内容

​ 2.与插值语法的内容:

​ (1)v-html回替换掉节点中所有的内容,{{xxx}}则不会

​ (2)v-html可以识别HTML结构

​ 3.严重问题:v-html有安全性问题!!!

​ (1)在网站上动态的渲染任意HTML是非常危险的,容易导致XSS攻击

​ (2)在一定可信的内容上使用v-html,用不要在用户提交的内容

10.v-cloak指令(没有值):

1.本质是一个属性,Vue实例创建完毕并接管容器后,会删除v-cloak属性

2.使用css 配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题

​ [v-cloak]{display:none} 代表隐藏所有带有v-cloak标签的

11.v-once指令:

1.v-once所在节点在初次动态渲染后,就视为静态内容了

2.以后数据的改变不会引起v-once所在的结构的更新,可以用于优化性能

12.v-pre指令:

1.跳过其所在的节点的编译过程

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

1.14.2、自定义指令

1、定义语法

局部指令:

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

全局指令:

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

2、配置对象中常用的三个回调

(1)bind:指令与元素成功绑定时调用

(2)inserted:指令与元素被插入页面时调用

(3)update:指令所在模板结构被重新解析时调用

3、注意

1.指令定义时不加v-,但是用要加v-

2.指令如果多个单词,要是用kebab-case命名方式,不要使用camelCase命名

例:

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

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

<div id="root">
    <h2>{{name}}h2>
    <h2>当前的n值是:<span v-text="n">span>h2>
    <h2>放大10背后的n值是:<span v-big="n">span>h2>
    <button @click="n++">点我n+1button>

    <hr />
    <input v-fbind:value="n" type="text">

div>

<script type="text/javascript">
    Vue.config.productionTip = false;//设置为 false 以阻止 vue 在启动时生成生产提示。
    //定义全局指令
    Vue.directive('fbind', {
        //指令与元素成功绑定时(一上来)
        bind(element, binding) {
            element.value = binding.value

        },
        //指令所在元素被插入页面时
        inserted(element, binding) {
            element.focus()
        },
        //指令所在的模板被重新解析时
        update(element, binding) {
            element.value = binding.value
        }
    })
    new Vue({
        el: '#root',
        data: {
            n: 1,
            name: '小王'
        },
        directives: {
            /*  big 函数何时会被调用?
                element:DOM元素,binding:绑定的所有信息
                      1. 指令与元素成功绑定时(一上来)
                      2. 指令所在的模板被重新解析时

                */
            big(element, binding) {
                element.innerText = binding.value * 10
            },
            /*   fbind:{
                      //指令与元素成功绑定时(一上来)
                      bind(element,binding){
                          element.value = binding.value

                      },
                      //指令所在元素被插入页面时
                      inserted(element,binding){
                          element.focus()
                      },
                      //指令所在的模板被重新解析时
                      update(element,binding){
                       element.value = binding.value

                      }
                  } */
        }
    });

script>

1.15、Vue实例生命周期

1.又名:生命周期回调函数、生命周期函数、生命周期钩子

2.是什么:Vue在关键时刻帮我们调用的一些特殊的函数

3.生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的

4.生命周期函数中this指向的是 vm 或 组件实例对象

1.15.1、生命周期流程图

【Vue全家桶】--- 第一章:Vue核心_第17张图片

1.15.2、Vue生命周期分析

1.初始化显示

beforeCreate()

created()

beforeMount()

mounted()

2.更新状态: this.xxx = value

beforeUpdate()

updated()

3.销毁vue 实例: vm.$destory()

beforeDestory()

destoryed()

1.15.3、常用的生命周期方法

1.mounted:发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初识化操作】

2.beforeDestroy:清除定时器、绑定自定义事件、取消订阅消息等【收尾工作】

1.15.4、销毁Vue实例

1.销毁后借助Vue开发者工具不能看到任何信息

2.销毁后自定义事件会失效,但原生DOM事件依然有效。

3.一般不会在beforeDestroy操作数据,因为即使操作数据,也不会再触发更新流程了

你可能感兴趣的:(前端,vue,前端)