初学Vue(2)

20,696次阅读
没有评论

共计 9686 个字符,预计需要花费 25 分钟才能阅读完成。

文章目录

  • 监视属性 watch
    • 深度监视
    • computed 和 watch 之间的区别
  • 绑定样式(class style)
  • 条件渲染
  • 列表渲染
    • 基本列表
    • key 的原理
    • 列表过滤
    • 列表排序
    • 收集表单中的数据 v-model
    • 过滤器(Vue3 已移除)

监视属性 watch

  1. 当被监视的属性变化时,回调函数自动调用,进行相关操作
  2. 监视的属性必须存在,才能进行监视
  3. 监视的两种写法:
    a. new Vue 时传入 watch 配置
    b. 通过 vm.$watch 监视
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: {
        immediate: true,  
        
        handler(newValue, oldValue){
          console.log('newValue:', newValue);
          console.log('oldValue:', oldValue);
        },
      }

      
      isHot(newValue,oldValue){
        console.log('isHot 被修改了')
      }
    }
  })

  
  
  vm.$watch('isHot',{
    immediate: true,  
    
    handler(newValue, oldValue){
      console.log('newValue:', newValue);
      console.log('oldValue:', oldValue);
    },
  })

  
  vm.$watch('isHot',(newValue,oldValue){
    console.log('isHot 被修改了',newValue)
  })
script>

深度监视

  1. Vue 中的 Watch 默认不监测对象内部值的改变(一层)
  2. 配置 deep:true 可以监测对象内部值改变(多层)
  3. 备注:
    a. Vue 自身可以监测对象内部值的改变,但 Vue 提供的 watch 默认不可以
    b. 使用 watch 时数据的具体结构,决定是否采用深度监视
body>
    div id="root">
        h2>今天天气很{{info}}h2>
        button @click="changeWeather">切换天气button>
        hr>
        h3> a 的值是:{{numbers.a}}h3>
        button @click="numbers.a++">点我让 a +1button>
        br>
        h3> b 的值是:{{numbers.b}}h3>
        button @click="numbers.b++">点我让 b +1button>
    div>
body>
script type="text/javascript">
    Vue.config.productionTip = false;

    const vm = new Vue({
        el: '#root',
        data: {
            isHot: true,
            numbers:{
                a: 1,
                b: 1
            }
        },
        computed: {
            info() {
                return this.isHot ? '炎热' : '凉爽'
            }
        },
        methods: {
            changeWeather() {
                this.isHot = !this.isHot
            }
        },
        watch:{
            isHot: {
                
                
                handler(newValue, oldValue){
                    console.log('newValue:', newValue);
                    console.log('oldValue:', oldValue);
                },
            },
            
            'numbers.a':{
                
                handler(){
                    console.log('a 被改变了');
                },
            },

            
            numbers: {
                deep: true,
                handler() {
                    console.log('a 被改变了');
                },
            }

          
          vm.$watch('isHot',{
            
          })
        }
    })
script>

computed 和 watch 之间的区别

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

绑定样式(class style)

  1. class 样式
    写法:class=“xxx”xxx 可以是字符串、对象、数组
    字符串写法适用于:类名不确定,要动态获取
    对象写法适用于:要绑定多个样式,个数不确定,名字也不确定
    数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用
  2. style 样式
    :style=“{fontSize:xxx}”其中 xxx 是动态值
    :style=“[a,b]”其中 a、b 是样式对象
div id="root">
  
  div class="basic" :class="mood" @click="changeMood">{{name}}div>br>br>
  
  div class="basic" :class="arr" @click="changeMood">{{name}}div> br>br>
  
  div class="basic" :class="arr" @click="changeMood">{{name}}div>br>br>
  
  div class="basic" :style="styleObj">{{name}}div>br>br>
  
  div class="basic" :style="styleArr">{{name}}div>
div>

script type="text/javascript">
  Vue.config.productionTip = false;  

  new Vue({
    el: '#root',
    data: {
      name: '檀健次',
      mood: 'normal',
      arr: ['attjc1', 'attjc2', 'attjc3'],
      classObj: {
        attjc1: false,
        attjc2: true,
        attjc3: true
      },
      styleObj: {
        color: 'white',
        backgroundColor: 'orange'
      },
      styleArr: [
        {
          fontSize: '30px'
        }
      ]
    },
    methods: {
      changeMood() {
        
        const arr = ['happy', 'sad', 'normal']
        this.mood = arr[Math.floor(Math.random() * arr.length)]
      }
    }
  })
script>

