1.从零开始学会Vue--{{基础指令}}

全新专栏带你快速掌握Vue2+Vue3

1.插值表达式{{}}

插值表达式是一种Vue的模板语法

我们可以用插值表达式渲染出Vue提供的数据

1.作用:利用表达式进行插值,渲染到页面中

表达式:是可以被求值的代码,JS引擎会将其计算出一个结果

以下的情况都是表达式:

javascript 复制代码
money + 100
money - 100
money * 10
money / 10 
price >= 100 ? '真贵':'还行'
obj.name
arr[0]
fn()
obj.fn()

2.语法

插值表达式语法:{{ 表达式 }}

html 复制代码
<h3>{{title}}<h3>

<p>{{nickName.toUpperCase()}}</p>

<p>{{age >= 18 ? '成年':'未成年'}}</p>

<p>{{obj.name}}</p>

<p>{{fn()}}</p>

3.错误用法

html 复制代码
1.在插值表达式中使用的数据 必须在data中进行了提供
<p>{{hobby}}</p>  //如果在data中不存在 则会报错

2.支持的是表达式,而非语句,比如:if   for ...
<p>{{if}}</p>

3.不能在标签属性中使用 {{  }} 插值 (插值表达式只能标签中间使用)
<p title="{{username}}">我是P标签</p>

2.基础指令

1.内容渲染指令(v-html)

什么是指令? 在 Vue中,带有 v- 前缀 的 特殊 标签属性

指令的作用: Vue会根据不同的**【指令】** ,针对标签实现不同的**【功能】**

2.条件渲染指令(v-show,v-if,v-else,v-else-if)

v-show与v-if

作用:v-show和v-if 用来控制元素的显示与隐藏
语法:

●v-show = "表达式" 表达式值为 true 显示, false 隐藏

●v-if= "表达式" 表达式值 true显示, false 隐藏
原理:

●v-show 原理: 切换 display:none 控制显示隐藏

●v-if 原理:基于条件判断,是否创建 或 移除元素节点
场景:

●v-show 用在 频繁切换显示隐藏的场景 (京东(JD.COM)-正品低价、品质保障、配送及时、轻松购物! 的手机京东)

●v-if 用在要么显示,要么隐藏,不频繁切换的场景(京东(JD.COM)-正品低价、品质保障、配送及时、轻松购物! 底部提示)

v-else,v-else-if

html 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <p v-if="gender ==1">性别:♂ 男</p>
      <p v-else>性别:♀ 女</p>
      <hr />
      <p v-if="score>90">成绩评定A</p>
      <p v-else-if="score>80">成绩评定B</p>
      <p v-else-if="score>70">成绩评定C</p>
      <p v-else>成绩评定D</p>
    </div>

    <script src="./vue2.7.16.js"></script>
    <script>
      const app = new Vue({
        el: '#app',
        data: {
          gender: 2,
          score: 95,
        },
      });
    </script>
  </body>
</html>

3.事件绑定指令(v-on)

**作用:**注册事件 (注册流程:事件名+ 事件处理逻辑 ,事件源哪去了?)

语法:

  • v-on:事件名="内联语句"
  • v-on:事件名="methods中的函数名"
  • v-on:事件名="methods中的函数名(参数)"

**举例:**button注册事件的三种写法

  • <button v-on:事件名="内联语句">按钮</button>
  • <button v-on:事件名="处理函数">按钮</button>
  • <button v-on:事件名="处理函数(实参)">按钮</button>

注意:v-on: 简写为 @

html 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <button @click="count--">-</button>
      <span>{{ count }}</span>
      <button v-on:click="count++">+</button>
      <hr />
      <button @click="del">-</button>
      <span>{{ num }}</span>
      <button v-on:click="num++">+</button>
      <hr />
      <button @click="changenNum(-5)">-5</button>
      <span>{{ num }}</span>
      <button v-on:click="changenNum(10)">+10</button>
    </div>
    <script src="./vue2.7.16.js"></script>
    <script>
      const app = new Vue({
        el: '#app',
        data: {
          count: 100,
          num: 0,
        },
        methods: {
          del() {
            if (this.num > 0) {
              this.num--;
            }
          },
          changenNum(num) {
            this.num += num;
          },
        },
      });
    </script>
  </body>
</html>

4.属性绑定指令(v-bind)

作用: 给元素的属性动态绑定数据 ->例如:<img src=" " >

