Vue基础知识-2

本文介绍了Vue的基础知识,包括Vue的渐进式特性、版本历史和MVC/MVVM架构思想。详细讲解了Vue的源代码结构,并提出学习Vue应避免直接操作DOM,转而使用指令。文章重点探讨了Vue的指令系统,如数据展示(v-html、v-text)、条件渲染(v-if、v-else、v-show、v-for)、单向和双向数据绑定(v-bind、v-model)、事件处理和修饰符,以及计算属性和watch的使用案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Vue的介绍

  1. 作者:尤雨溪
  2. vue是一个渐进式的javascript框架
  • 渐进式:越来越难学

  • vue是一个个人项目

  • Vue版本发布的时间

    • Vue 1.x 2014

    • Vue 2.x 2016 【 es6 vue 微信小程序 angular2.0 …

  1. MVC
  • MVC是一个软件的架构思维,分为三个部分

    • M Model 数据
    • V View 视图
    • C Controller 控制器
  • - MVC衍生

  • mvc backbone 【 前端框架 】

  • mvp

  • mvvm Vue Angular.ts 【 Angular2.0】

  • ember

  1. MVVM
  • M Model 数据

  • V View 视图

  • VM ViewModel 视图模型

  • V的变化会反应到VM上,反之同理,也就是vm的改变也会影响V

Vue的源代码

  1. 行数: 11945 开发环境
  2. Vue的源代码是通过匿名函数【 自调用函数 】来进行封装
  • 匿名函数好处
    • 解决了命名冲突
    • 规定了一个独立的作用域
    • 安全性高
      • xss 攻击脚本
      • CRSF 攻击脚本
  • 格式
//第一个括号表示定义一个匿名函数
//第二个括号表示调用这个函数 
//参数: 第一个括号中的参数为 形式参数
//第二个括号中的参数为 实际参数
//this - 指的就是window对象
//factory - 工厂函数   返回值就是Vue构造函数
//el不能是body
//Vue是通过面向对象原型继承 + 工厂函数进行底层代码封装的 
(function ( global,factory) {

})( this,function () {})

Vue学习的思路

  1. Vue有指令和组件系统两个大功能
  2. 通过js想操作DOM - > Vue也想操作DOM
  • 问题: Vue中不建议像二阶段一样直接去操作DOM
  • 解决: 方案: 指令

指令

数据展示

v-html 可解读XML标签

v-text

