vue2-2024

Object.defineProperty数据代理 &Observer数据劫持

数据代理,通过一个对象代理对另一个对象中属性的操作(读/写)

数据代理+数据劫持 ? 数据的双向绑定(vue中)

Vue 利用 Object.defineProperty 创建一个 observer 来劫持监听所有的属性,把这些属性全部转为 getter 和 setter。

Vue 中每个组件实例都会对应一个 watcher 实例,它会在组件渲染的过程中把使用过的数据属性通过 getter 收集为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。
修改data属性值-》重新解析模板-》生成新的(虚拟)dom-》diff算法对比-》生成更新后页面

TypeScript 复制代码
 let number=10
  let person={
    name:"lisi",
    sex:"男",
    age:number,
  }
  Object.defineProperty(person,"age",{
    // value:19,
    // enumerable:true,//可枚举
    // writable:true //可修改
    get(){
      debugger
      return  number
    },
    set(value){//value为 person.age=1   中的1
      debugger
      number=value
    }
  })
  person.age=1
  // for in  即可遍历数组也可遍历对象
  // for (const key in person) {
  //   if (Object.hasOwnProperty.call(person, key)) {
  //     const element = person[key];
  //     console.log(element)
  //   }
  // }
  

  console.log( Object.keys(person))
TypeScript 复制代码
  let obj1={
    "x":12
  }
  let obj2={
    name:"lisi",

  }
  Object.defineProperty(obj2,"x",{
    set(value){
      obj1.x=value
    },
    get(){
      return obj1.x
    }
  })

添加class样式

字符串写法

TypeScript 复制代码
<template>
  <div class="hello" :class="a" @click="changeColor()">
   {{msg}}
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  data(){
    return{
      a:"red"
    }
  },
  methods:{
    changeColor(){
      this.a="green"
    }
  }
}
</script>

数组写法

TypeScript 复制代码
 <div class="hello" :class="classarr" @click="changeColor()">


data(){
    return{
      classarr:["red","green","orange"]
    }
  },

对象写法

TypeScript 复制代码
  <div class="hello" :class="classobj" @click="changeColor()">
 

data(){
    return{
      classobj:{
        "red":true,
        "green":false,
        "orange":false,
      },
    }
  },

绑定style样式

方式1

TypeScript 复制代码
<template>
  <div class="hello" :style="styleobj"  @click="changeColor()">
   {{msg}}
  </div>
</template>

data(){
    return{
     
      styleobj:{
        fontSize:"40px"
      }
    }
  },

方式2

TypeScript 复制代码
  <div class="hello" :style="{fontSize:fontsize}"  @click="changeColor()">

方式3

:style[a,b]

a和b为样式对象 如:

styleobj:{

fontSize:"40px"

}

v-if

TypeScript 复制代码
<div v-if="n===1">1</div>
<div v-else-if="n===2">1</div>
<div v-else-if="n===3">1</div>
<div v-else>1</div>

计算属性

计算属性回调函数

2个时刻调用:初始化和方法里面的数据改动

TypeScript 复制代码
<template>
  <div class="hello" >
   <input type="text" v-model="inputtext">
   <button @click="sortAge=1">年龄升序</button>
   <button @click="sortAge=2">年龄降序</button>
   <button  @click="sortAge=0">原顺序</button>
   <ul >
    <li v-for="item in filperson" :key="item.id">
      {{ item.name }}  ------  {{ item.age }}
    </li>
   </ul>
  </div>
</template>

<script>

/* eslint-disable */
import { watch } from 'vue';
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  data(){
    return{
      sortAge:0,//1升序,2降序,0原顺序
      arr:[
        {"id":"1","name":"lisi1","age":12},
        {"id":"2","name":"lisi2","age":11},
        {"id":"3","name":"wangwu1","age":33},
        {"id":"4","name":"wang2","age":55}
      ],
      endarr:[],
      inputtext:""
    }
  },
  methods:{
  },
  computed:{
    // 默认执行一次,this.inputtext发生变化则计算一次
     
    filperson(){
        let starr= this.arr.filter((item)=>{
          return  item.name.includes(this.inputtext)
        })
        
        if(this.sortAge){
          debugger
          starr.sort((a,b)=>{
            return this.sortAge==1?a.age-b.age   :b.age-a.age
          })  
        }
      return starr
      }
  },
  
}
</script>