语法: v-bind:属性名 ="表达式 "

<img v-bind:src="imgUrl" alt="">

简写: v-bind: 可以简写成 => :bind

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

html 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <button v-show="index > 0" @click="index--">上一页</button>
      <div>
        <img :src="list[index]" alt="" />
      </div>
      <button v-show="index < list.length - 1" @click="index++">下一页</button>
    </div>
    <script src="./vue2.7.16.js"></script>
    <script>
      const app = new Vue({
        el: '#app',
        data: {
          index: 0,
          list: [
            './imgs/11-00.gif',
            './imgs/11-01.gif',
            './imgs/11-02.gif',
            './imgs/11-03.gif',
            './imgs/11-04.png',
            './imgs/11-05.png',
          ],
        },
      });
    </script>
  </body>
</html>

5.列表渲染指令(v-for)

**作用:**基于数据循环,多次渲染整个元素

v-for可以基于哪些数据进行遍历呢?
数组 ,对象,数字,其中基于【数组】遍历是我们常用的方式
遍历数组的语法:

html 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <h3>小黑水果店</h3>
      <ul>
        <li v-for="(item, index) in list">{{ item }} - {{ index }}</li>
      </ul>
      <ul>
        <li v-for="item in list">{{ item }}</li>
      </ul>
    </div>

    <script src="./vue2.7.16.js"></script>
    <script>
      const app = new Vue({
        el: '#app',
        data: {
          list: ['西瓜', '苹果', '鸭梨', '榴莲'],
        },
      });
    </script>
  </body>
</html>

不加 key-原地修改元素 (就地复用)

v-for的默认行为会尝试原地修改元素(就地复用

就是根据数据重新渲染li标签,此时要渲染三次性能不好

加key - 正确排序复用
**加key的作用:**给元素添加唯一标识

加了key之后就只会删除一开始的li

6.双向数据绑定(v-model)

**作用:**v-model是给 表单元素 双向数据绑定的,可以快速 获取 或 设置 表单元素内容

双向数据绑定是什么?

① 数据变化 → 视图自动更新

② 视图变化 → 数据自动更新

**语法:**v-model = '变量'

扩展: v-model还可以给select、checkbox、radio、textarea等表单元素使用

html 复制代码
<!--
 * @Date: 2025-01-02 17:38:11
 * @LastEditors: zl 1077167261@qq.com
 * @LastEditTime: 2025-01-02 17:51:40
 * @FilePath: \vue\vue基本语法\5.v-model.html
-->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <!-- 
      v-model 可以让数据和视图,形成双向数据绑定
      (1) 数据变化,视图自动更新
      (2) 视图变化,数据自动更新
      可以快速[获取]或[设置]表单元素的内容
     -->
      文本:<input type="text" v-model="msg" />
      <p>{{ msg }}</p>
      <hr />
      <input type="radio" value="true" name="option" /> 是
      <input type="radio" value="false" name="option" /> 否
      <hr />
      <input type="checkbox" v-model="ischecked" />
      <p>当前选择: {{ ischecked }}</p>
      <hr />
      <label for="fruit">选择水果:</label>
      <select v-model="selectedFruit" id="fruit">
        <option disabled value="">请选择</option>
        <option value="apple">苹果</option>
        <option value="banana">香蕉</option>
        <option value="orange">橙子</option>
      </select>
      <p>你选择了: {{ selectedFruit }}</p>
      <hr />
      账户:<input type="text" v-model="username" /> <br /><br />
      密码:<input type="password" v-model="password" /> <br /><br />
      <button @click="login">登录</button>
      <button @click="reset">重置</button>
    </div>
    <script src="./vue2.7.16.js"></script>
    <script>
      const app = new Vue({
        el: '#app',
        data: {
          username: '',
          password: '',
          msg: 'hello',
          ischecked: true,
          selectedFruit: '',
        },
        methods: {
          login() {
            console.log(this.username, this.password);
          },
          reset() {
            this.username = '';
            this.password = '';
          },
        },
      });
    </script>
  </body>
</html>
css 复制代码
html,
body {
  margin: 0;
  padding: 0;
}
body {index.css
  background: #fff;
}
button {
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  font-size: 100%;
  vertical-align: baseline;
  font-family: inherit;
  font-weight: inherit;
  color: inherit;
  -webkit-appearance: none;
  appearance: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
  line-height: 1.4em;
  background: #f5f5f5;
  color: #4d4d4d;
  min-width: 230px;
  max-width: 550px;
  margin: 0 auto;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-weight: 300;
}

:focus {
  outline: 0;
}

.hidden {
  display: none;
}

#app {
  background: #fff;
  margin: 180px 0 40px 0;
  padding: 15px;
  position: relative;
  box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
}
#app .header input {
  border: 2px solid rgba(175, 47, 47, 0.8);
  border-radius: 10px;
}
#app .add {
  position: absolute;
  right: 15px;
  top: 15px;
  height: 68px;
  width: 140px;
  text-align: center;
  background-color: rgba(175, 47, 47, 0.8);
  color: #fff;
  cursor: pointer;
  font-size: 18px;
  border-radius: 0 10px 10px 0;
}