条件渲染

  • 单分支 v-if

  • 双分支

    v-if

    v-else 必走一条

  • 多分支

    v-if = “type === ‘条件1’”

    v-else-if = “type ===‘条件2’”

    v-else//其他条件

  • 条件展示

    v-show

  • v-if vs v-show的比较

    • v-if是真正的控制dom的存在与否,v-show 是控制dom的display:none属性

    • 如果初始条件都为false,v-if会惰性渲染【 不渲染 】,但是v-show不管条件是什么都会渲染,所以v-show的初始渲染开销较高

    • 如果我们要频繁的切换flag,那么我们使用谁? 我们使用 v-show , 反之,使用v-if

  • 渲染数组

    • v-for = “(item,index) in 数组名”
  • 对象的渲染

    • v-for = “(item,index) in 对象名”
  • JSON的渲染

    • v-for = “(item,index) in JSON名”
  • 特殊数据的渲染

    • v-for = “item in 10”
  • 特殊数据的渲染

    • ​ 嵌套

      <!DOCTYPE html>
      <html lang="en">
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title> 指令 </title>
        <style>
          .container{
            margin: 20px;
          }
        </style>
      </head>
      <body>
        <div id="app">
          <div class="container">
            <h3> 数据展示 </h3>
              <p> {{ msg }} </p>
              <p v-html = "msg"></p>
              <p v-text = "msg"></p>
            <hr>
            <h3> 条件渲染 </h3>
              <h4> 条件渲染 - 单路分支 </h4>
              <p v-if = "flag"> 条件 - 单路分支 </p>
      
              <h4> 条件渲染 - 双路分支 </h4>
              <p v-if = "flag1"> 条件 - 双路 - 1 </p>
              <p v-else> 条件 - 双路 - 2 </p>
      
              <h4> 条件渲染 - 多路分支 </h4>
              <p v-if = " type === 'A'"> 条件 - A </p>
              <p v-else-if = "type === 'B'"> 条件 - B </p>
              <p v-else> 条件 - C </p>
            <hr>
            <h3> 条件展示 </h3>
              <p v-show = "flag2"> 条件 - 展示 </p>
      
            <hr>
      
            <h3> 列表渲染 </h3>
            <h4> 数组 </h4>
              <ul>
                <li v-for = " (item,index) in lists">
                  {{ item }} -- {{ index }}
                </li>
              </ul>
            <h4> 对象 </h4>
              <ul>
                <li v-for = " (value,key,index) in obj ">
                  {{ value }} --- {{ key }} --- {{ index }}
                </li>
              </ul>
      
            <h4> json  </h4>
              <ul>
                <li v-for = "(item,index) in json">
                  <p> 商品名称: {{ item.shopName }} -- {{ index }} -- {{ item.id }} </p>
                </li>
              </ul>
      
            <h4> 列表渲染特殊数据 </h4>
              <ul>
                <li v-for = "item in 10">
                  {{ item }}
                </li>
              </ul>
      
              <h4> 列表渲染嵌套 </h4>
      
              <ul>
                <li v-for = "item in banners">
                  <p> {{ item.name }} </p>
                  <ul>
                    <li v-for = "val in item.child">
                      {{ val.name }}
                    </li>
                  </ul>
                </li>
              </ul>
          </div>
        </div>
      </body>
      <script src="../../../lib/vue.js"></script>
      <script>
        new Vue({
          el: '#app',
          data: {
            msg: '<div> hello Vue.js</div>',
            flag: false,
            flag1: true,
            type: 'A',
            flag2: false,
            lists: [1,2,3,4],
            obj: {
              id: 1,
              name: 'Gabriel Yan',
              age: 16
            },
            json: [
              {
                id: 1,
                shopName: '商品一'
              },
              {
                id: 2,
                shopName: '商品二'
              },
              {
                id: 3,
                shopName: '商品三'
              }
            ],
            banners: [
              {
                id: 1,
                name: 'banner1',
                child: [
                  {
                    id: 1,
                    name: 'banner1 - 1'
                  }
                ]
              },
              {
                id: 2,
                name: 'banner2',
                child: [
                  {
                    id: 2,
                    name: 'banner2 - 2'
                  }
                ]
              },
              {
                id: 3,
                name: 'banner3',
                child: [
                  {
                    id: 3,
                    name: 'banner3 - 3'
                  }
                ]
              }
            ]
          }
        })
      </script>
      </html>
      

单向绑定数据

v-bind:value= ‘msg’

 <input type="text" :value = 'msg'>

样式绑定

:style="{ …}"

<p :style="{width:'100px',height:'100px',background:'yellow'}"></p>
<p :style="{width:w,height:h,background:bg}"></p>//w,h是data中的数据
  • 样式绑定 - 数组写法

    <p :style="[styhg,stycolor]"></p>
    

    绑定类名

    :class = “{…}”

    <p :class="{size:true,color:true}"></p>
    <p :class="{size:flage,color:flage}"></p>
    <p :class="{size:flage,color:flage}"></p>
    <p :class="{[size]:flage,[color]:flage}"></p>
    

    数组的写法

    <p :class = [size,color]></p>
    

    引申

    <p :class = "[ size,flage && bg || color]"></p>
    
  • 其他:可以绑定dom任意一个属性

    <img :src="imgUrl" alt="">
    

双向绑定

  • v-model

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <script src="../vue.js"></script>
        <title>Document</title>
    </head>
    <body>
        <div class="app">
            <h4>双向绑定</h4>
            <input type="text" v-model = 'msg'>
        </div>
    </body>
    <script>
        new Vue({
            el:'.app',
            data:{
                msg:'panda-pan'
            }
        })
    </script>
    </html>
    
  • 单向实现双向效果

    • 补充:

      • input身上有哪些事件?

        1. focus
        2. blur
        3. change
        4. input
      • 事件有几种绑定形式

        1. js中绑定

          var input = document.querySelector('input')
                  input.oninput = function () {}
                  DOM2级事件   事件监听
          
        2. html结构中绑定

          function load () {}
          
        3. vue中事件绑定形式选择2

      • 事件包含哪几个部分?

        1. 事件源
        2. 事件类型
        3. 事件处理程序
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
    </head>
    <body>
      <div id="app">
          <input type="text" :value = 'val' @input = 'change'>
      </div>
    </body>
    <script src="../vue.js"></script>
    <script>
      new Vue({
        el: '#app',
        data:{
            val:''
        },
        methods:{
           change:function(e){
               this.val = e.target.value
           }
        }
      })
    </script>
    </html>
    