条件过滤

TypeScript 复制代码
<template>
  <div class="hello" >
   <input type="text" v-model="inputtext">
   <ul>
    <li v-for="item in endarr" :key="item.id">
      {{ item.name }}
    </li>
   </ul>
  </div>
</template>

<script>

/* eslint-disable */
import { watch } from 'vue';
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  data(){
    return{
      arr:[
        {"id":"1","name":"lisi1"},
        {"id":"2","name":"lisi2"},
        {"id":"2","name":"wangwu1"},
        {"id":"3","name":"wang2"}
      ],
      endarr:"",
      inputtext:""
    }
  },
  methods:{
  },
  watch:{
     // 简写形式
    // inputtext(newvalue){
    //  this.endarr= this.arr.filter((item)=>{
    //     return  item.name.includes(newvalue)
    //   })
    // }
    // 完整形式
    inputtext:{
      // 初始化的时候立即执行
      immediate:true,
      handler(newvalue){
        this.endarr= this.arr.filter((item)=>{
          return  item.name.includes(newvalue)
        })
      }
    }
  }
}
</script>

后期给对象添加属性

TypeScript 复制代码
<template>
  <div class="hello" >
   
    <p>姓名:{{person.name}}</p> 
    <p>姓名:{{person.age}}</p> 
    <button @click="updata"> person添加属性</button>
  </div>
</template>

<script>

/* eslint-disable */
import Vue, { watch } from 'vue';
// import Vue from 'vue/types/umd';
// import { person } from '../../../hellovue3/src/types/index';
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  data(){
    return{
      person:{
        "name":"lisu",
      }
      
    }
  },
  methods:{
    updata(){
     // 方法1
      // Vue.set(this.person,"age","boo")//只可给data里面的对象上添加属性,不可给data添加
      // 方法2
      this.$set(this.person,"age","boo")
    }
  },
}
</script>

收集表单里面的信息

TypeScript 复制代码
<template>
  <div class="hello" >
    <!-- prevent组织默认刷新行为 -->
    <form @submit.prevent="sub">
   账号:<input type="text" v-model.trim="person.acount"><br/><br/>
   密码:<input type="password" v-model="person.password"><br/><br/>
   年龄:<input type="number" v-model.number="person.age"><br/><br/>
   性别:<label for="nan">男</label> <input v-model="person.personSex" type="radio" name="sex" id="nan" value="male">
         <label for="nv">女</label> <input v-model="person.personSex" type="radio" name="sex"  id="nv" value="famale"><br/><br/>
   爱好:学习<input type="checkbox" v-model="person.like" value="lea">
         打游戏<input type="checkbox" v-model="person.like" value="dyx">
         吃美食<input type="checkbox" v-model="person.like" value="cms"><br/><br/>
  喜欢城市:<select name="" v-model="person.city" aria-placeholder="请选择喜欢的城市" id="">
              <option value="1">上海</option>
              <option value="2">北京</option>
              <option value="3">深圳</option>
              <option value="4">广州</option>
            </select><br/><br/>
            <!-- v-model.lazy失去焦点更新数据 -->
  其他信息:<textarea name="" v-model.lazy="person.other" id="" cols="30" rows="10">

            </textarea><br/><br/>
            <!--checkbox不设置value值   则是否打勾为true或者false  -->
            <input type="checkbox" v-model="person.agree">我同意<br/><br/>
            <button>提交</button>
          </form>
  </div>
</template>

<script>


import Vue, { watch } from 'vue';

export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  data(){
    return{
      person:{

        acount:"",
        password:"",
        like:[],
        personSex:"",
        city:"",
        age:0,
        other:"",
        agree:''
      },
    }
  },
  methods:{
    sub(){
      console.log("提交")
      console.log(JSON.stringify(this.person))
    }
  },
}
</script>

v-html指令安全问题

cookie中 k1 ,k2的值被篡改,则不安全;

被其他网站获取到也不安全,获取到可直接登录(httponly可避免通过代码获取cookie)

