前言:当然既然学习框架的了,HTML+CSS+JS三件套必须的就不说了: JavaScript 快速入门
紧跟前文,目标学习Vue2.0——3.0: 懂个锤子Vue、WebPack5.0、WebPack高级进阶 涉及的技术栈…
学习前置链接: 懂个锤子Vue 项目工程化 懂个锤子Vue 项目工程化进阶⏫
v-model
是 Vue 框架中的一个内置指令:
用于在表单元素,如: input
、textarea
和 select
)上创建双向数据绑定;
双向绑定: 指在视图View
和数据模型Model
之间建立的一种同步机制,通过这种机制:
它的本质是一种语法糖,简化了数据绑定和事件监听的过程:其原理:
v-model
将表单控件的值value
,绑定到 Vue 实例的数据属性;v-model
监听用户对表单控件的输入事件,如 input
事件,并在用户输入时自动更新数据属性的值;v-model
自动更新表单控件的值,确保视图和数据的同步;<template>
<div id="app" style="border: 3px solid #000; margin: 10px">
<p>V-model 详解</p>
<p>v-model: <input v-model="msg" type="text"><br/></p> <!-- 双向绑定; -->
<p>原始input <input :value="msg2" type="text"><br/></p> <!-- 并没有双向绑定; -->
<p>自定义v-model <input :value="msg3" @input="msg3 = $event.target.value" type="text"><br/></p>
<!-- 在input中绑定value:value="vue数据属性" -->
<!-- input本身有个事件叫input, 用于监听value的值, 在input事件中监听并给 msg3 重新赋最新的值; 完成自定义双向绑定 -->
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
msg:'',
msg2:'',
msg3:'',
}
},
}
</script>
输入表单: @input
、单选表单: @change=""
$event.target.value
$event: 这是一个特殊变量,代表当前事件对象,.target: 事件对象的一个属性,它指向的是触发事件的那个具体的DOM元素
.value: 当这个表达式用在表单元素上时,它返回的是该表单元素的当前值:value
表单类型组件的封装是前端开发中提高代码复用性和可维护性的重要实践: but,随着UI框架丰富,实际开发接触不多
在Vue.js项目中,结合Element UI这样的UI库,封装可以更加高效,自定义特有的样式风格;
Demo 封装一个自定义表单:表单下拉框组件:
/components/menu/BaseSelect.vue
场景: 查询城市、区县下拉项目中很多地方都会使用,为了方便管理通常定义为一个组件,统一管理数据、样式;
自定义组件: /components/menu/BaseSelect.vue
<template>
<div>
<!-- 绑定 :value 值
监听change事件: 获取值并传递给父组件 -->
<select :value="selectId" @change="selectCity">
<!-- 组件内加载的下拉数据: -->
<option value="101">北京</option>
<option value="102">上海</option>
<option value="103">武汉</option>
<option value="104">广州</option>
<option value="105">深圳</option>
</select>
</div>
</template>
<script>
export default {
//获取父组件传递的默认值;
props: { selectId: String, },
methods: {
//@change:用户修改触发事件
selectCity(e) {
this.$emit('changeCity', e.target.value); //向父组件传递 新数据;
},
},
}
</script>
<style>/* 设置自定义表单样式 */</style>
App.vue 主组件:
<template>
<div id="app">
<!-- 父组件传递数据:
:selectId 父组件在子组件上,注册的 自定义属性传值;
父组件通过在: 子组件标签上监听自定义事件,并绑定 获取值同步修改selectId;
-->
<BaseSelect :selectId="selectId" @changeCity="selectId = $event" ></BaseSelect>
</div>
</template>
<script>
import BaseSelect from './components/menu/BaseSelect.vue'
export default {
name: 'App',
components:{ BaseSelect },
data() { return { selectId: '102', } }, //默认选择102
}
</script>
父组件通过:v-model传递组件数据: 实现子组件和父组件数据双向绑定;
v-model
给组件直接绑数据,因为v-model本质是: :value + @input
所以: v-model
相当于调用子组件配置:<BaseSelect :value="selectId" @input="selecteId = $event" />
props
通过 value(必须)
接收,事件触发名 input(必须)
<BaseSelect v-model="selectId" ></BaseSelect>
相当于:
<BaseSelect :value="selectId" @input="selectId = $event" ></BaseSelect>
**要注意:与,子组件配合使用哦!
.sync
修饰符是Vue.js
中用于实现父子组件间数据:双向绑定的一种特殊语法糖🍬 主要在Vue 2.x版本中使用:
特别是在需要:子组件能够直接修改父组件状态的场景下:
.sync提供了一种控制这种需求的方法,同时保持代码的清晰;
.sync 和 v-model 使用类似: 但,相比v-model
更高级方便,支持自定义:父子组件传递属性值
<子组件 :属性名.sync="xxx" ></子组件>
props:['属性名']
获取父组件传递值,如需传递|修改父组件数据:this.$emit('update:属性名', "传递值");
更新修改父组件数据;v-model: 实现组件双向绑定,固定了父子传递属性value
、监听事件名对应表单的修改事件名
;
.sync: 可以不局限表单组件,且支持自定义属性名,监听事件名@update:属性名
,相比之下更加,灵活方便;
Demo场景: 封装弹框类的基础组件,使用visible
属性 true|false
显示|隐藏,组件;
.sync
修饰符和 v-model
都是Vue.js中用于实现组件间数据绑定的机制:
.sync主要用于父子组件间的双向数据绑定, 特别是在Vue 2.x中;
它允许子组件修改父组件传递的属性值,通过触发一个特定的事件,通常是update:属性名
来实现;
可以用于: 多个属性,实现对多个数据项的双向绑定 ,不限于特定类型的元素或组件,适用于任何需要双向数据流的场景;
v-model
是Vue提供的一个指令,主要用于表单输入元素,实现数据的双向绑定;
对于原生表单元素: v-model通常等价于value属性绑定和对应的输入事件监听;
对于自定义组件: v-model内部转换为value的prop和input事件的监听;
在一个组件中只能有一个v-model,因为它代表单一的数据绑定点;
固定了父——子组件传递值:value
适用场景:v-model更适合简单的表单输入双向绑定,而.sync适用于需要子组件修改父组件数据的复杂场景
版本差异:在Vue 3中,.sync已被废弃,推荐使用Composition API中的方法来实现类似功能
而v-model依然存在,且支持更广泛的类型和自定义行为
灵活性:.sync提供了更灵活的双向绑定方式,尤其是在需要子组件影响父组件状态时
而v-model则更专注于简化用户体验设计中的数据绑定
在Vue框架中,ref
和$refs
是用于: 访问、操作组件内部、子组件的DOM元素及实例的关键特性:
ref是一个属性: 可以被添加到Vue模板中的元素、组件上:
this.$refs
可以访问到该元素的DOM
节点;this.$refs
将指向:该子组件的实例,允许你调用其方法或访问其数据;超级厉害的一个功能: 但注意:可以获取子组件的实例、属性、函数….,但并不能修改!!
$refs是一个对象,它包含了所有通过ref定义的引用:
$refs
中的引用在DOM渲染完成后才可用,因此通常在:mounted()
钩子中访问,确保元素\组件存在;this.$refs[refName]
会返回一个包含所有对应元素或组件的数组;通常情况,我们想要获取一个DOM元素:使用JS的 document.querySelector('选择器..');
这就有一个问题,如果存在相同选择器,就会获取到多个元素,而无法准确的获取某个DOM,当然可以通过设置ID选择器
实际开发中,并不建议设置特别多的ID,且组件化开发: 最后会将组件,合并为一个html
页面,导致无法准确获取对应DOM;
ref
属性类似于ID,定义在元素属性上:<元素 ref="属性x" ></元素>
this.$refs.属性x
可快速访问到该元素的DOM
节点,匹配最后一个匹配的属性;<template>
<div>
<p class="w" ref="w" >组件中的p属性</p>
<p ref="w" >组件中的p2属性</p>
</div>
</template>
<script>
export default {
//通常在:`mounted()` 钩子中访问,确保元素\组件存在;
mounted() {
//子组件中的P标签 和 父组件中P标签 相同的属性;
//因为: 组件最终会合并为一个html页面所以,会发送元素冲突情况: 获取class="w" DOM设置样式;
var mydom = document.querySelector('.w');
mydom.style.fontSize = '30px'; // 设置字体大小
mydom.style.fontWeight = 'bold'; // 设置字体加粗
//使用 $refs 获取Dom
var mydom2 = this.$refs.w;
mydom2.style.fontSize = '30px'; // 设置字体大小
mydom2.style.fontWeight = 'bold'; // 设置字体加粗
}
}
</script>
<style>/* 设置自定义表单样式 */</style>
ref 和 $refs最强大之处莫过于: 直接获取组件的实例、属性、函数;
ref
值: <子组件 ref="属性x" ></子组件>
this.$refs.属性x;
直接获取子组件实例,并通过实例获取:实例对象;主组件$refs
调用 子组件:
<template>
<div id="app">
<!-- 干扰组件,获取Dom -->
<p class="w" >干扰组件,获取Dom</p>
<BaseStr ref="ww" ></BaseStr><!-- 引入组件 -->
</div>
</template>
<script>
import BaseStr from './components/menu/BaseStr.vue'
export default {
name: 'App',
components:{ BaseStr },
mounted(){
//获取子组件实例:
var myzzj = this.$refs.ww;
console.log(myzzj.str);
myzzj.show();
}
}
</script>
Vue的异步更新机制和$nextTick方法是其核心特性之一:
用于优化:DOM更新的性能,管理数据变化与视图更新之间的关系;
Vue采用异步更新策略来处理数据变化与DOM的同步:
JavaScript
执行环境的事件循环结束之后,或在下一个宏任务如:setTimeout、setInterval、I/O完成等之前被处理:目的是合并多个数据变化,减少不必要的DOM操作,提高性能;
同时也导致一些问题: 由于数据变化和视图更新不是即时的,这可能导致调试时的逻辑断层
:
Demo需求: 点击页面编辑按钮,显示一个输入框,并立即获取编辑框的焦点
,因为异步更新机制: 立刻获取焦点失败!
$nextTick是一个方法,它允许开发者指定一个回调函数: 该函数将在Vue完成其当前的DOM更新周期后执行:
$nextTick
来确保你的代码在DOM
已经根据最新的数据渲染之后执行,mounted()
或updated()
,确保DOM已经更新后再执行某些操作;焦点
在更新数据的函数中,定义:$nextTick回调函数;
当函数内操作的数据修改后,等待DOM更新执行回调函数,完成对DOM的操作,解决了页面逻辑断层渲染问题;
<template>
<div class="app">
<!-- 默认不展示编辑框 -->
<div v-if="isShowEdit"> <input type="text" v-model="editValue" ref="inp" /> <button>确认</button> </div>
<div v-else><button @click="editFn">编辑</button></div>
</div>
</template>
<script>
export default {
data() {
return { isShowEdit: false, editValue: '', } //默认不展示编辑框
},
methods: {
editFn() {
// 1.显示文本框
this.isShowEdit = true //修改data数据 显示编辑框
// 2.让文本框聚焦\$nextTick等dom更新完之后 立马执行nextTick中的回调函数
// this.$refs.inp.focus() //使用: $refs 获取指定的DOM元素focus()设置焦点,因为异步刷新机制Dom并不会立刻更新;
this.$nextTick(() => {
console.log(this.$refs.inp)
this.$refs.inp.focus()
})
},
},
}
</script>
<style></style>
$nextTick还可以使用微任务,如:Promise、MutationObserver
或宏任务如:setTimeout,优先使用微任务来实现;
本代码已经使用Git进行管理: 公众号回复:Vue项目工程化
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。