事件

  • 业务: 点击button按钮,弹出input的value
  • 经验: 看到表单,想要得到它的value值,直接v-model
  • vue事件传参
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="app">
      <input type="text" v-model = 'val'>
      <button @click = 'fn($event,val)'>点击</button>
  </div>
</body>
<script src="../vue.js"></script>
<script>
  new Vue({
    el: '#app',
    data:{
        val:''
    },
    methods:{
        fn(e,val){
            console.log(e);
            console.log(val);
        }
    }
  })
</script>
</html>

修饰符

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
    .large{
      width: 200px;
      height: 200px;
      background: red;
    }
    .middle{
      width: 100px;
      height: 100px;
      background: blue;
    }
    .small{
      width: 50px;
      height: 50px;
      background: purple;
    }
  </style>
</head>
<body>
  <div id="app">
    <div class="large" @click = "largeHandler">
      <div class="middle" @click = "middleHandler">
        <div class="small" @click = "smallHandler"></div>
      </div>
    </div>
  </div>
</body>
<script src="../../lib/vue.js"></script>
<script>
  /* 
    业务: 给每一个盒子都加一个事件
   */
  new Vue({
    el: '#app',
    methods: { //方法: 里面存放的是: 事件处理程序
      largeHandler ( e ) {
        e.stopPropagation()
        alert( 'large' )
      },
      middleHandler ( e ) {
        alert( 'middle' )
        e.stopPropagation()
      },
      smallHandler ( e ) {
        alert( 'small' )
        e.stopPropagation()
      }
    }
  })
</script>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
    .large{
      width: 200px;
      height: 200px;
      background: red;
    }
    .middle{
      width: 100px;
      height: 100px;
      background: blue;
    }
    .small{
      width: 50px;
      height: 50px;
      background: purple;
    }
  </style>
</head>
<body>
  <div id="app">
    <div class="large" @click.stop = "largeHandler">
      <div class="middle" @click.stop = "middleHandler">
        <div class="small" @click.stop = "smallHandler"></div>
      </div>
    </div>
    <hr>
    <div class="large" @click.self = "largeHandler">
      <div class="middle" @click.self = "middleHandler">
        <div class="small" @click.self = "smallHandler"></div>
      </div>
    </div>
  </div>
</body>
<script src="../../lib/vue.js"></script>
<script>
  /* 
    业务: 给每一个盒子都加一个事件
   */
  new Vue({
    el: '#app',
    methods: { //方法: 里面存放的是: 事件处理程序
      largeHandler ( e ) {
        alert( 'large' )
      },
      middleHandler ( e ) {
        alert( 'middle' )
      },
      smallHandler ( e ) {
        alert( 'small' )
      }
    }
  })
</script>
</html>

按键修饰符

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <input type="text" @keyup = "fn( val,$event )" v-model = 'val'>
  </div>
</body>
<script src="../../lib/vue.js"></script>
<script>
  /* 
    业务: 按回车弹出input框的value

    键盘事件: 
      keyup
      keydown
      keypress
  */
  new Vue({
    el: '#app',
    data: {
      val: ''
    },
    methods: {
      fn ( val,e ) {
        if ( e.keyCode === 13 ) {
          console.log( val )
        }
      }
    }
  })
</script>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <input type="text" @keyup.13 = "fn( val )" v-model = 'val'>
    <hr>
    <input type="text" @keyup.enter = "fn( val )" v-model = 'val'>
    <hr>
    <input type="text" @keyup.p = "fn( val )" v-model = 'val'>
    
  </div>
</body>
<script src="../../lib/vue.js"></script>
<script>
  /* 
    业务: 按回车弹出input框的value

    键盘事件: 
      keyup
      keydown
      keypress
  */
  new Vue({
    el: '#app',
    data: {
      val: ''
    },
    methods: {
      fn ( val ) {
          console.log( val )
      }
    }
  })
</script>
</html>