#app input::-webkit-input-placeholder {
  font-style: italic;
  font-weight: 300;
  color: #e6e6e6;
}

#app input::-moz-placeholder {
  font-style: italic;
  font-weight: 300;
  color: #e6e6e6;
}

#app input::input-placeholder {
  font-style: italic;
  font-weight: 300;
  color: gray;
}

#app h1 {
  position: absolute;
  top: -120px;
  width: 100%;
  left: 50%;
  transform: translateX(-50%);
  font-size: 60px;
  font-weight: 100;
  text-align: center;
  color: rgba(175, 47, 47, 0.8);
  -webkit-text-rendering: optimizeLegibility;
  -moz-text-rendering: optimizeLegibility;
  text-rendering: optimizeLegibility;
}

.new-todo,
.edit {
  position: relative;
  margin: 0;
  width: 100%;
  font-size: 24px;
  font-family: inherit;
  font-weight: inherit;
  line-height: 1.4em;
  border: 0;
  color: inherit;
  padding: 6px;
  box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
  box-sizing: border-box;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.new-todo {
  padding: 16px;
  border: none;
  background: rgba(0, 0, 0, 0.003);
  box-shadow: inset 0 -2px 1px rgba(0, 0, 0, 0.03);
}

.main {
  position: relative;
  z-index: 2;
}

.todo-list {
  margin: 0;
  padding: 0;
  list-style: none;
  overflow: hidden;
}

.todo-list li {
  position: relative;
  font-size: 24px;
  height: 60px;
  box-sizing: border-box;
  border-bottom: 1px solid #e6e6e6;
}

.todo-list li:last-child {
  border-bottom: none;
}

.todo-list .view .index {
  position: absolute;
  color: gray;
  left: 10px;
  top: 20px;
  font-size: 22px;
}

.todo-list li .toggle {
  text-align: center;
  width: 40px;
  /* auto, since non-WebKit browsers doesn't support input styling */
  height: auto;
  position: absolute;
  top: 0;
  bottom: 0;
  margin: auto 0;
  border: none; /* Mobile Safari */
  -webkit-appearance: none;
  appearance: none;
}

.todo-list li .toggle {
  opacity: 0;
}

.todo-list li .toggle + label {
  /*
		Firefox requires `#` to be escaped - https://bugzilla.mozilla.org/show_bug.cgi?id=922433
		IE and Edge requires *everything* to be escaped to render, so we do that instead of just the `#` - https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/7157459/
	*/
  background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23ededed%22%20stroke-width%3D%223%22/%3E%3C/svg%3E');
  background-repeat: no-repeat;
  background-position: center left;
}

.todo-list li .toggle:checked + label {
  background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23bddad5%22%20stroke-width%3D%223%22/%3E%3Cpath%20fill%3D%22%235dc2af%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22/%3E%3C/svg%3E');
}

.todo-list li label {
  word-break: break-all;
  padding: 15px 15px 15px 60px;
  display: block;
  line-height: 1.2;
  transition: color 0.4s;
}

.todo-list li.completed label {
  color: #d9d9d9;
  text-decoration: line-through;
}

.todo-list li .destroy {
  display: none;
  position: absolute;
  top: 0;
  right: 10px;
  bottom: 0;
  width: 40px;
  height: 40px;
  margin: auto 0;
  font-size: 30px;
  color: #cc9a9a;
  margin-bottom: 11px;
  transition: color 0.2s ease-out;
}

.todo-list li .destroy:hover {
  color: #af5b5e;
}

.todo-list li .destroy:after {
  content: '×';
}

.todo-list li:hover .destroy {
  display: block;
}

.todo-list li .edit {
  display: none;
}

.todo-list li.editing:last-child {
  margin-bottom: -1px;
}

.footer {
  color: #777;
  padding: 10px 15px;
  height: 20px;
  text-align: center;
  border-top: 1px solid #e6e6e6;
}

.footer:before {
  content: '';
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  height: 50px;
  overflow: hidden;
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), 0 8px 0 -3px #f6f6f6,
    0 9px 1px -3px rgba(0, 0, 0, 0.2), 0 16px 0 -6px #f6f6f6,
    0 17px 2px -6px rgba(0, 0, 0, 0.2);
}

