Vue2保姆级教学

vue基础

什么是vue?

Vue(轻量级框架)是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。

Vue的特点

  • 1.采用组件化模式,提高代码复用率,且让代码更好维护。
  • 2.声明式编码(还有命令式编码),让编码人员无需直接操作DOM,提高开发效率。
  • 3.使用虚拟的DOM+优秀的Diff算法,尽量复用DOM节点
  • 4.安装Vue Devtools插件
在官网上点击进入学习 =>Vue Devtools=>下载将下载好的文件拖入到游览器的拓展程序里面

初识Vue

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
    <!--    插值语法  双括号里面必须写js表达式   注意区分js表达式(一个值) 和 js代码-->
    <h1>Hello,{{name}}!</h1>
</div>
<script type="text/javascript">
    //设置为 false 以阻止 vue 在启动时生成生产提示
    Vue.config.productionTip = false;
    //创建Vue实例{只能操作一个对象(配置对象)}
    let vm = new Vue({
        //element元素
        //用于指定当前Vue实例为那个容器服务,值通常为css选择器字符串
        //document.getElementById('root')
        el: '#root',
        data: {//data中用于存储数据,数据供el所指定的容器去使用,值我们暂时先写成一个对象
            name: '恋椿'
        },
    })

</script>
</body>
</html>

总结:

1.想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象;
2.root容器里的代码依然符合HTML规范,只不过混入了一些特殊的Vue语法;
3.root容器里的代码被称为【Vue模版】;
4.vue与容器的关系为1对1
5.真实开发中只有一个Vue实例,并且配合着组件一起使用;
6.{{xxx}}中的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(){}

模板语法

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<!--    指令语法-->
    <a v-bind:href="url">点我去学习</a>
<!--    可以简写成-->
    <a :href="url">点我去学习</a>
</div>
<script type="text/javascript">

    //创建Vue实例{只能操作一个对象}
    let vm = new Vue({
        //element元素
        //用于指定当前Vue实例为那个容器服务,值通常为css选择器字符串
        el: '#root',
        data: {//data中用于存储数据,数据供el所指定的容器去使用
            name: '恋椿',
            url:'http://www.atguigu.com',
        },
    })

</script>
</body>
</html>

总结:

 Vue模版语法有两大类
  1.插值语法:
     功能:用于解析标签体内容  写在标签体内
     写法:{{xxx}},xxx是js表达式,且可以直接读取到data中的所有属性值。
  2.指令语法:  写在标签内部
     功能:用于解析标签(包括:标签属性、标签体内容、绑定事件...)
     举例:v-bind:href="xxx" 或者可以简写为 :href="xxx",xxx同样要写js表达式,
          且可以直接读取到data中的所有属性。
标签体内用插值语法,标签属性内用指令语法

数据绑定:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
  单项数据绑定:<input type="text" :value="name"></br>
<!--  v-model只能应用在表单类元素上(输入类元素、有value值)-->
  双向数据绑定:<input type="text" v-model="name">
</div>
<script type="text/javascript">

  //创建Vue实例{只能操作一个对象}
  let vm = new Vue({

    el: '#root',
    data: {//data中用于存储数据,数据供el所指定的容器去使用
      name: '恋椿',
    },
  })

</script>
</body>
</html>

总结:

vue中有两种数据绑定
1.单项绑定(v-bind):数据只能从data中流向页面
2.双向绑定(v-model:value):可以简写为v-model,因为v-model默认收集的就是value值

el与data的两种写法:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
    <h1>{{name}}</h1>
</div>
<script type="text/javascript">


    let vm = new Vue({
        //el的第一种写法
        // el: '#root',
        //data的第一种写法:对象式
        // data: {//data中用于存储数据,数据供el所指定的容器去使用
        //   name: '恋椿',
        // },
        //  data的第二种写法函数式  用组件的时候必须使用函数式的写法,this代表的是vue实例
        data: function () {
            console.log("ddd", this)
            return {
                name: '恋椿'
            }
        }
    })
    //el的第二种写法 mount 挂载、放
    vm.$mount("#root")
