v-model语法糖,ref和$refs(vue操作dom),$nextTick使用,dynamic动态组件,自定义指令

01-v-model语法糖

  • v-model本质上是 value属性和input事件的一层包装

  • v-model的作用:提供数据的双向绑定

    • 数据发生了改变,页面会自动变 v-bind:value

    • 页面输入改变 , 数据会自动变化 v-on:input

  • v-model是语法糖, v-model等价于 给一个input框提供了 :value属性以及 @input事件

很显然如果每次使用input框,都需要提供value和input事件,比较麻烦,所以使用v-model

02-组件使用v-model

  • 我们经常遇到一种场景:

    1. 父组件提供一个数据给子组件使用(父传子)

    2. 子组件又需要修改父组件传过来的这个数据,所以需要子传父把值传给父组件。

  • 这种场景可以使用v-model进行简写。

    • 定义组件的时候,注意接收的值叫value, 子传父触发的事件叫 input

 

如果父传子的props值叫 value, 且 子传父触发的事件叫 input 。 那么这两个功能就可以使用v-model来简写

<template>
  <div>
    <h1>根组件App.vue</h1>
    <!-- 
      1.v-model = "msg"
        (1)data中的数据变化,表单的值也会变化     :value="msg"
        (2)表单的值发生变化,data中的数据也会变化  @input="msg=$event.target.value"
    -->
    <input type="text" v-model="msg" />
    <hr />
    <!-- 这种写法与上面写法功能一致 -->
    <input type="text" :value="msg" @input="msg = $event.target.value" />
    <hr />
    <!-- 这种写法也与上面写法一致 -->
    <input type="text" :value="msg" @input="doInput" />
    <hr />
  </div>
</template>
​
<script>
export default {
  data() {
    return {
      msg: ""
    };
  },
  methods: {
    doInput(e) {
      this.msg = e.target.value;
    }
  }
};
</script>
​
<style>
</style>

03-ref和$refs(vue操作dom)

  • 官方文档:API — Vue.js

  • ref作用:在vue中操作dom元素或组件vm实例

    • vue不推荐我们直接操作dom。如果真的要在vue中操作dom,可以使用ref语法

      • 说人话 : vue不能直接操作dom,真的要操作也要按vue规定的语法来。(ref语法)

  • 每个 vue 的组件实例上,都包含一个$refs 对象,里面存储着对应的DOM 元素或组件的引用。

ref语法使用流程语法

(1)给标签添加自定义属性red :<button ref="属性名"></button>

  • vue会自动把页面所有的ref属性,挂载到vue实例的$ref对象中

(2)通过 vm.$refs.属性名 获取该标签

  • 一定要注意 : vue在mounted勾子中完成页面真实DOM渲染,所以最早能获取dom的就是mounted钩子

ref易错点

1.添加的的时候是: ref

2.获取的时候是: $refs

1 给需要获取的 dom 元素或者组件, 添加 ref 属性

<template>
  <div>
    <h1>根组件App.vue</h1>
    <div ref="box">我是div盒子</div>
    <Goods ref="goods"></Goods>
    <button @click="fn">点我获取ref</button>
  </div>
</template>
2 通过 this.$refs.xxx 获取, 拿到组件可以调用组件的方法

<script>
//导入子组件
import Goods from "./components/Goods.vue";
export default {
  //注册组件
  components: { Goods },
  //方法
  methods: {
    fn() {
      // 如果ref给dom元素添加,获取的就是dom对象
      console.log(this.$refs.box);//DOM对象
      // 如果ref给组件添加,获取的就是组件vm实例
      console.log(this.$refs.goods);//组件vue实例
      this.$refs.goods.sayHi();
    }
  }
};
</script>

  • 子组件代码Goods.vue

<template>
  <div>
      <h2>我是子组件</h2>
  </div>
</template>
​
<script>
export default {
    methods: {
        sayHi(){
            console.log('你好我是子组件')
        }
    },
}
</script>
​
<style>
​
</style>

04-$nextTick使用

需求1: 点击按钮, 切换显示输入框

<template>
  <div>
    <!-- 需求1: 点击按钮, 切换显示输入框-->
    <input type="text" v-if="showInput">
    <button @click="fn" v-else>点此搜索</button>
  </div>
</template>
​
<script>
export default {
  data () {
    return {
      showInput: false
    }
  },
  methods: {
    fn () {
      this.showInput = true
    }
  }
}
</script>
​
<style>
​
</style>

需求2: 显示输入框的同时, 要获取焦点

当文本框展示出来之后,如果希望它立即获得焦点,则可以为其添加 ref 引用,并调用原生 DOM 对象的.focus() 方法即可。

直接调用会报错, 因为 vue 是 异步dom更新的 (提升渲染效率), this.showInput = true 执行完时, 实际的 dom 还没渲染出来

<input ref="inp" type="text" v-if="showInput">
​
fn () {
  this.isShowInput = true
  this.$refs.inp.focus()
}

组件的 $nextTick(callback) 方法,会把 callback 回调推迟到下一个 DOM 更新周期之后执行。

通俗的理解是:等组件的DOM 刷新之后,再执行 callback 回调函数。从而能保证 callback 函数可以操作到最新的 DOM 元素。

