Vue知识点

Vue与原生js对比

案例:将文本框输入的内容显示到页面中

原生js

在这里插入图片描述

vue

在这里插入图片描述

对比

最明显的区别:vue 中不用操作 dom 元素
这可以让开发者将经历集中到数据处理及业务逻辑开发中

vue

Vue特点

1.国人开发的一个轻量级框架。

2.双向数据绑定,在数据操作方面更为简单。

3.视图,数据,结构分离,不需要进行逻辑代码的修改,只需要操作数据就能完成相关操作。

4.组件化,方便封装和复用

5.虚拟DOM: dom操作是非常耗费性能的,不再使用原 生的dom操作节点,极大解放dom操作

vue框架

![在这里插入图片描述](https://img-blog.csdnimg.cn/2021031017014541.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0xpbHk2ODkxMA==,size_16,color_FFFFFF,

通过 new Vue 创建 vue 实例

el 属性指定当前 vue 实例的挂载点

data 中是模型数据,这些数据依赖于当前的vue实例,
可以在控制台中通过app.msg访问data中数据

数据绑定

所谓属于绑定,就是将 vue 实例中的 data 属性中的变量显示到挂载点(dom结构)中

内容绑定

将 data 中的数据显示成内容(开始标签与结束标签之间)
使用 {{}}

<div id="app">
   <p>{{title}}</p>
  </div>

上面只能显示纯文本,如果要显示 html 内容,需要使用 v-html 指令

<p v-html="content"></p>
属性绑定

将data中的数据作为某个元素的属性的值

使用 v-bind:属性名称 指令,属性可以是内置,也可以是自定义的

<p v-bind:id="id">{{title}}</p>

v-bind: 可以缩写为 :

<p :id="id" :class="title_class">{{title}}</p>
双向数据绑定
什么是数据双向绑定?

vue是一个mvvm框架,即数据双向绑定,即当数据发生变化的时候,视图也就发生变化,当视图发生变化的时候,数据也会跟着同步变化。这也算是vue的精髓之处了。值得注意的是, 我们所说的数据双向绑定,一定是对于UI控件来说的,非UI控件不会涉及到数据双向绑定。 单向数据绑定是使用状态管理工具(如redux)的前提。如果我们使用vuex,那么数据流也是单项的,这时就会和双向数据绑定有冲突解决方法

为什么要实现数据的双向绑定?

在vue中,如果使用vuex,实际上数据还是单向的,之所以说是数据双向绑定,这是用的UI控件来说,对于我们处理表单,vue的双向数据绑定用起来就特别舒服了。

<body>
    <div id="app">
      <!-- <span>{{msg}}</span> -->
      <input type="text" v-model="msg" />
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
      let app = new Vue({
        el: '#app',
        data: {
          msg: 'hello',
        },
      })
    </script>
  </body>
复选框的数据绑定

复选框,v-model 绑定的是 checked 属性
在这里插入图片描述
点击游泳阅读游戏也会被勾选

vue绑定
vue绑定class
<body>
  <div id="app">
    <p v-bind:class="pClass"></p>
    <!-- 对象表示法 -->
    <!-- <p v-bind:class="{active:isActive}">对象表示法</p> -->
    <!-- 多个属性共存 -->
    <!-- 将 class 属性称作静态 class,将 v-bind:class 称作动态class -->
    <p class="base" v-bind:class="{active:isActive,color:isColor}">对象表示法</p>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
    let app = new Vue({
      el: '#app',
      data: {
        id: 11,
        pClass: 'c2',
        isActive: true,
        isColor: true
      },
    })
  </script>
</body>
vue绑定style
<body>
  <div id="app">
    <p :style="{width:w,height:h,backgroundColor:a}"></p>
    <p :style="obj"></p>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
    let app = new Vue({
      el: '#app',
      data: {
        w: '300px',
        h: "200px",
        a: 'lightblue',
        obj: {
          width: '400px',
          height: '100px',
          backgroundColor: 'blue'
        }
      },
    })


  </script>
</body>

表单控件的值

可以用 v-model 指令在表单 、 及 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。

v-model 在内部为不同的输入元素使用不同的 property 并抛出不同的事件:

text 和 textarea 元素使用 value property 和 input 事件;

checkbox 和 radio 使用 checked property 和 change 事件;

select 字段将 value 作为 prop 并将 change 作为事件。

单选框

<body>
    <div id="app">
      <label for="man"></label>
      <input type="radio" id="man" value="man" v-model="gender" />
      <label for="women"></label>
      <input type="radio" id="women" value="women" v-model="gender" />
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
      let app = new Vue({
        el: '#app',
        data: {
          gender: '',
        },
      })
    </script>
  </body>

设置多个单选框的 v-model 为同样的值,就可以省略 name 属性

选择某个单选框后,此单选框的 vlue 属性值会赋值给 gender 属性

设置 gender 属性的值为某个单选框的 value 值,此单选框就会默认选中

下拉菜单

<body>
    <div id="app">
      <select v-model="city">
        <option disabled value="">请选择</option>
        <option value="bj">北京</option>
        <option value="sh">上海</option>
      </select>
      <p>{{city}}</p>
    </div>
  </body>
</html>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
  let app = new Vue({
    el: '#app',
    data: {
      city: '',
    },
  })
</script>
</body>

模板使用js表达

<body>
    <div id="app">
      <p>{{age + 1}}</p>
      <p>{{message.split('').reverse().join('')}}</p>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
      let app = new Vue({
        el: '#app',
        data: {
          age: 10,
          message: '12345',
        },
      })
    </script>
  </body>

列表渲染

我们可以用 v-for 指令基于一个数组来渲染一个列表。

<body>
    <div id="app">
      <ul>
        <li v-for="blog in blogs">{{blog}}</li>
      </ul>
      <ul>
        <li v-for="item in books">{{item.title}}--- {{item.author}}</li>
      </ul>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
      let app = new Vue({
        el: '#app',
        data: {
          blogs: ['今天的天气不是很好', '不知道明天怎样', '现在6度', '外面好冷啊'],
          books: [
            { id: 1, title: '庆余年', author: '忘了' },
            { id: 2, title: '在劫难逃', author: '五百' },
            { id: 3, title: '盗墓笔记', author: '南派三叔' },
          ],
        },
      })
    </script>
  </body>

模板渲染

<body>
    <div id="app">
      <ul>
        <li v-for="item in books">{{item.title}}</li>
      </ul>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
      let app = new Vue({
        el: '#app',
        data: {
          books: [],
        },
        created: function () {
          fetch('data.json')
            .then((res) => {
              return res.json()
            })
            .then((res) => {
              this.books = res
            })
        },
      })
    </script>
  </body>

created 函数会再 vue 实例实例化时执行

//data.json
[
  { "id": 1, "title": "庆余年", "author": "忘了" },
  { "id": 2, "title": "鬼吹灯", "author": "忘了" },
  { "id": 3, "title": "盗墓笔记", "author": "忘了" }
]

条件渲染

可以单独使用 v-if,或者 v-if 和 v-else,或者 v-if 和 v-else-if 搭配使用。
v-if在单独使用的时候,与 v-show 的作用是一样的,都是根据变量的值决定是显示还是隐藏当前元素。

<body>
  <div id="app">
    <h1 v-if="isMary">已婚</h1>
    <h1 v-else>未婚</h1>

    <div v-if="type">v-if</div>
    <div v-show="type">v-show</div>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
    let app = new Vue({
      el: '#app',
      data: {
        isMary: false,
        type: true
      },
    })
  </script>
</body>
v-if 和 v-show 的区别
共同点:都能控制元素的显示和隐藏。

不同点:实现本质方法不同。
v-show本质就是通过控制css中的display设置为none,控制隐藏,只会编译一次; v-if是动态的向DOM树内添加
或者删除DOM元素,若初始值为false,就不会编译了。而且v-if不停的销毁和创建比较消耗性能。

总结:如果要频繁切换某节点,使用v-show(切换开销比较小,初始开销较大)。如果不需要频繁切换某节点使用v-if (初始渲染开销较小,切换开销比较大)

事件处理

js 中可以通过 addEventListener 的方式为元素注册各种事件类型

vue 中通过 v-on 指令为元素注册事件监听,在 methods 对象中定义方法

<body>
  <div id="app">
    <button v-on:click="greet">按钮</button>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
    let app = new Vue({
      el: '#app',
      data: {
        name: 'onlifes'
      },
      methods: {
        greet: function () {
          // 事件当中, this 指向的是当前 vue 实例
          console.log(this.name);
          this.name = 'yhb'
        }
      }
    })
  </script>
</body>
切换元素背景
<title>Document</title>
  <style>
    .base {
      width: 200px;
      height: 200px;
      border: 1px solid black;
    }

    .active {
      background-color: blue;
    }
  </style>
</head>

<body>
  <div id="app">
    <div v-on:click="changeBg" class="base" :class={active:isActive}></div>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
    let app = new Vue({
      el: '#app',
      data: {
        isActive: false
      },
      methods: {
        changeBg: function () {
          this.isActive = !this.isActive
        }
      }
    })
  </script>
</body>
切换壁纸
<title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    html,
    body,
    #app {
      height: 100%;
    }

    nav {
      height: 150px;
      background-color: rgba(0, 0, 0, .2);
      text-align: center;
    }

    img {
      height: 120px;
      margin: 15px 20px;

    }
  </style>