指令

v-clock

指令+样式 当网络延迟时,动态渲染的页面字段不显示,当页面渲染结束后,vue自动删除v-clock

TypeScript 复制代码
<template>
  <div class="hello" >
  <p v-cloak>{{name}}</p>
  <p v-cloak>{{age}}</p>
  </div>
</template>

<script>

/* eslint-disable */
import Vue, { watch } from 'vue';

export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  data(){
    return{
      name:"1111",
      age:"2"
    }
  },
  methods:{
    
  },
}
</script>
<style scoped>
[v-cloak]{
  display: none;
}
.hello{
  width: 100%;
  height: 100px;
  /* border: 1px solid #dedede; */
  text-align: left;
}
</style>

v-pre

跳过这个元素和它的子元素的编译过程。可以用来显示原始 Mustache 标签。跳过大量没有指令的节点会加快编译。

v-once 只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。

自定义指令

自定义指令的两种实现方式

TypeScript 复制代码
<template>
  <div class="hello" >
    <!-- 指令v-big,num放大10倍 -->
    <!-- v-focus  页面刷新时得到焦点 -->
  <p >{{num}}</p>
  <!-- 放大10倍后的n -->
  <p v-big="num"></p>
  <button @click="num++">num加一</button><br/>
  <input v-focus="num" type="text"><br/>
  <input v-big-number="num"  type="text">
  </div>
</template>

<script>

/* eslint-disable */
import Vue, { watch } from 'vue';

// 全局自定义指令两种方法
// Vue.directive("big",function (element,binding){
//       element.innerText=binding.value*10
//     })
// Vue.directive("focus",{
//       // 指令和元素成功绑定时(一上来,并不是放入页面时)
//       bind(element,binding){
//         element.value=binding.value
//       },
//       // 指令所在元素被插入页面时
//       inserted(element,binding){
//         element.focus()
//       },
//       // 指令所在的模板被从新解析时
//       update(element,binding){
//         element.value=binding.value
//       }
//     })
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  data(){
    return{
      num:1,
    }
  },
  methods:{
    
  },
  directives:{
    // big函数何时会被调用?
    // 1.指令和元素成功绑定时(一上来,并不是放入页面时)
    // 2.指令所在的模板被从新解析时
    big(element,binding){
      
      element.innerText=binding.value*10
    },
    focus:{
      // 指令和元素成功绑定时(一上来,并不是放入页面时)
      bind(element,binding){
        element.value=binding.value
      },
      // 指令所在元素被插入页面时
      inserted(element,binding){
        element.focus()
      },
      // 指令所在的模板被从新解析时
      update(element,binding){
        element.value=binding.value
      }
    },
    'big-number'(element,binding){
      console.log(element,binding.value)
      element.value=binding.value*10
    } 
   }
}
</script>
<style scoped>
[v-cloak]{
  display: none;
}
.hello{
  width: 100%;
  height: 100px;
  /* border: 1px solid #dedede; */
  text-align: left;
}
</style>
相关推荐
轻口味12 分钟前
【每日学点鸿蒙知识】AVCodec、SmartPerf工具、web组件加载、监听键盘的显示隐藏、Asset Store Kit
前端·华为·harmonyos
alikami14 分钟前
【若依】用 post 请求传 json 格式的数据下载文件
前端·javascript·json
吃杠碰小鸡1 小时前
lodash常用函数
前端·javascript
emoji1111111 小时前
前端对页面数据进行缓存
开发语言·前端·javascript
泰伦闲鱼1 小时前
nestjs:GET REQUEST 缓存问题
服务器·前端·缓存·node.js·nestjs
m0_748250031 小时前
Web 第一次作业 初探html 使用VSCode工具开发
前端·html
一个处女座的程序猿O(∩_∩)O1 小时前
vue3 如何使用 mounted
前端·javascript·vue.js
m0_748235951 小时前
web复习(三)
前端
AiFlutter1 小时前
Flutter-底部分享弹窗(showModalBottomSheet)
java·前端·flutter
麦兜*1 小时前
轮播图带详情插件、uniApp插件
前端·javascript·uni-app·vue