Vue知识点
Vue.component的缺点:
- 全局定义: 强制要求每个component中的命令不重复
- 字符串模板:缺乏语法高亮,在HTML有多行的时候,需要丑陋的
\ - 不支持CSS:意味着当HTML和JavaScript组件化时,CSS被明显遗漏
- 没有构建步骤:限制只能使用HTML和ES5 JavaScript,而不能使用预处理器,如Pug(formerly Jade)和Babel
单文件组件
vue create my-app命令创建一个默认的项目
在main.js文件中有如下的代码:
new Vue({
render: h => h(App),
}).$mount('#app')
如何理解render: h => h(App),可参考:
首先需要了解这是 es 6 的语法,表示 Vue 实例选项对象的 render 方法作为一个函数,接受传入的参数 h 函数,返回 h(App) 的函数调用结果。
插槽
v-slot can only be used on components or
<template>.
TotoItem.vue
<template>
<li class="item">
<input type="checkbox" v-model="checked"/>
<slot name="item" v-bind="{checked}"></slot>
</li>
</template>
<script>
export default {
props: ["item"],
data () {
return {
checked: false
}
}
};
</script>
<style scoped>
.item {
color: red;
}
</style>
App.vue
<template>
<div id="app">
{{ msg }}
<div>
<input type="text" v-model="info">
<button v-on:click="handleClick">添加</button>
</div>
<ul>
<todo-item v-for="item in list" :key="item" v-slot:item="itemProps">
<!-- <template v-slot:item="itemProps">
<span :style="{fontSize: '20px', color: itemProps.checked ? 'red': 'blue'}">{{ item }}</span>
</template> -->
<span :style="{fontSize: '20px', color: itemProps.checked ? 'red': 'blue'}">{{ item }}</span>
</todo-item>
</ul>
</div>
</template>
<script>
import TodoItem from './components/TodoItem.vue'
export default {
data() {
return {
msg: "hello wz",
info: "",
list: []
};
},
methods: {
handleClick() {
this.list.push(this.info);
this.info = "";
}
},
components: {
TodoItem
}
};
</script>
<style>
</style>
自己的理解:
v-slot:item="itemProps"表示的是name为item的slot,itemProps表示的是子组件中v-bind="{checked}传递给父组件的itemProps
参考:
1.对slot与slot-scope的理解
由于slot是一块模板,因此对于任何一个组件,从模板种类的角度来分,共实都可分为非插槽模板和插槽模板。其中非插槽模板指的是HTML模板(也就是HTML的一些元素,比如div、span等构成的),其显与否及怎么显示完全由插件自身控制;但插槽模板(也就是slot)是一个空壳子,它显示与否以及怎么显示完全是由父组件来控制。不过,插槽显示的位置由子组件自身决定,slot写在组件template的哪块,父组件传过来的模板将来就显示在哪块。著作权归作者所有。
slot-scope的值将被用作一个临时变量名,此变量接收从子组件传递过来的prop对象
组件
组件的三大核心概念:属性、事件和插槽
单向数据流
所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。
额外的,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。
如何解决:
1.这个 prop 用来传递一个初始值;这个子组件接下来希望将其作为一个本地的 prop 数据来使用。在这种情况下,最好定义一个本地的 data 属性并将这个 prop 用作其初始值:
props: ['initialCounter'],
data: function () {
return {
counter: this.initialCounter
}
}
2.这个 prop 以一种原始的值传入且需要进行转换。在这种情况下,最好使用这个 prop 的值来定义一个计算属性:
props: ['size'],
computed: {
normalizedSize: function () {
return this.size.trim().toLowerCase()
}
}
如果在子组件中修改修改父组件的prop,会提示warn:
事件
可参考官方文档:事件处理
各种控价的input 和 change事件可参考https://jsfiddle.net/posva/oqe9e8pb/
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app">
<input type="text" @input="addEvent" @change="addEvent" />
<input type="range" min="0" max="100" @input="addEvent" @change="addEvent" />
<input type="checkbox" @input="addEvent" @change="addEvent" />
<input type="radio" name="radio" value="1" @input="addEvent" @change="addEvent" />
<input type="radio" name="radio" value="2" @input="addEvent" @change="addEvent" />
<select @input="addEvent" @change="addEvent">
<option value="1">1</option>
<option value="2">2</option>
</select>
<ul>
<li v-for="event in events">{{ eventText(event) }}</li>
</ul>
</div>
new Vue({
el: '#app',
data: {
events: []
},
methods: {
addEvent ({ type, target }) {
const event = {
type,
isCheckbox: target.type === 'checkbox',
target: {
value: target.value,
checked: target.checked
}
}
this.events.push(event)
},
eventText (e) {
return `${e.type}: ${e.isCheckbox ? e.target.checked : e.target.value}`
}
}
})
插槽
可分为普通插槽和作用域插槽,但2.0之后就不再区分了
1.普通插槽:父->子,父组件传递数据/元素/组件给子组件,子组件定义
<slot>占坑
2.作用域插槽:子->父,子组件<slot>绑定属性,传递(数据)给父组件,父组件通过slot-scope接收子组件传递属性
3.使用v-slot新语法,代替旧语法
4.多插槽时使用具名插槽方式(<slot name="header">),用于将数据绑定在指定的插槽
Slot.vue
<template>
<div>
<slot />
<slot name="title" />
<slot name="item" v-bind="{ value: 'vue' }" />
</div>
</template>
<script>
export default {
name: "SlotDemo"
};
</script>
使用
<h2>2.6 新语法</h2>
<SlotDemo>
<p>default slot</p>
<template v-slot:title>
<p>title slot1</p>
<p>title slot2</p>
</template>
<template v-slot:item="props">
<p>item slot-scope {{ props }}</p>
</template>
</SlotDemo>
<br />
<h2>老语法</h2>
<SlotDemo>
<p>default slot</p>
<p slot="title">title slot1</p>
<p slot="title">title slot2</p>
<p slot="item" slot-scope="props">item slot-scope {{ props }}</p>
</SlotDemo>
显示效果如下:
计算属性和监听器
- 减少模板中计算逻辑
- 数据缓存
- 依赖固定的数据类型(响应式数据)
- 更加灵活、通用
- watch中可以执行任何逻辑,如函数节流、ajax异步获取数据、甚至操作dom
computed vs watch
- computed能做的,watch都能做,反之则不行
- 能用computed的尽量用computed
补充:
生命周期的应用场景和函数式组件
生命周期分为三个阶段:
- 创建阶段
- 更新阶段
- 销毁阶段
创建阶段
更新阶段
销毁阶段
函数式组件
- functional: true
- 无状态、无实例、没有this上下文、无生命周期