Vue0830

v-bind

v-bind动态属性数据绑定

src属性中的数据它是通过data数据源中得到的

标准语法:v-bind:属性="动态数据"

简写语法::属性="动态数据"

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

v-for

循环 vue对于v-for进行了增强,它可以用for/of 都可以,而且两者都可以进行对象的迭代

语法:语法:vue2中小括号可以写,也可以不写,在vue3中一定要写小括号

注:vue2中如果一个标签中同时有v-if和v-for,则v-for的优先级高于v-if,所以在vue2中不推荐两者在一个标签中

vue3中v-if优先级高于v-for

v-for="(元素,索引) in/of 对象"

v-for="(元素,键名,索引)" in/of 对象

注:v-for建议给循环项每个添加一个key来做标识,用于提升性能,key值,一定是唯一不重复的,不建议使用循环的索引当作key值,一般在和后台请求数据时,要求后台提供一个唯一的id给我们

 <li v-for="(item,index) in user">{{index}} -- {{item}}</li> 
 <li v-for="item,index in user">{{index}} -- {{item}}</li> 
 <li v-for="item,index in user" :key="item.id">{{item.name}}</li>
 
  <script>
    const vm = new Vue({
      el: '#app',
      data: {
        // user: ['张三', '李四', '王五']
        // user: [{ id: 2, name: '李四' }, { id: 1, name: '张三' }]
        user: { id: 1, name: '张三' }
      }
    })
  </script>

循环对象

<div v-for="item,key,index in user" :key="key">{{index}} -- {{key}} -- {{item}}</div>

v-on事件

v-on:事件名="实现的方法[此方法定义在vue配置中的methods中]"

v-on使用很频繁 @事件名="方法"

绑定的方法,它可以写小括号,也可以不写小括号

<button @click="clickFn">点击事件</button>

注:methods中定义方法不用使用箭头函数,但是在方法体中建议使用箭头函数,用来保持this指向

v-on事件对象

如果你绑定方法时,没有写小括号,则vue在解析时,会自动给你映射一个event给绑定方法

<button @click="clickFn">点击事件</button>

如果你绑定方法时,有写小括号,则需要手动把event对象传过去$event,$event可以传多个,但是建议只传一个,一般写在第1位或最后1位

<button uname="李四" data-uname="张三" @click="evt=>clickFn($event)">点击事件</button>

 <script>
    const vm = new Vue({
      el: '#app',
      data: {
        num: 100
      },
      // 注:methods中定义方法不用使用箭头函数,但是在方法体中建议使用箭头函数,用来保持this指向
      methods: {
        // event可以用它来完成dom数据的获取
        clickFn(evt) {
          this.num++
          console.log(evt.target.getAttribute('uname'));
          console.log(evt.target.dataset.uname)
        },
        onEnter(evt) {
          if (evt.keyCode === 13) {
            console.log(evt.target.value);
          }
        }
      }
    })
  </script>

todolist案例

<!-- 第1步: 引入vue库文件 -->
  <script src="./js/vue.js"></script>
</head>
​
<body>
  <!-- 第2步:挂载点 -->
  <div id="app">
    <input placeholder="请输入内容" type="text" @keyup="onEnter">
    <hr>
    <ul>
      <!-- 条件渲染 -->
      <li v-if="todos.length===0">无任务</li>
      <li v-else v-for="item,index in todos" :key="item.id">
        <span>{{item.title}}</span>
        <!-- <span @click="del(item.id)">删除</span> -->
        <span @click="del(index)">删除</span>
      </li>
    </ul>
​
  </div>
​
  <!-- 第3步:实例化vue -->
  <script>
    const vm = new Vue({
      el: '#app',
      data: {
        todos: []
      },
      methods: {
        onEnter(evt) {
          if (evt.keyCode === 13) {
            this.todos.push({
              id: Date.now(),
              title: evt.target.value.trim()
            })
            evt.target.value = ''
          }
        },
        // del(id) {
        //   // 删除
        //   this.todos = this.todos.filter(item => item.id != id)
        // }
        del(index) {
          // 删除 它可以使用 vue中提供的变异方法splice来完成,用此方法它会触发视图更新
          this.todos.splice(index, 1)
        }
      }
    })
  </script>
