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
-
我们经常遇到一种场景:
-
父组件提供一个数据给子组件使用(父传子)
-
子组件又需要修改父组件传过来的这个数据,所以需要子传父把值传给父组件。
-
-
这种场景可以使用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() // 触发标签的事件方法
}
})