Vue相关知识
ref属性
- 被用来给元素或子组件注册引用信息(id的替代者)
- 应用在html标签上获取的是真实DOM元素,应用在组件标签上是组件实例对象(vc)
- 使用方式:
- 打标识:
<h1 ref="xxx">.....</h1>
或<School ref="xxx"></School>
- 获取:
this.$refs.xxx
- 打标识:
<template>
<div>
<h1 v-text="msg" ref="title"></h1>
<button ref="btn" @click="showDOM">点我输出上方的DOM元素</button>
<School ref="sch" />
</div>
</template>
<script>
//引入School组件
import School from "./components/School";
export default {
name: "App",
components: { School },
data() {
return {
msg: "欢迎学习Vue!",
};
},
methods: {
showDOM() {
console.log(this.$refs.title); //真实DOM元素
console.log(this.$refs.btn); //真实DOM元素
console.log(this.$refs.sch); //School组件的实例对象(vc)
},
},
};
</script>
props配置项
- 功能:让组件接收外部传过来的数据
- 传递数据:
<Demo name="xxx"/>
- 接收数据:
- 第一种方式(只接收):
props:['name']
- 第二种方式(限制类型):
props:{name:String}
- 第三种方式(限制类型、限制必要性、指定默认值):
props:{
name:{
type:String, //类型
required:true, //必要性
default:'老王' //默认值
}
}
备注:props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,若业务需求确实需要修改,那么请复制props的内容到data中一份,然后去修改data中的数据。
<template>
<div>
<h1>{{ msg }}</h1>
<h2>学生姓名:{{ name }}</h2>
<h2>学生性别:{{ sex }}</h2>
<h2>学生年龄:{{ myAge + 1 }}</h2>
<button @click="updateAge">尝试修改收到的年龄</button>
</div>
</template>
<script>
export default {
name: "Student",
data() {
console.log(this);
return {
msg: "我是一个尚硅谷的学生",
myAge: this.age,
};
},
methods: {
updateAge() {
this.myAge++;
},
},
//简单声明接收
// props:['name','age','sex']
//接收的同时对数据进行类型限制
/* props:{
name:String,
age:Number,
sex:String
} */
//接收的同时对数据:进行类型限制+默认值的指定+必要性的限制
props: {
name: {
type: String, //name的类型是字符串
required: true, //name是必要的
},
age: {
type: Number,
default: 99, //默认值
},
sex: {
type: String,
required: true,
},
},
};
</script>
nextTick
vue对dom的更新是异步的。
for(let i=0;i<n;i++){
this.someData+=i
}
如上面的例子,如果我们多次修改someDate
的值,并不是每次修改的结果都会渲染到页面上。因为我们只需要看到最终的值。vue是在执行完一次事件循环后把缓冲的数据更改更新到页面上
vm.$nextTick(callback)
,在下一次dom更新之后执行对应的回调,这样我们获取到的dom就是更新过的dom
下面了解下nextTick
的主要应用的场景及原因。
- 在Vue生命周期的
created()
钩子函数进行的DOM操作一定要放在Vue.nextTick()
的回调函数中
在created()
钩子函数执行的时候DOM 其实并未进行任何渲染,而此时进行DOM操作无异于徒劳,所以此处一定要将DOM操作的js代码放进Vue.nextTick()
的回调函数中。
- 在数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的DOM结构的时候,这个操作都应该放进
Vue.nextTick()
的回调函数中。
msg1和msg3显示的内容还是变换之前的,而msg2显示的内容是变换之后的。其根本原因是因为Vue中DOM更新是异步的
获取this.Message的两种情况:
在nextick中可以获取更新后的dom
插槽slot
插槽的作用是什么?
todo-button.vue——自定义组件
<button class="btn-primary"></button>
index.vue——引入 todo-button 组件
<todo-button>
Add todo <!-- 文本不会渲染,无法给按钮自定义文字 -->
</todo-button>
为了能给自定义组件添加或设置自定义内容,使得自定义组件通用化,于是有了插槽
<button class="btn-primary">
<slot></slot> <!-- slot 元素将会被 <todo-button> 组件里的内容代替 -->
</button>
这样就实现了给自定义组件添加或设置自定义内容,使得自定义组件通用化
匿名插槽及后备内容
以上 <slot>
元素就被称为 匿名插槽
为了防止开发者使用自定义组件的时候没有设置自定义内容时,自定义组件也能正常使用,我们需要给 slot 元素里面添加内容,这就是 后备内容:
<button type="submit">
<slot>Submit</slot> <!-- slot 元素将会被 <todo-button> 组件里的内容代替 -->
</button>
当我在一个父级组件中使用 并且不提供任何插槽内容时:
<submit-button></submit-button>
后备内容“Submit”将会被渲染出来。
具名插槽
如需要有多个插槽,我们就得让 <todo-button>
组件里包裹的自定义内容代替 todo-button.vue 的指定位置,我们就需要 具名插槽
<slot>
元素有一个特殊的 attribute:name
。这个 attribute 可以用来定义额外的插槽:
<base-layout>
组件:
<div class="container">
<header>
<slot name="header"></slot> <!-- 具名插槽 -->
</header>
<main>
<slot></slot> <!-- 匿名插槽 -->
</main>
<footer>
<slot name="footer"></slot> <!-- 具名插槽 -->
</footer>
</div>
一个不带 name
的 <slot>
出口会带有隐含的名字“default”。
在向具名插槽提供内容的时候,我们可以在一个 <template>
元素上使用 v-slot
指令(注意 v-slot
只能添加在 <template>
上),并以 v-slot
的参数的形式提供其名称:
调用base-layout组件的父元素:
<base-layout>
<template v-slot:default>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</template>
<template v-slot:footer>
<p>Here's some contact info</p>
</template>
<template v-slot:header>
<h1>Here might be a page title</h1>
</template>
</base-layout>
现在 <template>
元素中的所有内容都将会被传入相应的插槽。
最终渲染的 HTML 将会是:
<div class="container">
<header>
<h1>Here might be a page title</h1>
</header>
<main>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</main>
<footer>
<p>Here's some contact info</p>
</footer>
</div>
作用域插槽
有时让父组件中的插槽内容能够访问子组件中才有的数据是很有用的。例如,设想一个带有如下模板的 <current-user>
组件:
<span>
<slot>{{ user.lastName }}</slot>
</span>
我们可能想换掉备用内容,用名而非姓来显示。如下:
父组件:
<current-user>
{{ user.firstName }}
</current-user>
然而上述代码不会正常工作,因为只有 <current-user>
组件可以访问到 user
,而我们提供的内容是在父级渲染的。
为了让 user
在父级的插槽内容中可用,我们可以将 user
作为 <slot>
元素的一个 attribute 绑定上去:
<span>
<slot v-bind:user="user">
{{ user.lastName }}
</slot>
</span>
我们可以使用带值的 v-slot
来定义我们提供的插槽 prop 的名字:
<current-user>
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
</current-user>