​

事件修饰符

多个修饰符,通过点来连接操作

动态样式

class样式的动态添加,对象和数组方式

对象: {key它就是样式名称:布尔值【true生效,false不生效】} -- 一般用于开关显示

<div :class="titleClass">我是一个标题</div>

数组:[元素样式名称] 一般对于追加新样式,使用数组

addStyle() {
// 给数组添加元素,元素就是样式名称,这样它会就追加样式
// push unshift shift pop splice sort reverse 调用时都会让视图更新
          this.titleStyle.push('active')
          this.titleStyle.push('font30')
        }

//地址变了 所以会显示
this.titleClass = { ...this.titleClass, font30: true }

let titleClass=JSON.parse(JSON.stringify(this.title.titleClass));
titleClass.font30=ture;
this.titleClass=titleClass;
this.titleClass = Object.assign({}, this.titleClass, { font30: true })

动态给对象添加成员属性

 
this.$set(this.titleClass, 'font30', true)
let obj =  Object.assign(参数1地址和返回值地址是同一个地址)

动态样式-style

//style样式的动态添加,对象和数组方式
//对象
<div :style="{color:'blue',fontSize:'30px'}">我是一个标题</div>
//数组
<div :style="[{color:'blue'},{fontSize:'30px'}]">我是一个标题</div>

v-model

v-model它是一个语法糖,value和事件的综合体

用户登录案例

 <script src="./js/vue.js"></script>
</head>
​
<body>
  <!-- 第2步:挂载点 -->
  <div id="app">
    <div>
      <label>
        账号:
        <input type="text" v-model="username">
      </label>
    </div>
    <div>
      <label>
        密码:
        <input type="text" v-model="password">
      </label>
    </div>
    <div>
      <textarea v-model="intro"></textarea>
    </div>
    <div>
      <button @click="dologin">登录系统</button>
    </div>
  </div>
​
  <!-- 第3步:实例化vue -->
  <script>
    const vm = new Vue({
      el: '#app',
      data: {
        username: '',
        password: '',
        intro: 'afewlkfjewl'
      },
      methods: {
        dologin() {
          console.log(this.username, this.password, this.intro);
        }
      }
    })
  </script>

单个复选框

单个复选框,定义的数据类型为布尔类型 true选中,false未选中

click事件可以用,但它是的状态有太过提前,用onchange事件,改变后来获取

<input type="checkbox" @change="clickFn">
​
 <script>
    const vm = new Vue({
      el: '#app',
      data: {
        // 单个复选框一定要用布尔类型
        checked: false
      },
      methods: {
        clickFn(evt) {
          console.log(evt.target.checked);
        }
      }
    })
  </script>

多个复选框

多个复选框,定义的数据类型为数组

指定它的value值

 <ul>
        <li>
          <input type="checkbox" value="html" v-model="lessons">html
        </li>
        <li>
          <input type="checkbox" value="css" v-model="lessons">css
        </li>
        <li>
          <input type="checkbox" value="js" v-model="lessons">js
        </li>
      </ul>
      <hr>
      <div>{{lessons}}</div>
    </div>
  </div>
​
  <!-- 第3步:实例化vue -->
  <script>
    const vm = new Vue({
      el: '#app',
      data: {
        lessons: ["js",'css']
      },
      methods: {
      }
    })
  </script>
​

全选

<div id="app">
 <div>
 <input type="checkbox" v-model="checked" @change="onSelected">
  <li>
          <input type="checkbox" value="html" @change="selectlesson" v-model="lessons">html
        </li>
        <li>
          <input type="checkbox" value="css" @change="selectlesson" v-model="lessons">css
        </li>
        <li>
          <input type="checkbox" value="js" @change="selectlesson" v-model="lessons">js
        </li>
      </ul>
      <hr>
      <div>{{lessons}}</div>
    </div>
  </div>
  
   <script>
    const vm = new Vue({
      el: '#app',
      data: {
        lessons: [],
        checked: false
      },
      methods: {
        onSelected(evt) {
          // 选中了
          if (evt.target.checked) {
            this.lessons = ["js", 'html', 'css']
          } else {
            this.lessons = []
          }
        },
        selectlesson() {
          // 只要来操作数据源就可以改变视图
          //==判断   当this.lessons.length == 3时为true,赋值给checked
          this.checked = this.lessons.length == 3
        }
      }
    })
  </script>

