0. render 函数:用来渲染模板的
render (createElement, context) {
// 渲染模板返回的值就是页面展示的效果
return createElement('h1', '标签1')
}
1. 交给vue进行管理的函数,一般格式写this对象会指向vm,写成箭头函数this则会指向window;不是vue管理的函数,一般写成箭头函数则会指向vm,写成一般格式则会 指向window
2. Vue.set()
在对现有的对象进行添加属性或者修改,如果直接通过如下直接赋值的方式是不会生效的。
export default {
data () {
return {
persons: [
{id: 1, name: "张三", age: 18},
{id: 2, name: "李四", age: 15}
]
}
},
methods: {
changeObj(){
this.persons[0] = {id: 1, name: "赵六", age: 88} // 直接赋值不会生效
}
}
}
是因为一般在data中的属性或对象都会有各自对应的getter和setter,直接添加是没有这两个对应方法,导致不会去重新渲染模板,但是数据已经被修改的情况。通过使用Vue.set()可以解决新增属性或者修改属性达到动态修改渲染视图。
changeObj(){
// 为某个对象添加属性;但是有局限性,只能给data中某个对象去追加属性,并不能直接往data身上直接追加
this.$set(student, "gender", "male")
// 修改数组的第一个元素
this.$set(this.persons, 0, {id: 1, name: "赵六", age: 88})
}
※:也可以通过调用一些被vue包裹的api进行操作也会进行动态的渲染,例如数组的api,也可以被vue侦听到重新渲染模板
push()、pop()、shift()、unshift()、splice()、sort()、reverse()
3. 过滤器
通过一个 | 代表过滤器,类似Linux的管道操作,可以嵌套多个过滤器。
<p>{{ keywords | changeWord("yyyy") }}</p> 有参过滤器
<p>{{ keywords | changeMsg }}</p> 无参过滤器
<p>{{ keywords | changeMsg | changeWord("yyyy") }}</p> 嵌套过滤器
<script>
export default {
filters:{
changeWord(value, str){
return value + str
},
changeMsg (value){
return value
}
}
}
</script>
上面定义的是局部过滤器,组件和组件之间不能共用,下面定义全局过滤器。
Vue.filter("changeMsg",function (value){
return value.subString(1)
})
4. 收集表单参数
通过 v-model 接收参数,只会接收到 input 类型的 value 值。当遇见CheckBox时会比较特殊。
乒乓球:<input type="checkbox" value="pingPang" v-model="hobby">
羽毛: <input type="checkbox" value="badminton" v-model="hobby">
<script>
export default {
data(){
return {
hobby: [], // 空数组接收CheckBox,接收到为各个value组成的数组
hobby: "" // 永远接收到true/fasle
}
}
}
</script>
还可以设置一些v-model接收的相关信息
v-model.lazy // 代表懒加载,失去焦点时,才会将值同步过去
v-model.number // 只接受数字类型
v-model.trim // 自动去除空格
5. 一些指令
<p v-cloak>{{name}}</p> // 在渲染前不会展示
<p v-once>{{age}}</p> // 只会参与一次计算
<p v-pre>XXX</p> // 不会解析内容
6. vue的生命周期(启动大致流程)
启动流程:
1 首先初始化Vue相关的事件、以及生命周期相关。
2 执行BeforeCreate钩子函数,此时还无法访问vm中的data、methods。
3 初始化数据监测、数据代理。
4 执行created钩子函数可以访问vm中的data、methods。
5 判断是否有配置el配置项,如果没有在vm.$mount(el)时候再执行。
6 判断是否有配置template配置项,如果没有则编译el的外部HTML作为模板,生成虚拟dom;如果有通过render函数解析模板。
7 执行beforeMount钩子函数,此时页面还未经过编译,所有对dom的操作都不会生效。
8 将虚拟dom 替换 真实dom,创建vm.$set 并替换掉 el。
9 执行mounted钩子函数,页面呈现经过vue编译的dom, 对dom的操作均奏效, 一般再次进行开启定时器,订阅消息,绑定自定义事件 初始化过程结束。
更新流程:
首先会执行 beforeUpdate钩子函数,此时数据是新的,页面是旧的。
然后根据新数据生成新的虚拟dom。
最后执行 updated 钩子函数,此时数据是新的,页面也是新的; PS:尽量不要在这里更改组件的状态有可能会导致无限循环。
销毁流程
首先会执行 beforeDestroy 钩子函数, 一般在此关闭定时器,取消消息订阅等工作 dom还可以用。
然后移除所有的组件以及所有的监视。
最后执行 destroyed 钩子函数。
当vm调用$destroy的时候就会触发销毁流程,调用该方法会清除vm实例,并清除它与其他实例的链接,解绑所有命令,只是会将自定义事件解除。
在销毁hook函数中放更新数据的操作,不会触发updated和beforeUpdate钩子的。
7. 组件相关
通过 Vue.extend 创建子组件
// 传入的参数和 new Vue的时候相似,不需要传$el这个属性
const newA = Vue.extend({
data () {
return {
name: "sonComponent"
}
}
})
使用组件时,如果是单文件组件需要先引入。
<template>
// 相当于一个标签进行使用,组件内部可以嵌套
<top-bar></top-bar>
</template>
<script>
import topBar from './topBar'
export default {
// 局部注册
components: {
// 别名: 实际组件名称
topBar: topBar
}
}
</script>
※:每个组件中的 this 都是指向当前组件对象。
注册全局组件:
Vue.component('hello', {}) // 名称,传递的对象和new Vue大致相同
组件的本质:
直接输出组件,会发现其本质就是一个构造函数 VueComponent,由 vue.extend 方法生成的。
ƒ VueComponent (options) {
this._init(options);
}
※:vm 和 vc 有如下关系,这样是为了让 vc 也能使用 vm 的东西。让Vue原型对象作为兜底。
VueComponent.protoType.__proto__ === Vue.protoType
8. ref 属性:可以通过ref 绑定一个dom对象,相当于 id 属性的替代品。
<p ref="tar">我是个标签</p>
<script>
// 可以通过 this.$refs 拿到具体的dom,无需自己再手动操作dom
console.log(this.$refs.tar)
</script>
9. props 属性:用于向组件传递参数,并规范接收参数的格式等属性。可以在子组件的 $attrs 查看到父组件传递但是并未声明接收的属性;如果接收了就不会出现在 $attrs 中。
向组件传递参数
<top-bar peach="桃子" pear="梨"></top-bar>
<!-- 加上冒号 通过绑定的形式进行传值 这样可以解决每次都是字符串的问题 -->
<top-bar peach="桃子" :pear="1"></top-bar>
接收参数
export default {
// 方式一: 只写变量名称
props: ['peach', 'pear']
// 方式二: 指定类型接收,类型不匹配也能显示出来,但是会报错
props: {
'peach': String,
'pear': Number
}
// 方式三: 指定每个字段的类型
props: {
'pear': {
required: false, // 指定是否必填
type: String, // 指定类型
default: 'sdsd' // 指定默认值
}
}
}
tips:props是只读的不能修改,如果需要修改需要在data中进行备份;当和自身的data中变量名称冲突时,props的优先级更高。
10. 混入(mixIn)
所谓混入,就是将两个组件通用的逻辑抽离成一个单独的文件。
混入文件:
export default {
mounted () {
console.log("挂载")
},
methods: {
makeNoise(){
console.log("makeNoise")
}
}
}
局部混入:
import mix from '../public_minins' // 引入混入文件
export default {
// 如果方法或属性冲突了,会以当前实例的为主;如果生命周期钩子冲突会都执行。
mixins: [mix] // 可以混入多个js
}
全局混入:在 main.js 中进行配置
import mix from './public_minins'
Vue.mixin(mix)
11. 插件
插件的本质是个对象,但是必须要有一个install 方法,这个方法Vue会来调用。
定义插件:
export default {
install(Vue, option){
// 可以接收两个参数,第一个是Vue对象,第二个是注册时传入的参数
}
}
注册插件:
import tip from './public_minins'
Vue.use(tip, '你的名字', '天气之子')
12. 事件总线
用于组件之间信息的传递,其实Vue中没有事件总线,只不过是向 Vue.prototype 身上定义了一个组件属性,这样可以让所有的 vm 和 vc 都可以使用,通过这个这个组件进行消息的绑定和触发,以此达到传递消息的目的。一般多用于兄弟组件之间。
定义事件总线:一般在beforeCreated中定义
new Vue({
...
beforeCreate () {
Vue.prototype.messageBus = this // 创建一个事件总线
}
})
在A组件中注册事件
<script>
export default {
name: 'A',
mounted () {
// 为总线绑定触发事件
this.messageBus.$on("sendMessage", function (obj){
console.log(obj)
})
},
beforeDestroy () {
// 在组件销毁时最好解绑事件
this.messageBus.$off("sendMessage")
}
}
</script>
在B组件触发事件
<script>
export default {
name: 'Item',
props: ["obj"],
methods:{
clickMe(){
this.messageBus.$emit("sendMessage", this.obj)
}
}
}
</script>
13. 动画和过渡
动画和过渡都需要 <transition> 标签对HTML元素进行包裹。通过v-show控制元素是否展示。
<template>
<!-- 定义name以后vue会根据name名称寻找css,appear接收布尔值用于控制进入页面是否触发动画 -->
<transition name="me" :appear="true">
<div v-show="isShow" style="width: 100px; height: 100px">AAAA</div>
</transition-group>
</template>
动画css的定义:需要定义好@keyframe,以及按照vue规则定义好的css。vue的类名规则是:name(transition标签中定义的name,如果没有定义默认是 v) - 动作(enter / leave) - active。
<style scoped>
/*动画离开时激活的效果 */
.me-leave-active{
animation: mymove 1s reverse;
}
/*动画进入时激活的效果 */
.me-enter-active{
animation: mymove 1s;
}
@keyframes mymove {
from{
transform: translateX(-100px);
}
to{
transform: translateX(100px);
}
}
</style>
过渡效果css的定义:这里也是需要和name属性一起使用,不过有个技巧是,过渡开始起点就是过渡结束的终点,过渡开始终点就是过渡结束起点。
<style scoped>
/*过渡开始起点,已经结束的终点 */
.me-enter, .me-leave-to{
transform: translateX(-100%);
}
/*过渡进入、离开执行 */
.me-enter-active, .me-leave-active{
transition: 0.5s linear;
}
/*过渡开始终点,结束起点*/
.me-enter-to, .me-leave{
transform: translateX(100%);
}
</style>
※:transition 标签只能对一个元素进行控制,多个需要用 transition-group 标签,并为每个元素配置 key属性。
14. nextTick
在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。有点类似 setTImeOut。
this.$nextTick(function (){})
15. 插槽(slot)
为了展示在子组件标签中的HTML,需要在子组件中定义slot标签用于标识展示的位置;类似于给子组件传了一段HTML过去;好比在子组件中挖坑,父组件调用时传递。可以在子组件的 $slots 上查看到插槽信息。如果父组件传递但是子组件没有展示也不会丢失,还会在 $slots 中出现。
默认插槽:如果没有传slot对应的内容会展示默认文字。
父组件:
<span>卓哥哥</span>
子组件:
<template>
<div><slot>slot标签中可以显示文字是默认内容</slot></div>
</template>
具名插槽:在slot标签上添加name属性。父组件中通过slot属性进行指定,如果父组件中传递的是template标签还有第二种写法。
父组件:
<template>
<div><span slot="head">卓哥哥</span></div>
</template>
子组件:
<slot name="head">slot标签中可以显示文字是默认内容</slot>
template标签传递:
父组件:
<template>
<div><template v-slot:head></template></div>
</template>
子组件:
<slot name="head">slot标签中可以显示文字是默认内容</slot>
作用域插槽:子组件可以将自身的数据传入slot中,父组件引用时 通过slot-scope进行获取,还可以在这里进行结构解析。
父组件:
<div slot="head" slot-scope="obj">
<span v-for="item in obj.games" :key="item">{{item}}</span>
</div>
子组件:
<slot name="head" :games ="games" >slot标签中可以显示文字是默认内容</slot>
16. axios 和 vue-resource
axios 和 vue-resource 都是类型Ajax的异步请求工具。一般推荐使用axios,vue-resourcce年久失修。 两者返回的都是promise的结构。
17. 路由
在vue中使用路由控制展示的组件,文件一般定义在 router/index.js。在创建vue实例的时候需要传递进去。
import Router from 'vue-router' // 引入路由
Vue.use(Router) // 使用路由
export default new Router({
mode: 'history', // 默认是hash模式(url代#) history(不带#)
routes: [ // route中定义多组路由信息
{
path: '/app', // 路径, 一级路由需要加斜杠
name: 'App', // 路由名称
component: App, // 展示的组件
children:[ // 定义二级路由
{
path: 'grandson', // 子级都不需要斜杠
name: 'grandson',
component: grandson,
},{...}
]
},{...}
]
})
添加 vue-router 以后就会多了$router 和 $route 属性,每个组件都会有属于自己的 $route 属性,所有组件的 $router 都是相同的,也就是说全局只会有一个$router属性。
在vue中很少使用<a>标签,转而更多的会用 <router-link> 标签,经过vue编译后的 <router-link> 也会转变成 <a> 标签。
<!--to: 指定跳转的组件路由
active-class: 指定激活时的样式
replace: 请求路由会替换当前记录
-->
<router-link to="/group1">group1</router-link>
通过 router-link 标签给跳转组件传递参数:
(1) 通过 $route.query 参数
<!-- 这样传递参数会放到$route.query中,${} 进行参数值的获取 简写形式-->
<router-link to="/group1/grandson?msg=${item.id}">component</router-link>
<!-- to属性传递一个对象的格式 标准形式1 -->
<router-link :to="{
path: '/group1/grandson', // 指定跳转路由
query:{ msg: 'QQPP' }// 指定query的参数
}">component</router-link>
<!-- 通过名称指定路由 标准形式2 -->
<router-link :to="{
name: 'component',
query:{ msg: 'QQPP' }
}">component</router-link>
(2) 通过$route.param接收
首先需要在路由中定义好每个占位的变量。
{
path: 'grandson/:msg/:title', // 通过 冒号+变量名的格式
component: grandson
}
在传递的时候直接传递
<!-- 通过斜杠直接往后拼接 写法一-->
<router-link to="/group1/grandson/消息/标题">component</router-link>
<!--写法二 -->
<router-link :to="{
path: '/group1/grandson',
params:{ msg: '消息', title: '标题' }
}">component</router-link>
通过props进行参数传递
// 传递死数据
{
path: 'grandson',
component: grandson,
props: {msg: "消息标题"} // 将值以props属性形式传递给目标组件
}
// 如果值为真 将路由组件收到的 params 参数以 props 形式传递给组件
{
path: 'grandson',
component: grandson,
props: true
}
// 函数的返回值作为 props 形式传递给组件
{
path: 'grandson',
component: grandson,
props: function ($route){ // 这里更简单的写法是结构解析
return {msg: $route.params.msg}
}
}
缓存组件的内容:使用 <keep-alive> 标签进行缓存组件,通过include可以指定缓存哪些组件,值是组件名称;需要注意 <keep-alive> 需要给 <router-view> 使用。
<router-link to="/group1/grandson">component1</router-link>
<router-link to="/group1/grandson2">component2</router-link>
<p>
<keep-alive :include="['grandson2',]">
<router-view/>
</keep-alive>
</p>
使用 router 后会新增两个钩子函数,需要注意组件需要被 <keep-alive> 标签进行包裹。
activated () { // 组件激活时触发的hook函数
console.log("激活")
},
deactivated () { // 组件失活时触发的hook函数
console.log("失活")
}
前置路由守卫
/* to: 前往的路由
from: 起始的路由
next: 放行函数
*/
router.beforeEach((to, from, next) => {
if(to.path.indexOf('grand') === -1){
next() // 放行,如果不执行next就代表 被阻塞了
}
})
后置路由守卫
/* to: 前往的路由
from: 起始的路由
*/
router.afterEach((to, from) => {})
路由自定义信息
{
path: '/App',
name: 'App',
component: App
meta: {} // 这里可以自定义一些数据
}