.todo-count {
  float: left;
  text-align: left;
}

.todo-count strong {
  font-weight: 300;
}

.filters {
  margin: 0;
  padding: 0;
  list-style: none;
  position: absolute;
  right: 0;
  left: 0;
}

.filters li {
  display: inline;
}

.filters li a {
  color: inherit;
  margin: 3px;
  padding: 3px 7px;
  text-decoration: none;
  border: 1px solid transparent;
  border-radius: 3px;
}

.filters li a:hover {
  border-color: rgba(175, 47, 47, 0.1);
}

.filters li a.selected {
  border-color: rgba(175, 47, 47, 0.2);
}

.clear-completed,
html .clear-completed:active {
  float: right;
  position: relative;
  line-height: 20px;
  text-decoration: none;
  cursor: pointer;
}

.clear-completed:hover {
  text-decoration: underline;
}

.info {
  margin: 50px auto 0;
  color: #bfbfbf;
  font-size: 15px;
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
  text-align: center;
}

.info p {
  line-height: 1;
}

.info a {
  color: inherit;
  text-decoration: none;
  font-weight: 400;
}

.info a:hover {
  text-decoration: underline;
}

/*
	Hack to remove background from Mobile Safari.
	Can't use it globally since it destroys checkboxes in Firefox
*/
@media screen and (-webkit-min-device-pixel-ratio: 0) {
  .toggle-all,
  .todo-list li .toggle {
    background: none;
  }

  .todo-list li .toggle {
    height: 40px;
  }
}

@media (max-width: 430px) {
  .footer {
    height: 50px;
  }

  .filters {
    bottom: 10px;
  }
}
html 复制代码
<!--
 * @Date: 2025-01-02 17:54:51
 * @LastEditors: zl 1077167261@qq.com
 * @LastEditTime: 2025-01-02 18:12:25
 * @FilePath: \vue\vue基本语法\6.小黑记事本.html
-->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="./css/index.css" />
    <title>记事本</title>
  </head>
  <body>
    <!-- 主体区域 -->
    <section id="app">
      <!-- 输入框 -->
      <header class="header">
        <h1>小黑记事本</h1>
        <input placeholder="请输入任务" class="new-todo" v-model="value" />
        <button class="add" @click="add">添加任务</button>
      </header>
      <!-- 列表区域 -->
      <section class="main">
        <ul class="todo-list">
          <li class="todo" v-for="(item,index) in lists" :key="item.id">
            <div class="view">
              <span class="index">{{index+1}}.</span>
              <label>{{item.name}}</label>
              <button class="destroy" @click="del(index)"></button>
            </div>
          </li>
        </ul>
      </section>
      <!-- 统计和清空 -->
      <footer class="footer">
        <!-- 统计 -->
        <span class="todo-count"
          >合 计:<strong> {{lists.length}} </strong></span
        >
        <!-- 清空 -->
        <button class="clear-completed" @click = delAll()>清空任务</button>
      </footer>
    </section>

    <!-- 底部 -->
    <script src="./vue2.7.16.js"></script>
    <script>
      const app = new Vue({
        el: '#app',
        data: {
          id: 3,
          value: '',
          lists: [
            { id: 1, name: '吃饭饭' },
            { id: 2, name: '睡觉觉' },
            { id: 3, name: '打豆豆' },
          ],
        },
        methods: {
          del(idx) {
            this.lists.splice(idx, 1);
          },
          add() {
            if (this.value.trim()) {
              this.lists.unshift({
                id: this.id++,
                name: this.value,
              });
              this.value = '';
            } else {
              alert('请输入任务');
            }
          },
          delAll() {
            this.lists = [];
          }
        },
      });
    </script>
  </body>
</html>

3.指令补充

1.指令修饰符

什么是指令修饰符?

指令修饰符就是通过"."增加一些指令的后缀 ,让这个指令有不同的作用