单选和下拉

<div id="app">
    <div>
      <h3>{{sex}} -- {{city}}</h3>
      <!-- 定义的数据类型为字符串 -->
      <label>
        <input type="radio" value="先生" v-model="sex">建行
      </label>
      <label>
        <input type="radio" value="女神" v-model="sex">招行
      </label>
    </div>
    <hr>
    <div>
      <select v-model="city">
        <option value="0">==选择==</option>
        <option value="wh">芜湖</option>
        <option value="bj">北京</option>
      </select>
    </div>
​
  </div>
​
  <!-- 第3步:实例化vue -->
  <script>
    const vm = new Vue({
      el: '#app',
      data: {
        sex: '先生',
        city: '0'
      }
    })
  </script>
​

v-model

<!-- v-model修饰符 -->
    <!-- 延时更新数据源中的数据 -->
    <!-- <input v-model.lazy="title"> -->
    <!-- 去空格 trim -->
    <!-- <input v-model.trim="title"> -->
    //表单提交的数据都变成了字符串
    <!-- 转为数值 number -->
     <input type="number" v-model.number="n1">
    +
    <input type="number" v-model.number="n2">
    = {{n1+n2}}

购物车

<div id="app">
    <table border="1" width="600">
      <tr>
        <th>序号</th>
        <th>名称</th>
        <th>单价</th>
        <th>数量</th>
        <th>操作</th>
      </tr>
      <tr v-for="item,index in carts">
        <td>{{index+1}}</td>
        <td>{{item.name}}</td>
        <td>{{item.price}}</td>
        <td>
          <!-- <button @click="setNum(1,item)">+++</button> -->
          <button @click="setNum(1,index)">+++</button>
          <input type="number" v-model="item.num">
          <!-- <button @click="setNum(-1,item)">---</button> -->
          <button @click="setNum(-1,index)">---</button>
        </td>
        <td>
          <button @click="del(index)">删除</button>
        </td>
      </tr>
    </table>
    <hr>
    <h3>
      合计:
      {{totalPrice()}}
    </h3>
​
  </div>
​
  <!-- 第3步:实例化vue -->
  <script>
    const vm = new Vue({
      el: '#app',
      data: {
        carts: [
          { id: 1, name: '小米12pro', price: 1, num: 1 },
          { id: 2, name: '华为手机', price: 2, num: 1 },
          { id: 3, name: '水果手机', price: 3, num: 1 },
        ]
      },
      methods: {
        /* setNum(n, item) {
          item.num += n
        }, */
        setNum(n, index) {
          this.carts[index].num += n
          // if (this.carts[index].num <= 1) this.carts[index].num = 1
          // if (this.carts[index].num >= 3) this.carts[index].num = 3
          // 用最大值和最小值来限制它的范围,可以了解一下
          this.carts[index].num = Math.min(3, Math.max(1, this.carts[index].num))
        },
        totalPrice() {
          // 聚合运算
          return this.carts.reduce((prev, { price, num }) => {
            prev += price * num
            return prev
          }, 0)
        },
        del(index) {
          confirm('确定删除') && this.carts.splice(index, 1)
        }
      }
    })
     </script>

持久化

 function getCarts() {
      return !window.localStorage.getItem('carts') ? [{ id: 1, name: '小米12pro', price: 1, num: 1 },
      { id: 2, name: '华为手机', price: 2, num: 1 },
      { id: 3, name: '水果手机', price: 3, num: 1 }] : JSON.parse(window.localStorage.getItem('carts'))
    }
    function setCarts(carts) {
      window.localStorage.setItem('carts', JSON.stringify(carts))
    }