</script>
</body>
</html>

总结:

data与el的2种写法
     1.el有两种写法
       (1).new Vue时候配置el
       (2).先创建Vue实例,随后在通过vm.$mount('#root')指定el的值
     2.data的有两种写法
       (1).对象式
       (2).函数式  用组件的时候必须使用函数式的写法
     3.一个重要的原则:
       由Vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,this就不是Vue实例了(否则this就是window对象)

MVVM模型:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
    <h1>学校名称:{{name}}</h1>
    <h1>学校地址:{{address}}</h1>
</div>
<script type="text/javascript">

    let vm = new Vue({
        el: '#root',
        data: {
            name: '恋椿',
            address: '北大',
        },
    })

</script>
</body>
</html>

总结:

vue中有两种数据绑定
     MVVM模型
         1. M:模型(model):data中的数据
         2. V:视图(view):模版代码
         3. VM 视图模版(ViewModel):Vue实例
     观察发现
         1.data中的所有属性:最后都出现在了vm身上
         2.vm身上所有的属性 及 Vue原型上的所有属性,在Vue模版中都可以直接使用

数据代理:

Object.defineProperty方法

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>回顾Object.defineProperty方法</title>

</head>
<body>


<script type="text/javascript">


    let number = 18;
    let person = {
        name: '张三',
        sex: '男',
    }
    //追加属性             给谁追加  属性名
    Object.defineProperty(person, 'age', {
    // //age不参与遍历 不能枚举
        // value: number,
        //
        // //控制属性是否可以枚举、遍历 默认false
        // enumerable: true,
        //
        // //控制属性是否可以被修改 默认false
        // writable: true,
        //
        // //  控制属性能否被删除 默认false
        // configurable: true,

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

        set(value) {
            console.log("有人修改了age:" + value);
            number = value;
        }
    })

    //可以把传入对象的所有属性的属性名提取出来变成一个数组
    console.log(Object.keys(person))
    for (let key in person) {
        console.log(person[key])
    }

    console.log(person)
</script>

</body>
</html>

什么是数据代理?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>什么是数据代理</title>
</head>
<body>
<!--数据代理:通过一个对象代理另一个对象中的属性的操作-->
<script type="text/javascript">
    let obj = {x: 100}
    let obj2 = {y: 100}

    Object.defineProperty(obj2, 'x', {
        get() {
            return obj.x
        },
        set(value) {
            obj.x = value
        }
    })
</script>
</body>
</html>

Vue中的数据代理

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue中的数据代理</title>
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
    <h2>学校名称:{{name}}</h2>
    <h2>学校地址:{{address}}</h2>
    <h2></h2>
</div>
<script type="text/javascript">
    Vue.config.productionTip = false;
    let vm = new Vue({
        el: "#root",
        //_data==data ——>将data内的数据挂到vm身上
        //_data中的数据是数据劫持不是数据代理
        data: {
            name: '叨叨学院',
            address: '叨叨市叨叨路',

        }
    })
</script>
</body>
</html>

总结:
         1.Vue中的数据代理:
              通过vm来代理data对象中属性的操作(读/写)
         2.Vue中的数据代理的好处:
              更加方便的操作data中的数据
         3.基本原理:
              通过Object.defineProperty()把data对象中的所有属性添加到vm上。
              为每一个添加到vm上的属性,都制定一个getter/setter。
              在getter/setter内部去操作(读/写)data中对应的属性

事件的处理:

基本使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>事件的基本使用</title>
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
    <h2>欢迎来到{{name}}学院学习</h2>
    <button v-on:click="showInfo1">点我提示信息1</button>
<!--    简写-->
    <button @click="showInfo2(666,$event)">点我提示信息2</button>
</div>
</body>
<script type="text/javascript">
    Vue.config.productionTip=false;
   const vm = new Vue({
        el:'#root',
        data:{
            name:'叨叨叨'
        },
        methods:{
            showInfo1(event){//触发事件的元素
                // console.log(event.target)
                alert('叨叨同学你好!')
            },
            showInfo2(number,event){//触发事件的元素
                console.log(number)
                alert('叨叨同学你好!!')
            }
        }

    })