常用:

① 按键修饰符 @keyup.enter → 键盘回车监听

② v-model修饰符

  • v-model.trim → 去除首尾空格
  • v-model.number → 转数字

③ 事件修饰符

  • @事件名.stop → 阻止冒泡
  • @事件名.prevent → 阻止默认行为
  • @事件名.stop.prevent --->可以连用 即阻止事件冒泡也阻止默认行为
html 复制代码
<!--
 * @Date: 2025-01-03 09:45:28
 * @LastEditors: zl 1077167261@qq.com
 * @LastEditTime: 2025-01-03 09:45:33
 * @FilePath: \vue\2.watch与computed\1.指令修饰符.html
-->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .father {
        width: 200px;
        height: 200px;
        background-color: pink;
        margin-top: 20px;
      }
      .son {
        width: 100px;
        height: 100px;
        background-color: skyblue;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <h3>v-model修饰符 .trim .number</h3>
      姓名:<input v-model.trim="username" type="text" /><br />
      年纪:<input v-model.number="age" type="text" /><br />

      <h3>@事件名.stop → 阻止冒泡</h3>
      <div @click="fatherFn" class="father">
        <div @click.stop="sonFn" class="son">儿子</div>
      </div>

      <h3>@事件名.prevent → 阻止默认行为</h3>
      <a @click.prevent href="http://www.baidu.com">阻止默认行为</a>
    </div>
    <script src="./vue.2.7.js"></script>
    <script>
      const app = new Vue({
        el: '#app',
        data: {
          username: '',
          age: '',
        },
        methods: {
          fatherFn() {
            alert('老父亲被点击了');
          },
          sonFn(e) {
            // e.stopPropagation()
            alert('儿子被点击了');
          },
        },
      });
    </script>
  </body>
</html>

2.v-model在表单元素中的使用

常见的表单元素都可以用 v-model 绑定关联 → 快速 获取设置 表单元素的值

它会根据 控件类型 自动选取 正确的方法 来更新元素

值得注意的是在单选框与下拉菜单中v-model的使用有一些不一样

html 复制代码
<!--
 * @Date: 2025-01-03 10:10:31
 * @LastEditors: zl 1077167261@qq.com
 * @LastEditTime: 2025-01-03 10:30:41
 * @FilePath: \vue\2.watch与computed\2.v-model操作表单.html
-->
<style>
  textarea {
    display: block;
    width: 240px;
    height: 100px;
    margin: 10px 0;
  }
</style>

<div id="app">
  <h3>小黑学习网</h3>
  姓名:
  <input type="text" v-model="user.username" />
  <br /><br />
  是否单身:
  <input type="checkbox" v-model="user.isSingle" />
  <br /><br />
  <!-- 
    前置理解:
      1. name:  给单选框加上 name 属性 可以分组 → 同一组互相会互斥
      2. value: 给单选框加上 value 属性,用于提交给后台的数据
    结合 Vue 使用 → v-model
  -->
  性别:
  <input type="radio" name="sex" value="1" v-model="user.sex" />男
  <input type="radio" name="sex" value="2" v-model="user.sex" />女 <br /><br />
  <!-- 
    前置理解:
      1. option 需要设置 value 值,提交给后台
      2. select 的 value 值,关联了选中的 option 的 value 值
    结合 Vue 使用 → v-model
  -->
  所在城市:
  <select v-model="user.city">
    <option value="101">北京</option>
    <option value="102">上海</option>
    <option value="103">成都</option>
    <option value="104">南京</option>
  </select>
  <br /><br />
  自我描述:
  <textarea v-model="user.desc"></textarea>
  <button @click="show">立即注册</button>
  <hr />
  {{ user }}
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>

<script>
  const app = new Vue({
    el: '#app',
    data: {
      user: {
        username: 'zs',
        isSingle: true,
        sex: '1',
        city: '101',
        desc: '你好我叫zs',
      },
    },
    methods: {
      show() {
        console.log(this.user);
      },
    },
  });
</script>

3.v-bind对样式的操作

为了方便开发者进行样式控制,

Vue 扩展了 v-bind 的语法,可以针对 class 类名style 行内样式 进行控制

① 操作class 类名 语法 :class = "对象/数组"

② 操作style行内样式 语法 :style = "样式对象"

1.操作class类名

操作class 类名 语法 :class = "对象/数组"

  1. 对象形式

如:

**适用场景:**一个类名,来回切换

  1. 数组形式

如:

**适用场景:**批量添加或删除类

html 复制代码
<style>
  * {
    margin: 0;
    padding: 0;
  }
  ul {
    display: flex;
    border-bottom: 2px solid #e01222;
    padding: 0 10px;
  }
  li {
    width: 100px;
    height: 50px;
    line-height: 50px;
    list-style: none;
    text-align: center;
  }
  li a {
    display: block;
    text-decoration: none;
    font-weight: bold;
    color: #333333;
  }
  li a.active {
    background-color: #e01222;
    color: #fff;
  }
</style>
<div id="app">
  <ul>
    <li v-for="(item,idx) in list" :key="item.id">
      <a @click="getActive(idx)" href="#" :class="{active:item.isActive}"
        >{{item.name}}</a
      >
    </li>
  </ul>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      list: [
        { id: 1, name: '京东秒杀', isActive: true },
        { id: 2, name: '每日特价', isActive: false },
        { id: 3, name: '品类秒杀', isActive: false },
      ],
    },
    methods: {
      getActive(idx) {
        this.list.forEach((item, index) => {
          if (idx === index) {
            item.isActive = true;
          } else {
            item.isActive = false;
          }
        });
      },
    },
  });
