Vue.js 其他指令
1.ref标识
通过给HTML标签或者组件标签设定ref属性,根据他的属性值来访问这个HTML元素或者组件
语法:this.$refs.属性值
//为p标签设置ref属性
<div id="app">
<p ref="p1">期待你脚踏祥云</p>
<button @click="test">点我</button>
</div>
//根据ref属性值来访问这个元素
methods: {
test() {
console.log(this.$refs.p1.innerText)
}
}
2.v-cloak
在vue实例渲染HTML模版之前,页面中的{{msg}}这种语法就会原模原样的输出,例如
<body>
<div id="app">
<p>{{msg}}</p>
</div>
</body>
</html>
<script>
//模拟网速慢的情形,延时创建vue实例
setTimeout(() => {
var vm = new Vue({
el: '#app',
data: {
msg:"今天周末"
},
})
}, 1000);
</script>
解决办法一:为标签设置v-cloak属性
原理:当vue对模版渲染完毕后会移除元素标签内vue指令,可以利用这个特性,结合css的属性选择器来隐藏未解析的标签
//css属性选择器
<style>
[v-cloak]{
display: none;
}
</style>
//为元素添加v-cloak属性,当元素未渲染时处于隐藏状态,渲染完毕后就正常展示
<body>
<div id="app">
<!-- 模版编译完成之后会自动的那个移除 v-cloak 属性-->
<p v-cloak>{{msg}}</p>
</div>
</body>
</html>
<script>
//模拟网速慢的情形,延时创建vue实例
setTimeout(() => {
var vm = new Vue({
el: '#app',
data: {
msg:"今天周末"
},
})
}, 1000);
</script>
解决办法二:使用v-text指令
在vue对模版渲染之前,v-text指令不会影响页面的展示
<body>
<div id="app">
<p v-text="msg"></p>
</div>
</body>
3.自定义指令
(1)全局注册
语法:Vue.directive(指令名称,回调函数)
回调函数有2个参数 el和binding
el:指令所绑定的元素,可以用来直接操作 DOM
binding:包含指令相关信息的对象,binding.value就是指令绑定的值
Vue.directive('upper-text',function(el,binding){
el.innerText = binding.value.toUpperCase();
})
(2)局部注册:只能在该组件中使用
组件中接受一个 directives 的选项
directives: {
focus: {
// 指令的定义
inserted: function (el) {
el.focus()
}
}
}
然后你可以在模板中任何元素上使用新的 v-focus 属性,如下:
<!-- 自动获取焦点 -->
<input type="text" v-focus>
(3)如果注册的自定义指令名含有 - 等字符,可以用 '' 包裹起来
directives:{
'lower-text':function(el,binding){
el.innerText = binding.value.toLowerCase();
}
}
(4)自定义指令的使用
<!-- msg的值为 good -->
<p v-html="msg"></p>
<!-- 使用插件的自定义指令 -->
<p v-upper-text="msg"></p>
渲染结果:
<p>good</p>
<p>GOOD</p>
(5)钩子函数
bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素
el.focus()
}
})
(6)实例:文本滚动指令
思路:将当前文本放入子容器中,动态计算子容器与父容器的宽度差异,调用js定时器动态修改子容器的位置
<script>
Vue.directive('scroll',{
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el,binding) {
//创建容器装载文本
var content_box = document.createElement('div')
content_box.style.display = 'inline-block'
//不允许换行
content_box.style.whiteSpace = 'nowrap'
content_box.innerHTML = binding.value
//将文本容器添加到元素中
el.appendChild(content_box)
//判定内容是否溢出
if(el.scrollWidth - el.offsetWidth > 0){
//隐藏溢出的内容
el.style.overflow = 'hidden'
var now_position = 0 //当前位置 默认0
var direction = 'left' //移动方向 默认向左移动
var target = el.offsetWidth - el.scrollWidth //负数
var rest = 20 //动画暂停时间
//使用定时器实时修改位移
setInterval(()=>{
//只有rest小于0才执行动画
if(rest <= 0){
if(direction == 'left'){
now_position--
}else{
now_position++
}
//如果左移到底 则返回
if(now_position < target){
direction = 'right'
}
//如果右移到底 则返回 并暂停动画
if(now_position > 0){
direction = 'left'
//暂停动画
rest = 20
}
//更新位置
content_box.style.transform = `translateX(${now_position}px)`
}
rest--
},100)
}
}
})
new Vue({
el:"#app",
data:{
msg:"床前明月光,疑是地上霜"
}
})
</script>
使用
<body>
<div id="app">
<div style="border:1px solid red;width:100px;margin:20px auto;" v-scroll="msg">
</div>
</div>
</body>