</script>
</html>

总结:
         所有被Vue所管理的方法都写成普通方法
         事件的基本使用:
             1.使用v-on:xxx 或 @xxx 绑定事件, 其中xxx是事件名;
             2.事件的回调需要配置在methods对象中,最终会在vm身上;
             3.methods配置的函数,不要用箭头函数!否则this就不是vm了;
             4.methods配置的函数,,都是被Vue所管理的函数,this的指向是vm 或 组件实例对象;
             5.@click='demo' 和 @click='demo($event)' 效果一致,但后者可以传参;

事件的修饰符

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>事件的基本使用</title>
    <script type="text/javascript" src="../js/vue.js"></script>
    <style>
        *{
            margin-top: 30px;
        }
        .demo1{
            height: 50px;
            background-color: pink;
        }
        .box1{
            padding: 5px;
            background-color: green;
        }
        .box2{
            padding: 5px;
            background-color: orange;
        }
        .list{
            width: 200px;
            height: 200px;
            background-color: peru;
            overflow: auto;
        }
        li{
            height: 100px;
        }
    </style>
</head>
<body>
<div id="root">
    <h2>欢迎来到{{name}}学院学习</h2>

<!--    1.prevent:阻止默认事件(常用);-->
    <a href="http://www.baidu.com" @click.prevent="showInfo">点我提示信息1</a>

<!--    2.stop:阻止事件冒泡(常用);-->
<!--    先调用子代的事件在调用自身的(从上到下捕捉然后触底反弹开始冒泡)    -->
    <div class="demo1" @click="showInfo2">
        <button @click.stop="showInfo">点我提示信息2</button>
    </div>

<!--    3.once:事件只触发一次(常用);-->
    <div class="demo1">
        <button @click.once="showInfo">点我提示信息3</button>
    </div>

<!--    4.capture:使用事件的捕获方式;-->
    <div class="box1" @click.capture="showMsg(1)">
        div1
        <div class="box2" @click="showMsg(2)">
            div2
        </div>
    </div>

<!--    5.self:只有event.target是当前操作的元素时才触发事件;-->
    <div class="demo1" @click.self="showInfo2">
        <button @click="showInfo">点我提示信息2</button>
    </div>

<!--    6.passive:事件的默认行为立即执行,无需等待事件回调执行完毕;-->
<!--    @scroll是给滚动条加的滚动事件 @wheel是给鼠标的滚轮添加的滚动事件-->
    <ul @wheel.passive="demo" class="list">
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
    </ul>

</div>
</body>
<script type="text/javascript">
    Vue.config.productionTip = false;
    new Vue({
        el: '#root',
        data: {
            name: '叨叨叨'
        },
        methods: {
            showInfo(e) {

                // e.preventDefault() //阻止默认行为
                // e.stopPropagation() //阻止冒泡事件
                alert('同学你好!')
                // console.log(e.target)
            },
            showInfo2(e) {
                console.log(e.target)
                alert('ddd!')
            },
            showMsg(msg) {

                console.log(msg)
            },
            demo() {
                for (let i=0;i<100000;i++) {
                    console.log("#")
                }
                console.log("累不")
            }
        }
    })
</script>
</html>

总结:
          Vue中的事件修饰符:
              1.prevent:阻止默认事件(常用);
              2.stop:阻止事件冒泡(常用);
              3.once:事件只触发一次(常用);
              4.capture:使用事件的捕获方式;
              5.self:只有event.target是当前操作的元素时才触发事件;
              6.passive:事件的默认行为立即执行,无需等待事件回调执行完毕;
          注意修饰符可以连续写

键盘事件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>事件的基本使用</title>
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
    <h2>欢迎来到{{name}}学院学习</h2>
    <!--  @keydown按下按键不用抬起来就触发  @keyup按下按键抬起来才触发-->
    <input type="text" placeholder="按下回车提示输入" @keyup.ctrl.a="showInfo">