条件渲染

  1. v-if
    写法:
    (1) v-if=“表达式”
    (2) v-else-if=“表达式”
    (3) v-else=“表达式”
    适用于:切换频率较低的场景
    特点:不展示的 DOM 元素直接被移除
    注意:v-if 可以和:v-else-is、v-else 一起使用,但要求结构不能被打断
  2. v-show
    写法:v-show=“表达式”
    适用于:切换频率较高的场景
    特点:不展示的 DOM 元素未被移除,仅仅是使用样式隐藏掉
  3. 备注:使用 v -if 的时候,元素可能无法获取到,而使用 v -show 一定可以获取到
div id="root">
  h2>当前值是:{{n}}h2>
  button @click="n++">点我 n +1button>

  
  

  
  

  
  div v-if="n === 1">tjcdiv>
  div v-else-if="n === 2">txddiv>
  div v-else-if="n === 3">tlqdiv>
  div v-else>哈哈div>
div>

script type="text/javascript">
  Vue.config.productionTip = false;  

  new Vue({
    el: '#root',
    data: {
      name: '檀健次',
      n: 1
    }
  })
script>

列表渲染

基本列表

v-for 指令

  1. 用于展示列表数据
  2. 语法:v-for=“(item,index) in xxx”:key=“yyy”
  3. 可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)
div id="root">
  
  h2>人员列表(遍历数组)h2>
  ul>
    li v-for="(p,index) in persons" :key="index">
      {{p.name}}--{{p.age}}
    li>
  ul>
  
  h2>汽车信息h2>
  ul>
    li v-for="(value,k) of car" :key="k">
      {{value}}--{{k}}
    li>
  ul>
  
  h2>循环指定次数h2>
  ul>
    li v-for="n in 5" :key="n">
      {{n}}
    li>
  ul>
div>

script type="text/javascript">
  Vue.config.productionTip = false;  

  new Vue({
    el: '#root',
    data: {
      persons:[
        {id: '001',name: '张三',age: 18}
        ,{id: '002',name: '李四',age: 19}
        ,{id: '003',name: '王五',age: 20}
      ],
      car:{
        name: '奔驰',
        price: '100 万',
        color: '黑色'
      }
    }
  })
script>

key 的原理

初学 Vue(2)

  1. 虚拟 DOM 中 key 的作用:
    key 是虚拟 DOM 对象的标识,当数据发生变化时,Vue 会根据【新数据】生成【新的虚拟 DOM】,随后 Vue 进行【新虚拟 DOM】与【旧 DOM】的差异比较,比较规则如下:
  2. 对比规则:
    a. 旧虚拟 DOM 中内容没变,直接使用之前的真实 DOM
    ⅰ. 若虚拟 DOM 中内容没变,直接使用之前的真实 DOM
    ⅱ. 若虚拟 DOM 中内容变了,则生成新的真实 DOM,随后替换掉页面中之前的真实 DOM
    b. 旧虚拟 DOM 中未找到与新虚拟 DOM 相同 key,创建新的真实 DOM,随后渲染到页面
  3. 用 index 作为 key 可能会引发的问题:
    a. 若对数据进行:逆序添加、逆序删除等破坏顺序操作:
    b. 如果结构中还包含输入类 DOM:会产生错误 DOM 更新 ==> 界面有问题
  4. 开发中如何选择 key?:
    a. 最好使用每条数据的唯一标识作为 key,比如 id、手机号、身份证号、学号等唯一值
    b. 如果不存在对数据的逆序添加、逆序删除等破坏顺序的操作,仅用于渲染列表用于展示,使用 index 作为 key 是没有问题的

列表过滤

div id="root">
  
  h2>人员列表h2>
  input type="text" placeholder="请输入名字" name="" id="" v-model="keyWord">
  ul>
    li v-for="(p,index) in filPersons" :key="index">
      {{p.name}}--{{p.age}}
    li>
  ul>
div>

script type="text/javascript">
  Vue.config.productionTip = false;  

  
  new Vue({
    el: '#root',
    data: {
      keyWord: '',
      persons: [
        { id: '001', name: '檀健次', age: 18 }
        , { id: '002', name: '赵丽颖', age: 19 }
        , { id: '003', name: '成毅', age: 20 }
      ],
      filPersons: []
    },
    watch: {
      keyWord: {
        immediate: true,
        handler(val) {
          this.filPersons = this.persons.filter((p) => {
            return p.name.indexOf(val) !== -1
          })
        }
      }
    }
  })

  
  new Vue({
    el: '#root',
    data: {
      keyWord: '',
      persons: [
        { id: '001', name: '檀健次', age: 18 }
        , { id: '002', name: '赵丽颖', age: 19 }
        , { id: '003', name: '成毅', age: 20 }
      ]
    },
    computed:{
      filPersons(){
        return this.persons.filter((p) => {
          return p.name.indexOf(this.keyWord) !== -1
        })
      }
    }
  })
script>

列表排序