<template>
  <div>
    <!-- 需求1: 点击按钮, 切换显示输入框
         需求2: 显示输入框的同时, 要获取焦点
     -->
    <input type="text" v-if="showInput" ref="inp">
    <button @click="fn" v-else>点此搜索</button>
  </div>
</template>
​
<script>
export default {
  data () {
    return {
      showInput: false
    }
  },
  methods: {
    fn () {
      // 显示输入框
      this.showInput = true
      // 输入框获取焦点
​
      /* 报错原因: 
        (1) vue更新DOM是一个异步的过程。(虽然设置了showInput为true,但是不会立即显示输入框)
        (2) 异步代码需要等当前队列同步代码全部执行完毕之后才会执行
        解决方案:
        this.$nextTick(callback) : 会等组件的DOM刷新之后再来执行callback回调函数
      */
​
      // this.$refs.inp.focus() // 报错
      this.$nextTick( ()=>{
        this.$refs.inp.focus()
      } )
    }
  }
}
</script>
​
<style>
​
</style>

05-dynamic动态组件

  • 什么是动态组件: 让多个组件使用同一个挂载点,并动态切换,这就是动态组件。

    • 混淆点解读:动态组件 看起来和v-if v-else功能有些类似,但其实两者是不同的。

      • v-if v-else : 只是根据条件来决定渲染哪一个盒子,不能像组件那样复用。

      • 动态组件:通过设置组件名,让一个挂载点可以切换不同的组件

 

  • App.vue

<template>
  <div>
    <h3>动态组件的演示</h3>
    <!-- 动态组件 => 多个组件使用同一个挂载点, 并可以动态的切换展示 -->
    <button @click="comName = 'UserAccount'">未登录</button>
    <button @click="comName = 'UserInfo'">已登录</button>
    
    <!-- 动态组件:让多个组件使用同一个挂载点,实现动态切换
        <component :is="组件名" ></component>
    -->
    <component :is="comName"></component>
  </div>
</template>
​
<script>
// 导入组件
import UserAccount from './components/UserAccount.vue'
import UserInfo from './components/UserInfo.vue'
​
export default {
  data () {
    return {
      comName: 'UserAccount'
    }
  },
  //注册组件
  components: {
    UserAccount,
    UserInfo
  }
}
</script>

  • UserAccount.vue

<template>
  <div class="user-account form-box">
    <div class="form-box-item">
      <label for="username">账 户: </label>
      <input id="username" type="text" placeholder="请输入用户名">
    </div>
​
    <div class="form-box-item">
      <label for="password">密 码: </label>
      <input id="password" type="text" placeholder="请输入密码">
    </div>
  </div>
</template>
​
<script>
export default {
  name: 'UserAccount'
}
</script>
​
<style lang="less">
​
</style>

  • UserInfo.vue

<template>
  <div class="user-info form-box">
    <div class="form-box-item">
      <label for="words">人生格言: </label>
      <input id="words" type="text" placeholder="请填写人生格言">
    </div>
​
    <div class="form-box-item">
      <label for="info">个人简介: </label>
      <input id="info" type="text" placeholder="请填写个人简介">
    </div>
​
    <div class="form-box-item">
      <label for="hobby">兴趣爱好: </label>
      <input id="hobby" type="text" placeholder="请填写兴趣爱好">
    </div>
  </div>
</template>
​
<script>
export default {
  name: 'UserInfo'
}
</script>
​
<style lang="less">
​
</style>

06-自定义指令

  • 官方文档:自定义指令 — Vue.js

  • 1.复习指令作用 : 给标签添加额外的功能

  • 2.复习指令本质 : 行内自定义属性

  • 3.自定义指令作用 : 给标签添加 vue没有的,额外的功能

1.1-自定义指令:局部注册

  • 局部注册:只能在当前组件使用

  • 需求:

    • 1.添加一个自定义指令 v-focus,作用是让input表单自动聚焦

    • 2.添加一个自定义指令v-color,作用是设置标签文本颜色

<template>
  <div>
    <h1>根组件</h1>
    <!-- 使用指令 v-指令名 -->
    <input type="text" v-focus/>
    <br />
    <p v-color=" bgc ">我是p标签,我使用了自定义指令v-red</p>
  </div>
</template>
​
<script>
export default {
  data() {
    return {
      bgc:'green'
    }
  },
  //自定义指令都写在这个对象里面
  directives: {
    //1.指令名:  focus
    focus: {
      // inserted(el) :  当指令被使用的时候会执行一次
      inserted(el) {
        //el : 你的指令写在哪一个标签上,这个el就是标签dom对象
        el.focus()
      },
      
    },
    //2.指令名: color
    color: {
      inserted(el,binding) {
        console.log(el)//指令所绑定的元素
        console.log(binding)//一个对象,包含指令名、指令值等数据
        console.log(binding.value)//指令值
        el.style.color = binding.value
      },
      // update(el,binding) : 当指令的值发生改变时触发
      update(el,binding) {
        console.log(el,binding)
        el.style.color = binding.value
      },
    }
  }
}
</script>
​
<style></style>

1.2-自定义指令:全局注册

  • 全局注册: 在main.js中注册,任何地方可用

// 全局指令 - 任何组件内"直接"使用
Vue.directive("focus", {
  inserted(el) {
    el.focus() // 触发标签的事件方法
  }
})

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值