</div>
</body>
<script type="text/javascript">
    Vue.config.productionTip = false;

    new Vue({
        el: '#root',
        data: {
            name: '叨叨叨'
        },
        methods: {
            showInfo(e) {
                // if (e.keyCode !== 13) return
                console.log(e.target.value)
                // console.log(e.key,e.keyCode)


            }
        },
    })
</script>
</html>

总结:
          1.Vue中常用的案件别名:
               回车=>enter
               删除=>delete(捕获“删除”和“退格“ 键)
               退出=>esc
               空格=>space
               换行=>tab   特殊keyup不适合用tab,不许用keydown
               上=>up
               下=>down
               左=>left
               右=>right

          2.Vue未提供别名的按键,可以使用按键的原始key去绑定,但注意要转为kebab(短横命名)
               ***例如CapsLock按键的key值为CapsLock,用的时候得写成caps-lock

          3.系统修饰键(用法特殊):ctrl、alt、shift、meta
               (1).配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发
               指定和修饰键组合的按键   @keyup.ctrl.y="showInfo"
               (2).配合keydown使用:正常触发事件。
          4.也可以使用keyCode去指定具体的按键(不推荐)
          5.Vue.config.keyCodes.自定义键名=建码,可以去定义按键别名

计算属性

三种方式:

插值语法实现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>1.姓名案例_插值语法.html</title>
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
    姓:<input type="text" v-model="firstName"><br/>
    名:<input type="text" v-model="lastName"><br/>
    姓名:<span>{{firstName.slice(0,3)}}-{{lastName}}</span>
    姓名:<span>{{firstName}}-{{lastName}}</span>
</div>
</body>
<script type="text/javascript">
    Vue.config.productionTip = false;
    new Vue({
        el: '#root',
        data: {
            firstName: '张',
            lastName: '三'
        },
        methods: {
            showInfo() {
            }
        }
    })
</script>
</html>

methods实现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>1.姓名案例_插值语法.html</title>
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
      <!--
          只要Vue中的数据发生变化,Vue将重新解析模版,重新调用函数
      -->
<div id="root">
    姓:<input type="text" v-model="firstName"><br/>
    名:<input type="text" v-model="lastName"><br/>
    姓名:<span>{{fullName()}}</span>
</div>
</body>
<script type="text/javascript">
    Vue.config.productionTip = false;
    new Vue({
        el: '#root',
        data: {
            firstName: '张',
            lastName: '三',
            age:18
        },
        methods: {
            fullName() {
                console.log(123)
                return this.firstName+'-'+this.lastName
            }
        }
    })
</script>
</html>

计算属性实现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>姓名案例_计算属性实现</title>
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
    姓:<input type="text" v-model="firstName"><br/>
    名:<input type="text" v-model="lastName"><br/>

    姓名:<span>{{fullName}}</span><br/>
    <!--    有缓存,初次读取时会调用,所以来的数据发生变化时重新调用-->
    姓名:<span>{{fullName}}</span><br/>
    姓名:<span>{{fullName}}</span><br/>
    姓名:<span>{{fullName}}</span><br/>
</div>
</body>
<script type="text/javascript">
    Vue.config.productionTip = false;
   let vm= new Vue({
        el: '#root',
        data: {
            firstName: '张',
            lastName: '三'
        },
        computed:{
            fullName:{
                //get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值
                get(){
                    return this.firstName + '-' + this.lastName
                },
                set(value){
                    console.log('set',value)
                    const arr=value.split('-')
                    this.firstName=arr[0]
                    this.lastName=arr[1]
                }
            }
        }

    })
</script>
</html>

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

计算属性简写

当确定只读取不修改时可以这样写,计算属性中不能开启异步任务去维护数据
 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>姓名案例_计算属性实现</title>
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
    姓:<input type="text" v-model="firstName"><br/>
    名:<input type="text" v-model="lastName"><br/>

    姓名:<span>{{fullName}}</span><br/>