div id="root">
  
  h2>人员列表h2>
  input type="text" placeholder="请输入名字" name="" id="" v-model="keyWord">
  button @click="sortType = 2">年龄升序button>
  button @click="sortType = 1">年龄降序button>
  button @click="sortType = 0">原顺序button>
  ul>
    li v-for="(p,index) in filPersons" :key="index">
      {{p.name}}--{{p.age}}
    li>
  ul>
div>

script type="text/javascript">
  Vue.config.productionTip = false;  

  new Vue({
    el: '#root',
    data: {
      keyWord: '',
      sortType: 0,  
      persons: [
        { id: '001', name: '檀健次', age: 18 }
        , { id: '002', name: '檀小呆', age: 2 }
        , { id: '003', name: '赵丽颖', age: 19 }
        , { id: '004', name: '成毅', age: 20 }
        , { id: '005', name: '虞书欣', age: 20 }
      ]
    },
    computed: {
      filPersons() {
        const arr = this.persons.filter((p) => {
          return p.name.indexOf(this.keyWord) !== -1
        })
        if (this.sortType) {
          arr.sort((a, b) => {
            return this.sortType === 1 ? b.age - a.age : a.age - b.age
          })
        }
        return arr
      }
    }
  })
script>

初学 Vue(2)

  1. 如何监测数组中的数据
    数组更新检测
    通过包裹数组更新元素的方法实现,本质就是做了两件事:
    a. 调用原生对应的方法对数组进行更新
    b. 重新解析模板,进而更新页面
    初学 Vue(2)没有 get、set 方法,不能直接操作数组,通过索引值等修改,Vue 不起效
    可通过七个方法修改:
    1). push 向数组的末尾添加一个或多个元素,并返回新的长度
    2). pop 向数组的末尾添加一个或多个元素,并返回新的长度
    3). shift 用于把数组的第一个元素从其中删除,并返回第一个元素的值。改变数组的长度
    4). unshift 向数组的开头添加一个或更多元素,并返回新的长度。该方法将改变数组的数目
    5). splice 用于添加或删除数组中的元素
    6). sort 用于对数组的元素进行排序。排序顺序可以是字母或数字,并按升序或降序。默认排序顺序为按字母升序
    注意 使用数字排序,你必须通过一个函数作为参数来调用。函数指定数字是按照升序还是降序排列。
    7). reverse 颠倒数组中元素的顺序
    原理:上述七个方法和原来数组的七个方法有所不同,是 Vue 继承后重新包装数组中长用的方法
    初学 Vue(2)
    如果不是用上述方法,也可以用 Vue.set()和 vm.$set()
    在这里插入图片描述
  2. Vue.set()
    返回值:设置的值
    用法:
    像响应式对象中添加一个 property 并确保这个新 property 同样是响应式的,且触发视图更新。它必须用于响应式对象上添加新 property, 因为 Vue 无法探测普通的新增 property(比如 this.myObject.newProperty = ‘hi)
    注意:对象不能是 Vue 实例,或者 Vue 实例的根数据对象。
div id="root">
  h1>学校信息h1>
  h2>学校名称:{{name}}h2>
  h2>学校地址:{{address}}h2>
  hr>
  h1>学生信息h1>
  button @click="addSex">添加一个性别属性button>
  h2>姓名:{{student.name}}h2>
  h2 v-if="student.sex">性别:{{student.sex}}h2>
  h2>年龄:真实{{student.age.rAge}}, 对外{{student.age.sAge}}h2>
  h2>朋友h2>
  ul>
    li v-for="(f,index) in student.friends" :key="index">
      {{f.name}}--{{f.age}}
    li>
  ul>
div>

script type="text/javascript">
  Vue.config.productionTip = false;  

  new Vue({
    el: '#root',
    data: {
      name: '河南科技学院',
      address: '新乡',
      student: {
        name: '张三',
        
        age: {
          rAge: 18,
          sAge: 19
        },
        friends: [
          { name: '李四', age: 20 },
          { name: '王五', age: 21 },
          { name: '赵六', age: 22 }
        ]
      }
    },
    methods: {
      addSex(){
        Vue.set(this.student, 'sex','女' )
      }
    }
  })
script>
  1. 数据劫持
    指的是在访问或者修改对象的某个属性时,通过一段代码拦截这个行为,进行额外的操作或者修改返回结果。
    比较典型的是 Object.defineProperty()和 ES2016 中新增的 Proxy 对象。数据劫持最著名的应用当属双向绑定,这也是一个已经被讨论烂了的面试必考题。例如 Vue 2.x 使用的是 Object.defineProperty()(Vue 在 3.x 版本之后改用 Proxy 进行实现)。
  2. 大合集