</script>

2.操作style样式

语法 :style = "样式对象"

如:

**适用场景:**某个具体属性的动态设置

css 复制代码
<style>
  #app {
    margin: 100px auto;
    text-align: center;
  }
  .progress {
    margin: 100px auto;
    height: 25px;
    width: 400px;
    border-radius: 15px;
    background-color: #272425;
    border: 3px solid #272425;
    box-sizing: border-box;
    margin-bottom: 30px;
  }
  .inner {
    width: 50%;
    height: 20px;
    border-radius: 10px;
    text-align: right;
    position: relative;
    background-color: #409eff;
    background-size: 20px 20px;
    box-sizing: border-box;
    transition: all 1s;
  }
  .inner span {
    position: absolute;
    right: -20px;
    bottom: -25px;
  }
</style>

<div id="app">
  <div class="progress">
    <div class="inner" :style="{width:percent +'%'}">
      <span>{{percent}}%</span>
    </div>
  </div>
  <button @click="setPercent(25)">设置25%</button>
  <button @click="setPercent(50)">设置50%</button>
  <button @click="setPercent(75)">设置75%</button>
  <button @click="setPercent(100)">设置100%</button>
  <br />
  <br />
  <button @click="add">开始</button>
  <button @click="percent=0">重置</button>
  <button @click="clear">停止</button>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>

<script>
  const app = new Vue({
    el: '#app',
    data: {
      percent: 50,
      timer: null,
    },
    methods: {
      setPercent(num) {
        this.percent = num;
      },
      add() {
        //清除定时器
        this.clear();
        this.timer = setInterval(() => {
          this.percent += 1;
          if (this.percent >= 100) {
            this.clear();
          }
        }, 300);
      },
      clear() {
        clearInterval(this.timer);
        this.timer = null;
      },
    },
  });
</script>
相关推荐
祈澈菇凉2 小时前
Webpack的基本功能有哪些
前端·javascript·vue.js
小纯洁w2 小时前
Webpack 的 require.context 和 Vite 的 import.meta.glob 的详细介绍和使用
前端·webpack·node.js
想睡好3 小时前
css文本属性
前端·css
qianmoQ3 小时前
第三章:组件开发实战 - 第五节 - Tailwind CSS 响应式导航栏实现
前端·css
记得早睡~3 小时前
leetcode150-逆波兰表达式求值
javascript·算法·leetcode
zhoupenghui1683 小时前
golang时间相关函数总结
服务器·前端·golang·time
White graces3 小时前
正则表达式效验邮箱格式, 手机号格式, 密码长度
前端·spring boot·spring·正则表达式·java-ee·maven·intellij-idea
庸俗今天不摸鱼3 小时前
Canvas进阶-4、边界检测(流光,鼠标拖尾)
开发语言·前端·javascript·计算机外设
bubusa~>_<4 小时前
解决npm install 出现error,比如:ERR_SSL_CIPHER_OPERATION_FAILED
前端·npm·node.js
yanglamei19624 小时前
基于Python+Django+Vue的旅游景区推荐系统系统设计与实现源代码+数据库+使用说明
vue.js·python·django