</div>
</body>
<script type="text/javascript">
    Vue.config.productionTip = false;
    let vm = new Vue({
        el: '#root',
        data: {
            firstName: '张',
            lastName: '三'
        },
        computed: {
            fullName: function () {

                return this.firstName + '-' + this.lastName
            },
            // fullName: function () {
            //     setTimeout(()=>{
            //         return this.firstName + '-' + this.lastName
            //     },1000)
            //
            // }


        }

    })
</script>
</html>

监视属性

天气案例:当点击按钮时切换天气

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>监视属性</title>
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h2>今天天气很{{info}}</h2>
    <button @click="changeWeather">切换天气</button>

<!--    简化版 可以写一些简单的语句-->
    <button @click="isHot=!isHot">切换天气</button>
</div>
</body>
<script type="text/javascript">
    Vue.config.productionTip=false;
    new Vue({
        el:'#root',
        data:{
            isHot:true
        },
        computed:{
            info(){
                return this.isHot ? '炎热' : '凉爽'
            }
        },
        methods:{
            changeWeather(){
                this.isHot=!this.isHot
            }
        }

    })
</script>
</html>

使用监视属性完成

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>事件的基本使用</title>
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h2>今天天气很{{info}}</h2>
    <button @click="changeWeather">切换天气</button>
</div>
</body>
<script type="text/javascript">
    Vue.config.productionTip=false;
  const vm= new Vue({
        el:'#root',
        data:{
            isHot:true
        },
        computed:{
            info(){
                return this.isHot ? '炎热' : '凉爽'
            }
        },
        methods:{
            changeWeather(){
                this.isHot=!this.isHot
            }
        },
        watch:{
            info:{
                // immediate:true,//初始化时让handler调用一下
                handler(newValue,oldValue){
                    console.log('isHot被修改了')
                    console.log('newValue:'+newValue)
                    console.log('oldValue:'+oldValue)
                }
            }
        }

    })
    // vm.$watch('isHot',{
    //     // immediate:true,//初始化时让handler调用一下
    //     handler(newValue,oldValue){
    //         console.log('isHot被修改了')
    //         console.log(newValue)
    //         console.log(oldValue)
    //     }
    // })
</script>
</html>

总结:

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

深度监视

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>深度监视</title>
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
    <h2>今天天气很{{info}}</h2>
    <button @click="changeWeather">切换天气</button>
    <hr/>
    <h3>a的值为:{{numbers.a}}</h3>
    <button @click="numbers.a++">点我a++</button>
    <hr/>
    <h3>b的值为:{{numbers.b}}</h3>
    <button @click="numbers.b++">点我b++</button>
</div>
</body>
<script type="text/javascript">
    Vue.config.productionTip = false;
    const vm = new Vue({
        el: '#root',
        data: {
            isHot: true,
            numbers: {
                a: 1,
                b: 2
            }
        },
        computed: {
            info() {
                return this.isHot ? '炎热' : '凉爽'
            }
        },
        methods: {
            changeWeather() {
                this.isHot=!this.isHot
            }
        },
        watch: {
            isHot: {
                handler(newValue, oldValue) {
                    console.log('isHot被修改了')
                    console.log('newValue:'+newValue)
                    console.log('oldValue:'+oldValue)
                }
            },
            //监视多级结构中某个属性的变化
            // 'numbers.a':{
            //     handler(newValue, oldValue) {
            //         console.log('a的值被改变')
            //     }
            // }
            //监视多级结构中所有属性的变化
            numbers: {
                deep: true,//开启深度监视
                handler(newValue, oldValue) {
                    console.log('numbers改变了')
                }
            }
        }


    })

</script>
</html>

总结:

深度监视:
               (1).Vue中的watch默认不监测对象内部值的改变(一层)
               (2).配置deep:true可以监测对象内部值改变(多层)
          备注:
               (1).Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以!
               (2).使用watch时根据数据的具体结构,决定是否采用深度监视

深度监视简写

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>深度监视</title>
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>