自定义指令

自定义指令常用钩子函数

bind 第一次绑定到元素时调用

inserted 被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)

update 数据更新时调用

componentUpdated 指令所在组件的 VNode 及其子 VNode 全部更新后调用。

unbind 只调用一次,指令与元素解绑时调用。

// 定义自定义指令
    // 全局 和 局部
    // 全局定义,所有的组件或vue的实例都会生效,可以使用
    // 对象写法,它提供5个钩子函数
    // Vue.directive('指令名称,不需要写v-开头',对象或函数)
    /* Vue.directive('red', {
      // bind 第一次绑定到元素时调用
      bind(el, bindings) {
        console.log('bind');
        // 通过dom操作来完成对于当前绑定的标签添加css样式
        // el.style.color = 'red'
        // el.style.fontSize = '30px'
        // cssText方案,现在推荐
        // el.style.cssText = 'font-size: 30px;\
        //                     color: blue;'
        el.style.cssText = `color:red;font-size:30px`
      },
      // inserted
      inserted(el, bindings) {
        console.log('inserted');
      },
      // update
      update(el, bindings) {
        console.log('update');
      },
      // componentUpdate
      componentUpdated(el, bindings) {
        console.log('componentUpdated');
      },
      // unbind
      unbind(el, bindings) {
        console.log('unbind');
      },
    }) */
​
    const vm1 = new Vue({
      el: '#app1',
      data: {
        isShow: true,
        title: '我是一个标题111'
      },
      // 定义局部指令,只有当前的实例能用
      directives: {
        red: {
          // bind它还没有绑定到父元素中,初始化
          bind(el) {
            el.style.cssText = `color:red;font-size:30px`
            const divDom = document.createElement('div')
            divDom.innerHTML = '我是它的兄弟'
            el.appendChild(divDom)
          },
          // inserted(el) {
          //   console.log(el.parentNode);
          // }
        },
        auth: {
          inserted(el) {
            // query/search 字符串  ==> 对象
            // if (location.search != '?username=admin') {
            //   el.remove()
            // }
            // URLSearchParams它是html5提供的新的Api方法,用于获取url地址中的search转为对象
            let urlSearch = new URLSearchParams(location.search)
            // console.log(urlSearch.get('username'));
            if (urlSearch.get('username') != 'admin') {
              // 以前兼容性更好的写法,但是现在可以不管
              // el.parentNode.removeChild(el)
              el.remove()
            }
          }
        }
      }
    })
​
    const vm2 = new Vue({
      el: '#app2',
      data: {
      },
      directives: {
        red: {
          bind(el) {
            el.style.cssText = `color:blue;font-size:30px`
          }
        }
      }
    })
  </script>

模块化

const validateMethod = {
      phone(el) {
        // 手机号码
        let reg = /^1[3-9]\d{9}$/
        if (!reg.test(el.value)) {
          // 不合法
          el.style.color = 'red'
          if (!el.nextSibling) {
            const spanDom = document.createElement('span')
            spanDom.innerHTML = '不合法,修改一下'
            // el.parentNode?.appendChild(spanDom)
            el.parentNode && el.parentNode.appendChild(spanDom)
          }
        } else {
          el.style.color = 'black'
          el.nextSibling && el.nextSibling.remove()
        }
        console.log('phone');
      },
​
      email(el, value) {
        console.log('email')
      },
      str(el, value) {
        if (value) {
          if (el.value.length > value.len) {
            if (!el.nextSibling) {
              const spanDom = document.createElement('span')
              spanDom.innerHTML = value.msg
              el.parentNode?.appendChild(spanDom)
            }
          } else {
            el.nextSibling?.remove()
          }
        }
      }
    }
​
    Vue.directive('validate', (el, { value, modifiers }) => {
​
      Object.keys(modifiers).forEach(name => {
        validateMethod[name](el, value)
      })
    })
​
    const vm1 = new Vue({
      el: '#app',
      data: {
        phone: '13525125121',
        email: 'aa@aa.com',
        str: 'aaa'
      },
      methods: {
      }
    })
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值