</head>

<body>
  <div id="app" :style="{backgroundImage:bgImg}">
    <nav>
      <img src="./images/1.jpg" v-on:click="changeBg('./images/1.jpg')" alt="">
      <img src="./images/2.jpg" v-on:click="changeBg('./images/2.jpg')" alt="">
      <img src="./images/3.jpg" v-on:click="changeBg('./images/3.jpg')" alt="">
    </nav>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
    let app = new Vue({
      el: '#app',
      data: {
        bgImg: 'url(./images/1.jpg)'
      },
      methods: {
        changeBg: function (url) {
          console.log(url);
          // 切换 bgImg 的值为当前点击的图片的路径
          this.bgImg = `url(${url})`
        }
      }
    })
  </script>
</body>

计算属性

对于任何复杂逻辑,你都应当使用计算属性。

<body>
  <div id="app">
    <!-- {{numbers.split('').reverse().join('')}} -->
    <p>{{reversednumbers}}</p>

    <table>
      <thead>
        <tr>
          <th>编号</th>
          <th>标题</th>
          <th>发表时间</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="item in blogListFormat">
          <td>{{item.id}}</td>
          <td>{{item.title}}</td>
          <td>{{item.create_time}}</td>
        </tr>
      </tbody>
    </table>

  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
  <script>
    let app = new Vue({
      el: '#app',
      data: {
        numbers: '12345',
        blogList: [
          { id: 1, title: '今天真的好冷', create_time: 1614665768000 },
          { id: 2, title: '明天气温就回升了', create_time: 1614579284000 },
          { id: 3, title: '春暖花开', create_time: 1583043284000 }
        ]
      },
      // 用户自定义的方法
      methods: {
        // formatTime: function (a) {
        //   return a
        // }
      },
      // 计算属性
      computed: {
        reversednumbers: function () {
          // 计算属性内部一定要使用 return 返回一个值
          return this.numbers.split('').reverse().join('')
        },
        blogListFormat: function () {
          this.blogList.forEach(item => {
            item.create_time = moment((item.create_time)).format('YYYY-MM-DD HH:mm:ss')
          })
          return this.blogList
        }
      }
    })
  </script>