<div id="root">
    <h2>今天天气很{{info}}</h2>
    <button @click="changeWeather">切换天气</button>
</div>
</body>
<script type="text/javascript">
    Vue.config.productionTip = false;
    const vm = new Vue({
        el: '#root',
        data: {
            isHot: true,
        },
        computed: {
            info() {
                return this.isHot ? '炎热' : '凉爽'
            }
        },
        methods: {
            changeWeather() {
                this.isHot = !this.isHot
            }
        },
        watch: {
            //正常写法
            // isHot: {
            //     handler(newValue, oldValue) {
            //         console.log('isHot被修改了')
            //         console.log(newValue)
            //         console.log(oldValue)
            //     }
            // }

        //    简写  前提 immediate deep 不需要改变时
        //     isHot(newValue,oldValue){
        //         console.log('isHot被修改了',newValue,oldValue)
        //     }
        }


    })
    //完整写法
    // vm.$watch('isHot',{
    //     immediate:true,
    //     depp:true,
    //     handler(newValue,oldValue){
    //         console.log('isHot被修改了',newValue,oldValue)
    //
    //     }
    // })
//    简写
    vm.$watch('isHot',function (newValue,oldValue){
        console.log('isHot被修改了',newValue,oldValue)
    })
</script>
</html>

总结:
          深度监视:
               (1).Vue中的watch默认不监测对象内部值的改变(一层)
               (2).配置deep:true可以监测对象内部值改变(多层)
          备注:
               (1).Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以!
               (2).使用watch时根据数据的具体结构,决定是否采用深度监视

watch实现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>姓名案例_计算属性实现</title>
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
    姓:<input type="text" v-model="firstName"><br/>
    名:<input type="text" v-model="lastName"><br/>

    姓名:<span>{{fullName}}</span><br/>
</div>
</body>
<script type="text/javascript">
    Vue.config.productionTip = false;
    let vm = new Vue({
        el: '#root',
        data: {
            firstName: '张',
            lastName: '三',
            fullName: '张-三'
        },
        watch: {
            // firstName(newValue) {
            //     setTimeout(()=>{
            //         this.fullName = newValue + '-' + this.lastName
            //     },1000)
            // },
            firstName(newValue) {
                this.fullName = newValue + '-' + this.lastName
            },
            lastName(newValue) {
                this.fullName = this.firstName + '-' + newValue
            }
        }

    })
</script>
</html>

总结:
    当确定只读取不修改时可以这样写
    watch中可以开启异步任务去维护数据
    定时函数不属于Vue所管理的

    computed 和 watch之间的区别:
       1.computed能完成的功能,watch都能完成
       2.watch能完成的功能computed不一定能完成,例如:watch可以进行异步操作。
    两个重要的小原则:
       1.所有被Vue所管理的函数,做好写成普通函数,这样this的指向才是 vm 或 组件实例对象。
       2.所有不得Vue所管理的函数(定时器的回调函数、ajax的回调函数等),最好写成箭头函数,这样this的指向才是 vm 或 组件实例对象。

绑定样式

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>绑定样式</title>
    <style>
        .basic {
            border: 1px solid black;
        }

        .happy {
            border: 1px solid pink;
            background-color: red;
        }

        .sad {
            border: 2px double green;
            background-color: #807f80;
        }

        .normal {
            border: 2px solid black;
            background-color: #7fc6eb;
        }

        .lianChun1 {
            background-color: lawngreen;
        }

        .lianChun2 {
            background-color: red;
            font-weight: bold;
        }

        .lianChun3 {
            border-radius: 5px;
        }
    </style>
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
    <!--    绑定class样式 -字符串写法 适用于 : 样式的类名不确定,需要动态指定 -->
    <div class="basic" :class="mood" @click="changeMood">{{name}}</div>
    <br/>
    <!--    绑定class样式 -数组写法 适用于 : 要绑定的样式个数不确定,名字也不确定 -->
    <div class="basic" :class="arr" >{{name}}</div>
    <br/>
    <!--    绑定class样式 -对象写法 适用于 : 要绑定的样式确定,名字确定,但要动态的决定用不用 -->
    <div class="basic" :class="classObj">{{name}}</div>
    <br>
    <div class="basic" :style="{fontSize: fsize + 'px'}">{{name}}</div>
    <div class="basic" :style="styleObj">{{name}}</div>