模板语法

  • 补充

    • 数据类型有哪些?【 2种说法 】

      1. 第一种类型说法

        初始数据类型: number string null undefined boolean

        引用数据类型: object

      2. 第二种说法

        基本数据类型L: number string boolean
        复杂数据类型: object
        特殊数据类型: null undefined

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <p> number: {{ num }} </p>
    <p> string: {{ str }} </p>
    <p> boolean: {{ bool && 1 || 2 }}</p>
    <p> null: {{ nul && 3 || 4 }}</p>
    <p> undefined: {{ und && 5 || 6 }}  </p>
    <p> array: {{ arr[1] }}</p>
    <p> object: {{ obj.name }}</p>
    <!-- <p> function: {{ ( function() { console.log('fn')} )() }}</p> -->

  </div>
</body>
<script src="../../lib/vue.js"></script>
<script>
    
      
          
          
      
          
  new Vue({
    el: '#app',
    data: {
      num: 10,
      str: 'Gabriel Yan',
      bool: true,
      nul: null,
      und: undefined,
      arr: [1,2,3],
      obj: {
        name: '老彭'
      }
    }
  })
</script>
</html>

计算属性

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="app">
    {{ msg.split('').reverse().join('') }}
    <hr>
    <p> {{ newMsg }} </p>
  </div>
</body>
<script src="../../lib/vue.js"></script>
<script>
  /* 
    业务:将msg这个字符串 反向 输出
    思路: 反向   reverse   数组  

    思考: V应该是用于数据展示,但是我们这么处理,发现V做了一部分逻辑判断,又违背了MVVM

    解决: 计算属性


   */
  new Vue({
    el: '#app',
    data: {
      msg: 'I Love eat 葡萄 '
    },
    computed: {
      //计算属性中存放的都是方法
      newMsg () {
        return this.msg.split('').reverse().join('')
      }
    }
  })
</script>
</html>
案列1:用户名
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <div>
      姓: <input type="text" v-model = "firstName">
    </div>
    <hr>
    <div>
      名: <input type="text" v-model = "lastName">
    </div>
    <hr>
    <div>
      全名: <input type="text" v-model = "fullName">
    </div>
  </div>
</body>
<script src="../../lib/vue.js"></script>
<script>
  new Vue({
    el: '#app',
    data: {
      firstName: '',
      lastName: ''
    },
    computed: {
      fullName () {
        return this.firstName + this.lastName
      }
    }
  })
</script>
</html>
案列2:用户名(改)
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <div>
      姓: <input type="text" v-model = "firstName">
    </div>
    <hr>
    <div>
      名: <input type="text" v-model = "lastName">
    </div>
    <hr>
    <div>
      全名: <input type="text" v-model = "fullName">
    </div>
  </div>
</body>
<script src="../../lib/vue.js"></script>
<script>
  new Vue({
    el: '#app',
    data: {
      firstName: '',
      lastName: ''
    },
    computed: {
      fullName: {
        get () { //getter
          return this.firstName + this.lastName
        },
        set ( val ) { //val就是当前绑定元素的value值
          // val  XXX
          this.firstName = val.slice( 0,1 )
          this.lastName = val.slice( 1 )
        }
      }
    }
  })
</script>
</html>

watch:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="app">
      <div>
        姓: <input type="text" v-model = "firstName">
      </div>
      <hr>
      <div>
        名: <input type="text" v-model = "lastName">
      </div>
      <hr>
      <div>
        全名: <input type="text" v-model = "fullName">
      </div>
  </div>
</body>
<script src="../../person/vue.js"></script>
<script>
  new Vue({
    el: '#app',
    data: {
      firstName: '',
      lastName: '',
      fullName: ''
    },
    watch: { // 侦听 谁?      谁 -> 指的是data中的数据
      // watch中可以存放方法 
      firstName ( val ) {
        // console.log('firstname改变了')
        this.fullName = val + this.lastName
      },
      lastName ( val ) {
        this.fullName = this.firstName + val
      },
      // fullName ( val ) {
      //   this.firstName = val.slice( 0,1 )
      //   this.lastName = val.slice( 1 )
      // }
      fullName: {
        deep: true, //深度监听
        handler (val) { // 处理程序
          this.firstName = val.slice( 0,1 )
          this.lastName = val.slice( 1 )
        }
      }
    }
  })
</script>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值