</body>

data 中和 compoted 中都叫做属性
也就是说 numbers 和 reversednumbers 都叫做属性

1、data 中的属性的值是一个数字、字符串、对象、数组等静态值

2、compited 中的属性叫做计算属性,其值是一个匿名函数

3、匿名函数一定要返回一个值,作为这个属性的值

控制台中修改 create_time 的值测试计算属性,注意不能加上引号

使用方法格式化日期
<body>
  <div id="app">
    <table>
      <thead>
        <tr>
          <th>编号</th>
          <th>标题</th>
          <th>发表时间</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="item in blogList">
          <td>{{item.id}}</td>
          <td>{{item.title}}</td>
          <td>{{formatTime(item.create_time)}}</td>
        </tr>
      </tbody>
    </table>

  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
  <script>

    let app = new Vue({
      el: '#app',
      data: {
        blogList: [
          { id: 1, title: '今天真的好冷', create_time: 1614665768000 },
          { id: 2, title: '明天气温就回升了', create_time: 1614579284000 },
          { id: 3, title: '春暖花开', create_time: 1583043284000 }
        ]
      },
      // 用户自定义的方法
      methods: {
        formatTime: function (a) {
          return moment(a).format('YYYY-MM-DD HH:mm:ss')
        }
      },
    })
  </script>
</body>

侦听器

虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。

vue 中的计算属性是不支持异步操作的,只能计算一些同步的值,但是可以使用 vue-async-computed 插件实现这一点

案例
<body>
  <div id="app">
    <input type="text" v-model="age">
    <br>
    <span>{{message}}</span>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
    /*
    用户在文本框中输入年龄
    1、如果年龄>=12,span中就显示“12虽已经到了入刑年龄”
    2、如果年龄<12岁,span中就显示“还不到入刑年龄”
    */
    let app = new Vue({
      el: '#app',
      data: {
        age: 20,
        message: ''
      },
      methods: {},
      computed: {},
      watch: {
        age: function (newValue, oldValue) {
          // 当 age 属性发生变化时,就会执行这个函数
          if (newValue >= 12) {
            this.message = '12虽已经到了入刑年龄'
          } else {
            this.message = '还不到入刑年龄'
          }
        }
      }
    })
  </script>
</body>
用计算属性实现侦听器
<body>
  <div id="app">
    <input type="text" v-model="age">
    <br>
    <span>{{ageInfo}}</span>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
    let app = new Vue({
      el: '#app',
      data: {
        age: 20
      },
      computed: {
        ageInfo: function () {
          if (this.age >= 12) {
            return '12岁已经到了入刑年龄'
          } else {
            return '还不到入刑年龄'
          }
        }
      }
    })
  </script>
</body>
问答案例
<body>
  <div id="app">
    <label for="question">请输入你的问题</label>
    <input type="text" v-model="question">
    <ul>
      <li v-for="item in answer">
        {{item}}
      </li>
    </ul>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>

  <script>
    let app = new Vue({
      el: '#app',
      data: {
        question: '',
        answer: []
      },
      // 
      methods: {
        getAnswer: function () {
          let that = this
          axios.get('http://localhost:3000/answer.php?q=' + this.question)
            .then(function (response) {
              // console.log(response.data);
              that.answer = response.data
            })
        }
      },
      watch: {
        question: function (newValue) {
          this.getAnswer()
        }
      }
    })
  </script>
</body>

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值