</div>
</body>
<script>
    Vue.config.productionTip=false;
   const vm= new Vue({
        el: '#root',
        data: {
            name: '恋椿',
            mood: 'normal',
            arr:['lianChun1','lianChun2','lianChun3'],
            classObj:{
                lianChun1:false,
                lianChun2:false,
            },
            fsize:'40',
            
        },
        methods: {
            changeMood() {
                // document.getElementById("root").className='basic happy';
                //this.mood = 'happy'
                const arr=['happy','sad','normal']
            //    随机生成随机数
               const  index=Math.floor(Math.random()*3)
                this.mood=arr[index]
            //    网页测试 删除样式 vm.arr.shift()  vm.arr.push('lianChun1')

            }
        }
    })
</script>
</html>

条件渲染

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>条件渲染</title>
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
    <p v-if="num==1">百度</p>
    <p v-else-if="num==2">腾讯</p>
    <p v-else="num==3">阿里</p>
    <p v-if="num==4">痘印</p>

    <p v-show="num==1">天猫</p>
    <p v-show="num==2">淘宝</p>


</div>
</body>
<script>
    Vue.config.productionTip = false;
    const vm = new Vue({
        el: "#root",
        data() {
            return {
                num: 2
            }

        }
    })
</script>
</html>

总结:
v-if 和 v-show的区别
如果需要频繁的切换使用show较好
当条件不成立,v-if内的所有子节点不会解析(项目中使用)

循环及列表过滤

语法:

 v-for="(item, index) in xxx" :key=“yyy”

使用:

  • 可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)
  • v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名(形参)。
  • v-for 还支持一个可选的第二个参数,即当前项的索引。
  • 可以用 of 替代 in 作为分隔符,因为它更接近 JavaScript 迭代器的语法:
    • 数组: (item, index)
    • 对象: (value, key)
    • 字符串:(char, index)
    • 数字:(number, index)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue初体验</title>
    <!-- 1.引入Vue -->
    <script src="../js/vue.js"></script>
</head>
<body>
<!-- 2.准备一个容器 -->
<div id="root">
    <h1>数组遍历</h1>
    <input type="text"  placeholder="请输入要查询的姓名" v-model="keyWord">
    <button @click="sortType = 2 ">年龄升序</button>
    <button @click="sortType = 1 ">年龄降序</button>
    <button @click="sortType = 0 ">复原</button>
    <table cellpadding="0" cellspacing="0" border="1">
        <thead>
        <th width="100px">ID</th>
        <th width="100px">姓名</th>
        <th width="100px">年龄</th>
        </thead>
        <tr v-for="(user,index) in userListFil" :key="user.id" align="center">
            <td>{{user.id}}</td>
            <td>{{user.name}}</td>
            <td>{{user.age}}</td>
        </tr>
    </table>
</div>
<script>
    //3.创建Vue实例
    const vm = new Vue({
        el:'#root',
        data:{
            userList:[
                {id:1,name:'张飞',age:18},
                {id:2,name:'刘备',age:19},
                {id:3,name:'关羽',age:20},
                {id:4,name:'曹操',age:18},
                {id:5,name:'关平',age:19},
                {id:6,name:'曹植',age:20},
            ],
            keyWord:'',
            sortType:0,
        },
       computed:{
           // 只过滤
           // userListFil(){
           //     return this.userList.filter((user)=>{ //将userList下的所有对象都交给user
           //         return user.name.indexOf(this.keyWord) !== -1 //查找是否包含keyWord
           //     })
           // }
           userListFil(){
               const arr = this.userList.filter(user=>{
                   return user.name.indexOf(this.keyWord) !== -1;
               });
               //判断是否排序
               if (this.sortType !== 0){
                   //sort函数要比较两个值,然后返回一个用于说明这两个值的相对顺序的数字。
                   arr.sort((p1,p2)=>{ //将原位置(p1) 和后一个(p2) 进行比较
                       if(p1.age - p2.age < 0){  //如果p1的年龄大于p2
                           console.log(p1.age + "小于" + p2.age + "调换位置")
                       }else if(p1.age - p2.age > 0){
                           console.log(p1.age + "大于" + p2.age + "位置不变")
                       }else {
                           console.log(p1.age + "等于" + p2.age + "位置不变")
                       }
                       return this.sortType === 1 ? p2.age - p1.age : p1.age - p2.age;
                   });
               }
               return arr;
           }
       }
    });