div id="root">
  h1>学校信息h1>
  button @click="student.age++">年龄 + 1 岁button>br>
  button @click="addSex">添加性别属性,默认值:女button>br>
  button @click="student.sex = '未知 '"> 修改性别button>br>
  button @click="addFriend">在列表首位添加朋友button>br>
  button @click="updateFriendName">修改第一个朋友的名字为:张三button>br>
  button @click="updateHobby">修改第一个爱好为:开车button>br>


  h2>学校名称:{{name}}h2>
  h2>学校地址:{{address}}h2>
  hr>
  h1>学生信息h1>
  h2>姓名:{{student.name}}h2>
  h2>年龄:{{student.age}}h2>
  h2 v-if="student.sex">性别:{{student.sex}}h2>
  ul>
    li v-for="item in student.hobby" :key="item">
      {{item}}
    li>
  ul>
  h2>朋友h2>
  ul>
    li v-for="(f,index) in student.friends" :key="index">
      {{f.name}}--{{f.age}}
    li>
  ul>
div>

script type="text/javascript">
  Vue.config.productionTip = false;  

  const vm = new Vue({
    el: '#root',
    data: {
      name: '河南科技学院',
      address: '新乡',
      student: {
        name: '张三',
        
        age: 18,
        hobby: ['吃饭', '睡觉', '打游戏'],
        friends: [
          { name: '李四', age: 20 },
          { name: '王五', age: 21 },
          { name: '赵六', age: 22 }
        ]
      }
    },
    methods: {
      addSex(){
        Vue.set(this.student, 'sex','女' )
      },
      addFriend(){
        this.student.friends.unshift({name:'张三',age:18})
      },
      updateFriendName(){
        this.student.friends[0].name = '张三'  
      },
      updateHobby(){
        this.student.hobby.splice(0,1,'开车')
        
      }
    }
  })
script>

收集表单中的数据 v-model

  1. ,则 v -model 收集的是 value 值,用户输入的就是 value 值
  2. ,则 v -model 收集的是 value 值,且要给标签配置 value 值

a. 没有配置 input 的 value 属性,那么收集的就是 checked(勾选 or 未勾选,是布尔值)
b. 配置 input 的 value 属性:
ⅰ. v-model 的初始值是非数组,那么收集的就是 checked(勾选 or 未勾选,是布尔值)
ⅱ. v-model 的初始值是数组,那么收集的就是 value 组成的数组
备注:v-model 的三个修饰符:
lazy:失去焦点再收集数据
number:输入字符串转为有效的数字
trim:输入首尾空格过滤

body>
  div id="root">
    form>
      账号:input type="text" v-model.trim="username">br>br>
      密码:input type="password" v-model="password">br>br>
      年龄:input type="number" v-model.number="age">br>br>
      性别:input type="radio" name="sex" v-model="sex" value="">input type="radio" name="sex" v-model="sex" value="">br>br>
      爱好:input type="checkbox" v-model="hobby" value="吃饭 "> 吃饭
      input type="checkbox" v-model="hobby" value="睡觉 "> 睡觉
      input type="checkbox" v-model="hobby" value="打游戏 "> 打游戏
      br>br>
      所属校区:select name="" id="">
        option value="">请选择校区option>
        
        option value="beijing">北京option>
        option value="shanghai">上海option>
        option value="guangzhou">广州option>
        option value="shenzhen">深圳option>
      select>br>br>
      button @click.prevent="submit">提交button>
    form>
  div>
body>

script type="text/javascript">
  Vue.config.productionTip = false;

  const vm = new Vue({
    el: '#root',
    data: {
      username: '',
      password: '',
      age: '',
      sex: '',
      hobby: [],
      citys: 'beijing'
    },
    methods: {
      submit() {
        console.log(this.username, this.password, this.sex, this.hobby);
      }
    }
  })
script>

过滤器(Vue3 已移除)

定义 : 对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)
语法:

  1. 注册过滤器:Vue.filter(name,callback) 或 new Vue {filters:{} }
  2. 使用过滤器:{{xxx | 过滤器名}} 或 v-bind: 属性 =“xxx | 过滤器名”
    备注:
  3. 过滤器也可以接收额外参数、多个过滤器也可以串联
  4. 并没有改变原本的数据,是产生新的对应的数据

原文地址: 初学 Vue(2)

    正文完
     0
    Yojack
    版权声明:本篇文章由 Yojack 于2024-11-10发表,共计9686字。
    转载说明:
    1 本网站名称:优杰开发笔记
    2 本站永久网址:https://yojack.cn
    3 本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长进行删除处理。
    4 本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
    5 本站所有内容均可转载及分享, 但请注明出处
    6 我们始终尊重原创作者的版权,所有文章在发布时,均尽可能注明出处与作者。
    7 站长邮箱:laylwenl@gmail.com
    评论(没有评论)