</script>
</body>
</html>

key的原理:

  • 有相同父元素的子元素必须有独特的 key。重复的 key 会造成渲染错误

收集表单数据:

  • 若:type=text、password、number,则v-model默认收集的是value值,用户输入的就是value值。
  • 若:type=radio,则v-model默认收集的是value值,因为此类型无法输入内容,则无法通过输入得到value值,所以要给标签手动添加value值。
  • 若:type=checkbox

          没有配置input的value属性,那么默认读取的的就是checked是否被勾选(勾选 or 未勾选,是布尔值)

          配置input的value属性:

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

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

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

                  lazy:失去焦点再收集数据

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

                  trim:输入首尾空格过滤

Vue指令

常用的内置指令

内置指令解释

v-text

更新元素的 textContent
v-html更新元素的 innerHTML
v-if如果为true, 当前标签才会输出到页面
v-else如果为false, 当前标签才会输出到页面
v-show通过控制display样式来控制显示/隐藏
v-for遍历数组/对象
v-on绑定事件监听, 一般简写为@
v-bind强制绑定解析表达式, 可以省略v-bind
v-model双向数据绑定

v-text与v-html的区别:

  v-text : 更新元素的 textContent
  • 作用:向其所在的节点中渲染文本内容。
  • 与插值语法的区别:v-text会替换掉节点中的内容,{{xx}}则不会。
v-html : 更新元素的 innerHTML
  • 作用:向指定节点中渲染包含html结构的内容。
  • 与插值语法的区别:
    • v-html会替换掉节点中所有的内容,{{xx}}则不会。
    • v-html可以识别html结构。

注意:v-html有安全性问题!!!!

  • 在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击。
  • 一定要在可信的内容上使用v-html,永不要用在用户提交的内容上!

v-once与v-pre

v-once
  • v-once所在节点在初次动态渲染后,就视为静态内容了。
  • 以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。
v-pre
  • 跳过其所在节点的编译过程。(vue 不去解析 插值等语法)
  • 可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译。

ref与v-cloak

ref
  • 为某个元素注册一个唯一标识, vue对象通过$refs属性访问这个元素对象。
v-cloak
  • 使用它防止闪现表达式, 与css配合: [v-cloak] { display: none }
    • 本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性。
    • 使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题。

自定义指令

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue初体验</title>
    <!-- 1.引入Vue -->
    <script src="../js/vue.js"></script>
</head>
<body>
<!-- 2.准备一个容器 -->
<div id="root">
    <h1>当前n的值是:<span v-text="num"></span></h1>
    <h1>放大10倍后的n的值是:<span v-big="num"></span></h1>
    <button @click="num++">点击num+1</button>
    <hr>
    <input type="text" v-fbind:value="num">
</div>
<script>
    //3.创建Vue实例
    const vm = new Vue({
        el:'#root',
        data:{
            num:10,
        },
        directives:{
            big(el,binding){
                el.innerText = binding.value * 10;
            },
            fbind:{
                bind(el,binding){
                    el.value = binding.value;
                },
                // 指令的定义
                inserted(el,binding){
                    el.focus();
                },
                update(el,binding){
                    el.value = binding.value;
                    el.focus();
                }
            }
        },
    });
</script>
</body>
</html>

  • 26
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值