名称 | 内容 |
---|---|
$data | 传入的data内容,修改可引发页面内容变化 |
$props | 父组件传入子组件 |
$el | 绑定的html的节点 |
$options | 新建Vue实例对象时穿进去的内容,修改optins的内容不会引发页面变化,有render方法,在页面从新渲染时会调用 |
$root | 整个Vue对象的根节点,app.$root === app |
$children | 组件内部的元素 |
$slots | 插槽 |
$scopedSlots | 区域化插槽 |
$refs | 模板的引用 |
$isServer | 服务端渲染时能够用来判断 |
$watch | 监听内容,与写在实例中效果相同,但经过$watch写的监听要返回的unWatch方法结束监听 |
$on | 监听事件是否被触发,能够获取emit传递的参数 |
$emit | 触发事件,监听哪一个对象就要经过哪一个事件触发,能够传值 |
$once | 与on类似,但只被触发一次 |
$forceUpdate | 强制组件从新渲染 |
$set | 给新值赋值而且页面会渲染 |
$delete | 删除值 |
$nextTick | 异步操做 |
生命周期 | 介绍 | 可调用次数 |
---|---|---|
beforeCreate | 还未绑定Dom,不能进行dom操做**(不要放入ajax请求)** | |
created | 还未绑定Dom,不能进行dom操做 | |
beforeMount | el只为html中写的节点,还未绑定,说明还未渲染(未调用render方法) | |
mounted | el绑定为渲染后的节点,说明以前进行了渲染(已调用render方法),实例已经建立完成 | |
beforeUpdate | 更新的对象时模板,须要虚拟DOM的重洗渲染和补丁修改,可是若是更改的数据在模板中没有使用,就不会进行更新 | |
updated | 数据更改致使虚拟DOM从新渲染和打补丁,注意要避免在这个钩子函数中操做数据 | |
activated | ||
deactivated | ||
beforeDestory | 实例销毁以前调用。在这一步,实例仍然彻底可用,this仍能获取到实例。通常在这一步中进行:销毁定时器、解绑全局事件、销毁插件对象等操做 | |
destoryed | Vue 实例销毁后调用。调用后,Vue 实例指示的全部东西都会解绑定,全部的事件监听器会被移除,全部的子实例也会被销毁 |
指令名 | 指令做用 |
---|---|
v-text | 标签里面要显示的文本内容,内容较多时不建议使用 |
v-html | 将html代码片断展现为html标签 |
v-show | 根据内容的Boolean值来显示或不显示内容,原理是设置display:none; |
v-if | 与v-show不一样的是若是判断为false将不会放在文档流里,若是频繁切换会动态增删节点,会形成性能问题 搭配指令有 v-else v-else-if |
v-for | 循环,用法为 v-for="item in arr",item为数组内的值或对象,arr为储存值的数组,若是要拿到顺序则写为v-for="(item, index) in arr" 遍历对象可用 v-for="(val, key,index) in obj"的方式,val为值,key为对应的键,index为对应的索引值即顺序,使用v-for时须要:key=""来绑定一个惟一识别 |
v-on | 监听事件,能够监听到$emit触发的事件 |
v-model | 双向绑定数据,可进行实时更改,通常用于input,通常输入以后会变为字符串 |
若是想让值为数字,在v-model后加.number修饰符 | |
若是想去掉首位的空格,在v-model后加.trim修饰符 | |
若是不想实时更改,而是失焦后更改,在v-model后加.lazy修饰符 | |
v-pre | 不解析内部内容,即内部内容保留源格式 |
v-cloak | 通常直接在页面引入vue.js代码时使用,在vue代码完成以前让内容隐藏,vue加载完成后再展现 |
v-once | 数据绑定内容只执行一次,通常为静态内容使用,节省性能开销,不会作虚拟DOM对比 |
首先写一个组件内容javascript
const component = {
templete: '<div>This is compoent</div>'
}
复制代码
而后咱们用Vue实例的方法引入组件html
import Vue from 'vue'
Vue.component('ComponentName',component); //定义了一个名为name的组件
//组件名用大写开头并用驼峰命名 (类的思想)
复制代码
使用时:前端
第一种状况-直接在tempelate内使用:vue
new Vue({
el:'#root',
tempelate:'<component-name></component-name>' //使用时使用小写,而且单词之间用-链接
})
复制代码
第二种状况-从新命名使用:java
new Vue({
el:'#root',
tempelate:'<new-name-component></new-name-component>',
//使用时使用小写,而且单词之间用-链接
components: {
newNameComponent: component
}
})
复制代码
const component = {
templete: '<div>{{text}}</div>',
data(){ //必需要使用函数返回值的方式
return{
text:'hello'
}
}
}
复制代码
使用一个return新对象的方法能够防止多个组件动态绑定至一个相同的值,例如v-model的场景就会出现相关的问题webpack
const component = {
templete: ` <div> <span v-show="active">see me if active</span> <span>{{propOne}}</span> //prop与data类似都是绑定在this上,能够直接使用 </div> `
data(){ //必需要使用函数返回值的方式
return{
text:'hello'
}
},
props: {
active: Boolean,//向组件传递一个布尔值,key为active
propOne: String //驼峰式命名
}
}
复制代码
使用时web
new Vue({
el:'#root',
tempelate:` <new-component :active="true" prop-one="123"></new-component> //须要用v-bind解析传入的值 <new-component :active="false" prop-one="456"></new-component> //在prop中为驼峰式的命名在使用时使用小写而且用-链接的方式(非强制,只是规范) `,
//使用时使用小写,而且单词之间用-链接
components: {
NewComponent: component
}
})
复制代码
props数据的一些设置ajax
const component = {
props: {
active: {
type: Boolean, //设置为布尔值
required: true, //这个属性为必需属性
default: true, //设置默认值为true,若是有了default就不须要required
validator (value) { //可用来检测输入的值是否符合要求,可用来自定义检测
return typeof value === 'Boolean'
}
},
propOne: {
type: Object,
default() { //若是默认值为一个对象,则应该用函数返回一个对象的形式
return {
}
}
}
},
.....
}
复制代码
当咱们新建一个Vue实例时,它内部都是一些默认的属性,若是咱们想使用咱们已经定义过的组件的一些属性内容咱们能够用下列代码:vue-router
... 已建立组件component
const ComponentVue = Vue.extend(component); //前提是component没有required为true的props
new ComponentVue({
el: '#root',
})
复制代码
但若是咱们须要用到props呢?vuex
咱们能够用下面的方式:
... 已建立组件component
const ComponentVue = Vue.extend(component);
new ComponentVue({
el: '#root',
propsData: { //用propsdata来向原组件的props传值才能使用
propOne: 'xxx',
}
})
复制代码
会先执行原组件的mounted,再执行extend实例的mountend
const component = {
props: ['value'],
template: ` <div> <input type="text" @input="handleInput" v-model="value" > </div> `,
methods: {
handleInput(e) {
this.$emit('input', e.target.value); //向父组件触发input事件
}
}
}
//在Vue实例中
new Vue({
components: {
CompOne: component
},
el: '#root',
data () {
return {
value: '123'
}
}
template: ` <div> <comp-one :value="value" @input="value = arguments[0]"></comp-one> //arguments数组即为经过$emit后面传递的参数 </div> `
})
复制代码
咱们还能够经过下面的功能实现
const component = {
model: {
prop: 'value1', //为要传的值
event: 'change' //为触发的事件
},
props: ['value1'],
template: ` <div> <input type="text" @input="handleInput" v-model="value1"> </div> `,
methods: {
handleInput(e) {
this.$emit('input', e.target.value); //向父组件触发input事件
}
}
}
//在Vue实例中
new Vue({
components: {
CompOne: component
},
el: '#root',
data () {
return {
value: '123'
}
}
template: ` <div> <comp-one v-model="value"></comp-one> //arguments数组即为经过$emit后面传递的参数 </div> `
})
复制代码
当咱们在Vue实例调用的组件内部直接写入html元素时,它是不会显示的,由于咱们没有告诉组件要放在哪里显示,这时就须要 插槽 了
//组件内
const component = {
template: ` <div> <slot></slot> //为内容添加插槽位置,没有声明插槽位置的元素都会放在这个里面 </div> `
}
//实例中
new Vue({
components: {
CompOne: component
},
el: '#root',
template: ` <div> <comp-one> <span>我会被放在slot中</soan> </comp-one> </div> `
})
复制代码
具名插槽
//组件内
const component = {
template: ` <div> <div class="header"> <slot name="header"></slot> </div> <div class="body"> <slot name="body"></slot> </div> </div> `
}
//实例中
new Vue({
components: {
CompOne: component
},
el: '#root',
template: ` <div> <comp-one> <span slot="header">我会被放在slot name为header的插槽中</soan> <span slot="body">我会被放在slot name为body的插槽中</soan> </comp-one> </div> `
})
复制代码
做用域插槽 让插槽内绑定的数据为组件的数据
使用方法为:
//组件内
template: ` <div> <slot value="456" anothervalue="content"></slot> </div> `
//实例中
template:` <div> <comp-one><span slot-scope="props">{{props.value}} {{props.anothervalue}}</span></comp-one> //slot-scope 的对象即为组件内slot传递值的对象 </div> `
复制代码
或者可使用组件内部data的值,它并不影响本地data的使用:
//组件内
template: ` <div> <slot :value="value" anothervalue="content"></slot> //注意要使用v-bind形式 </div> `,
data() {
return{
value="this is data value"
}
}
//实例中
template:` <div> <comp-one><span slot-scope="props">{{props.value}} {{props.anothervalue}}</span></comp-one> //slot-scope 的对象即为组件内slot传递值的对象 </div> `
复制代码
如何越级拿到vue组件实例呢?
使用 provide属性!
//子组件
const ChildComponent = {
template: '<div>child component</div>',
inject: ['grandfather'] //获取实例向外提供的对象
}
//组件
const component = {
name: 'comp',
component: {
ChildComponent //声明子组件
},
template: ` <div> <child-component /> //若是为空组件能够这样书写 </div> `,
}
//实例
new Vue({
components: {
CompOne: component
},
provide (){
return{
grandfather: this //将本身这个实例做为对象向外提供,仅为节点下的节点(子节点 & 子节点的子节点 $ ......)
} //使用函数返回值的方式的缘由与data相同
},
...
})
复制代码
但通常provide只提供一次值,不会实现model模式,若要实现须要给provide的值提供得到方法,方法以下:
provide (){
return{
const data = {} //先设置一个空对象
Object.defineProperty(data,'value',{
get: () => this.value, //没次使用值时实际上是用了这个get方法
enumerable: true //可读属性
})
}
}
复制代码
这种方法虽然是实现了跨级model,但属于一种hack方法,官方不建议使用。
render方法是咱们渲染的一个方法,它内部会返回一个createElement方法,这个方法是Vue给咱们提供的建立节点的方法,使用render方法咱们就能够不使用template
//组件
const component = {
name: 'comp',
props: ['props1'],
render (createElement) {
return createElement('div', {
//data数据 data: this.data形式
},[ //注意要传递数组
this.$slots.default //无名为default,具名slot将default改成名字便可
this.props1 //传递prop值
])
}
}
//实例
new Vue({
components: {
CompOne: component
},
render( createElement ) { //不必定为createElement,能够用其余字母表示,但下面的方法名要保持一致
return createElement(
'comp-one',{
ref: 'comp'
},[ //注意节点内在建立节点要传递一个数组
createElement(
'span',{
ref: 'span',
slot: 'header' //能够指定要渲染的slot插槽位置
},this.value)
]) //Vue提供的建立节点的函数
}
})
复制代码
on形式的监听,须要实例和组建中都使用on
//组件
const component = {
name: 'comp',
props: ['props1'],
render (createElement) {
return createElement('div', {
on: {
click: () => {this.$emit('click')} //监听click事件,向父级触发click事件
}
},[ //注意要传递数组
this.$slots.default //无名为default,具名slot将default改成名字便可
this.props1 //传递prop值
])
}
}
//实例
new Vue({
components: {
CompOne: component
},
render( createElement ) { //不必定为createElement,能够用其余字母表示,但下面的方法名要保持一致
return createElement(
'comp-one',{
ref: 'comp',
on: {
click: this.handleClick //点击组件会受到组件传递的click事件,并触发handleClick方法
}
},[ //注意节点内在建立节点要传递一个数组
createElement(
'span',{
ref: 'span'
},this.value)
]) //Vue提供的建立节点的函数
},
methods: {
handleClick() {
//do something....
}
})
复制代码
nativeOn 有个很大的便捷,那就是咱们只须要在实例中声明而组件中能够不用声明
//组件
const component = {
name: 'comp',
props: ['props1'],
render (createElement) {
return createElement('div', {
},[ //注意要传递数组
this.$slots.default //无名为default,具名slot将default改成名字便可
this.props1 //传递prop值
])
}
}
//实例
new Vue({
components: {
CompOne: component
},
render( createElement ) { //不必定为createElement,能够用其余字母表示,但下面的方法名要保持一致
return createElement(
'comp-one',{
ref: 'comp',
nativeOn: {
click: this.handleClick //nativeOn会自动绑定到组件根节点的dom上面
}
},[ //注意节点内在建立节点要传递一个数组
createElement(
'span',{
ref: 'span'
},this.value)
]) //Vue提供的建立节点的函数
},
methods: {
handleClick() {
//do something....
}
})
复制代码
template实际上是render方法的一种编译方式
router,顾名思义即为路由,vue框架可让咱们在前端实现路由功能,这个功能对WebApp这种应用来讲是必不可少的。
使用路由以前须要先安装模块,npm install vue-router
通常咱们将路由分为两个文件,router.js 和 routes.js,一个用来存放路由信息,另外一个用来写路由逻辑功能
//routes.js
import Todo from '../views/todo/todo.vue' //引入要展现的页面
import Login from '../views/login/login.vue'
export default [
{
path: '/', //网页的路径
component: Todo //指定输入上方路径后显示什么页面
},
{
path: '/login',
compoent: Login
}
]
复制代码
//router.js
import Router from 'vue-router' //引入vue-router模块
import routes from './routes' //引入咱们写的路由信息
//每次引入路由文件时会返回一个路由对象
export default () => {
return new Router({
routes
})
}
复制代码
为了实现跳转,咱们还须要用router-view来实现对路由跳转事后的展现
// app.vue
<template>
<div id="app">
<div id="cover"></div>
<Header></Header>
<router-view></router-view> //这部分来进行跳转,页面内容展现在这部分
<!-- <todo></todo> -->
<Footer></Footer>
</div>
</template>
复制代码
咱们也能够用路由来实现首页重定向,在routes.js写入这部份内容
//routes.js
import Todo from '../views/todo/todo.vue' //引入要展现的页面
import Login from '../views/login/login.vue'
export default [
{
path: '/',
redirect: '/app' //当输入默认路径时重定向到app页面
},
{
path: '/app', //网页的路径
component: Todo //指定输入上方路径后显示什么页面
},
{
path: '/login',
compoent: Login
}
]
复制代码
此时咱们会注意到网页上的url是 http://localhost:8080/#/app,他默认会传一个hash,咱们能够更改这个东西须要更改router.js的内容
import Router from 'vue-router' //引入vue-router模块
import routes from './routes' //引入咱们写的路由信息
//每次引入路由文件时会返回一个路由对象
export default () => {
return new Router({
routes,
mode:'history' //mode改成 'hash'即为hash方式
})
}
复制代码
此时在此运行我就能够发现那个#消失了
咱们还能够经过base属性设计基路径
import Router from 'vue-router' //引入vue-router模块
import routes from './routes' //引入咱们写的路由信息
//每次引入路由文件时会返回一个路由对象
export default () => {
return new Router({
routes,
mode:'history',
base: '/base/' //设置基路径为base,经过vue-router的跳转都会加入基路径
})
}
复制代码
此时咱们再访问localhost:8080发现他的路径跳转为了
localhost:8080/base/app
但基路径并非强制的,咱们把base去掉访问依然能够访问到app
还有两个属性使咱们要配合router-link使用的
//app.vue
<template>
<div id="app">
<div id="cover"></div>
<Header></Header>
<router-link to="/app">app</router-link>
<router-link to="/login">login</router-link>
<router-view></router-view>
<!-- <todo></todo> -->
<Footer></Footer>
</div>
</template>
复制代码
咱们在app.vue中加入两个router-link(与a标签相似,原理是经过a标签实现的),to的内容即为他们要跳转的路由,而后咱们能够全局设置连接的样式
export default () => {
return new Router({
routes,
mode:'history',
linkActuveCLass:'active-link', //只要有一部分被激活会加上
linkExactActiveClass: 'exact-active-link' //当前路径彻底匹配才加上
})
}
复制代码
可能会有点难理解,那咱们这样想,你当前有一个/app的页面,展现的是app.vue,而后app下面有个子页面是childApp.vue,路径是/app/childApp,当咱们在localhost:8080/app/childApp的路径下时,此时routerlink to 为childApp的连接的样式为'active-link' 和'exact-active-link',而app的routerlink的样式为'active-link' 而不会有'exact-active-link'
咱们把路径输入url时,按下回车,会想服务器发送一个请求,若是此时咱们没有在服务器中,添加路由映射时,浏览器会返回咱们一个错误信息
Cannot GET /xxx //xxx即为url的内容
//webpack.config.client.js
const devServer = {
port: 8000,
host: '0.0.0.0',
overlay: {
errors: true,
},
historyApiFallback: {
index: 'index.html' //加上这个咱们输入url后刷新页面仍是会显示出内容
},
hot: true
}
复制代码
咱们有时在跳转页面时,不想回到上一级时已经返回到了顶部而不是跳转以前的位置,咱们能够在Router里设置一个scrollBehavior
export default () => {
return new Router({
routes,
mode:'history',
scrollBehavior (to, from, savedPosition){ //to -> 跳转的路由 from -> 当前的路由即跳转的起始点 savedPosition -> 保存当前滚动条滚动的位置
if(savedPosition) { //若是是有滚动距离的,返回到以前的页面位置
return savedPosition
} else { //不然,返回顶部
return {x:0 , y:0}
}
}
})
}
复制代码
这部分主要讲路由方面的参数
import Todo from '../views/todo/todo.vue'
import Login from '../views/login/login.vue'
export default [
{
path: '/',
redirect: '/app' //当输入默认路径时重定向到app页面
},
{
path: '/app',
component: Todo,
name: 'app' //给当前的路由设置一个姓名,能够用来跳转,与路径和组件名无强制联系
},
{
path: '/login',
compoent: Login
}
]
复制代码
而后在routerlink上能够进行经过name跳转
<router-link :to="{name:'app'}"> </router-link> //传入对象,让Vue来解析它
复制代码
以后就能够进行跳转了,没必要每次都要写路径
用来存放一些元信息
import Todo from '../views/todo/todo.vue'
import Login from '../views/login/login.vue'
export default [
{
path: '/',
redirect: '/app' //当输入默认路径时重定向到app页面
},
{
path: '/app',
component: Todo,
meta: {
title:'this is app', //与html的meta一样的效果
description: 'author Reaper Lee'
}
},
{
path: '/login',
compoent: Login
}
]
复制代码
用来写当前路径下的子组件
import Todo from '../views/todo/todo.vue'
import Login from '../views/login/login.vue'
export default [
{
path: '/app',
component: Todo,
children: [ //注意是数组
{
path: 'child', //路径信息,与父级相同
component: Child
}
]
}
]
复制代码
但注意这个只会在 父组件即(Todo)下的routerview展现,不会和Todo抢占同一个routerview
transition顾名思义就是路由的过分,即为一次过渡动画,咱们使用时要配合routerview使用
//app.vue
<template>
<div id="app">
<router-link to="/app">app</router-link>
<router-link to="/login">login</router-link>
<transition name="fade"> //使用fade的动画做为过渡
<router-view></router-view>
</transition>
</div>
</template>
<style> //定义这个fade动画 .fade-enter-active, .fade-leave-active { transition: opacity .5s; } .fade-enter, .fade-leave-to { opacity: 0; } </style>
复制代码
咱们能够经过路由传递一些参数,这个会在咱们好比查看一个物品的详情页等场景使用会比较多。具体方法以下
// routes.js
export default [
{
path: '/app/:id', //这里咱们就声明了一个路由上的参数
component: Todo,
}
]
复制代码
此时咱们直接访问/app 是不会有内容的
但当咱们访问/app/xxxx (xxxx为要传递的参数),此时咱们就能够正常的显示页面,咱们获取这个参数能够在父组件中使用this.$route来获取参数
this.$router.params.id 就能够拿到路径中的参数了,id是咱们在上面的path中给的参数名为id,要与参数名保持一致
复制代码
还有一种更强大的方法,那就是把路径中的参数做为组件的props传递给组件
// routes.js
export default [
{
path: '/app/:id', //这里咱们就声明了一个路由上的参数
props:true, //这里咱们设置为true便可让参数做为props传递给组件
component: Todo
}
]
复制代码
而后在组件中咱们须要把参数的props声明
//todo.vue
export default {
props: ['id'] //声明一个名为 id 的props数据
}
复制代码
而后咱们就能够在组件中拿到这个参数了!并且经过props传递的参数咱们能够更好的使用,因此若是真的须要经过路径传参数咱们尽量使用props。
咱们有时会碰见在主页要使用多个router-view来展现组件的状况,此时咱们须要给一些router-view提供name属性
//app.vue
<template>
<div id="app">
<router-link to="/app">app</router-link>
<router-link to="/login">login</router-link>
<router-view /> //内部不放内容能够写成空标签形式
<router-view name="a" />
</div>
</template>
复制代码
与此同时,咱们也要修改路由信息的JavaScript文件的一些内容
//routes.js
export default [
{
path: '/app/:id', //这里咱们就声明了一个路由上的参数
components:{ //注意由于要展现多个组件,因此咱们这里定义为components
default: App //在没有给name属性的router-view中展现的组件
a: Another //在name属性为a的router-view中展现
} ,
}
]
复制代码
当咱们触发一个导航时,全局前置守卫按照穿件的顺序调用,守卫是异步执行的。咱们能够经过守卫来进行一些拦截,好比只有登陆以后才能进入的一些页面或者使用的一些功能。
函数名 | 做用 |
---|---|
beforeEach | 通常在这个守卫方法中进行全局拦截,好比必须知足某种条件(用户登陆等)才能进入路由的状况 |
beforeResolve | 和beforeEach相似,区别是在导航被确认以前,同时在全部组件内守卫和异步路由组件被解析以后,解析守卫就被调用 |
afterEach | 在全部路由跳转结束的时候调用这些钩子不会接受 next 函数也不会改变导航自己 |
beforeEnter | 可直接定义在路由配置上,和beforeEach方法参数、用法相同,调用位置在beforeEach 和 beforeResolve |
大致的用法以下
//index.js
import createRouter from './config/router' //先导入咱们写的路由信息
const router = createRouter()
router.beforeEach((to, from, next) >= { //to -> 跳转的路由 from -> 当前的路由即跳转的起始点,next为这次跳转的函数,调用他才能执行跳转
if(若是没有登陆){
next('/login') //跳转到登陆页面
}else if(没有注册) {
next({path:'/register',replace:true}); //咱们也能够传递一个对象,replace设置为true就不会放在history的栈堆内
}
})
router.beforeResolve((to, from, next) >= {
//do something
next();
})
router.beforeEach((to, from) >= {
//do something
next();
})
复制代码
在路由上设置beforeEnter
//router.js
export default [
{
path: '/app',
component: Todo,
name: 'app', // 给当前的路由设置一个姓名,能够用来跳转,与路径和组件名无强制联系
meta: {
title: 'this is app', // 与html的meta一样的效果
description: 'author Reaper Lee'
},
beforeEnter (to,from,next) { //只有在进入路由以前调用
//dosomething
}
}
]
复制代码
函数名 | 做用 |
---|---|
beforeRouteEnter | 在渲染该组件的对应路由前调用,用法与参数和beforeEach相似, next须要被主动调用 ,此时实例并未被建立,不能使用this |
beforeRouteUpdate | 在当前路由改变,而且组件被复用时调用,此时实例已经建立,this能够访问实例,next须要被主动调用,不能传回调 |
beforeRouteLeave | 导航离开该组件的对应路由时调用。能够访问组件实例this,next须要被主动调用,不能传回调 |
//comp.vue
export default {
beforeRouteEnter (to, from, next) {
//在这里咱们由于没有实例,因此不能用this,但咱们要用获取的参数,就在next里使用回调函数
next( vm => {
//在这里能够拿到参数
})
},
beforeRouteUpdate (to,from, next){
next()
},
beforeRouteLeave (to, from, next){ //咱们能够经过下面的代码来实现退出时的提示确认
if(flobal.confirm('are you sure to leave?')){
next()
}
}
data() {
return {
}
}
}
复制代码
咱们路由若是有很是多,一次性经过webpack把所有打包进去会致使js文件变得异常的大,而且初次加载的时间会变得很是长,显然是不可取的。咱们可让对应不一样的路由只加载那一部分的组件的代码。
使用这部分功能咱们须要安装一个babel的插件
npm i babel-plugin-syntax-dynamic-import -D
以后在 .babelrc文件中咱们写入
"plugins": [ "syntax-dynamic-import" ] 复制代码
//routes.js
//注意咱们不在开头import组件
export default [
{
path: '/app',
component:() => { import('组件的路径')}, //注意要用一个函数
}
]
复制代码
VueX 是基于Vue框架的一个状态管理工具
官网的介绍是:
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的全部组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
npm install vuex -S
以后我么你在项目的文件夹里建一个新的文件夹为stroe,并在内部建立stroe.js,他将做为整个数据存储的入口
//store.js
import Vuex from 'vuex'
import Vue from 'vue'
Vue.use(Vuex)
export default () => {
return new Vuex.store({
state:{ //储存的对象
count: 0
},
mutations:{ //对state进行操做的方法
updateCount(state,num){ //第一个参数都为state,第二个参数为你能够传的参数
state.count = num;
}
}
})
}
复制代码
咱们须要在index.js引入Vuex
//index.js
import Vuex from 'vuex'
import createStore from './store/store'
const store = createStore()
new Vue({
router,
store,
render: (h) => h(App)
}).$mount(root)
复制代码
到这里以后咱们就已经把Vuex引入了
//app.vue
<script>
export default {
components:{
},
mounted () {
this.$router //咱们就能够经过this.$store拿到所需的数据
this.$store.commit('updateCount',参数) //咱们使用store的mutaitions时须要使用 commit方法,第一个参数
}
}
</script>
复制代码
咱们能够把state当作vue组件的data数据来使用
//state.js
export default {
}
复制代码
咱们也要在store里引入
//store.js
import defaultState from './state/state'
export default () => {
return new Vuex.Store({
state: defaultState,
mutations: {
updateCount(state,num){
state.count = num;
}
}
})
}
复制代码
咱们也能够把mutations也单独写个文件
//mutations.js
export default {
updateCount (state, num){
state.count = num;
}
}
//store.js
import Vuex from 'vuex'
import defaultState from './state/state'
import mutations from './mutations/mutations'
export default () => {
return new Vuex.Store({
state: defaultState,
mutations: mutations
})
}
复制代码
咱们能够把一些要直接在页面用的数据放在getters,而后能够直接方便使用
好比咱们在state.js里写入了咱们的名字信息
// state.js
export default {
count: 0,
firstName: 'Reaper',
lastName: 'Lee'
}
复制代码
咱们在getters里写入获取全名的方法
//getters.js
export default {
fullName (state) {
return `${state.firstName} ${state.lastName}`
}
}
复制代码
而后咱们能够经过Vuex提供的方法快速使用getters
//app.vue
<template>
<p>
{{fullName}}
</p>
</template>
<script>
export default {
computed: {
fullName () {
return this.$store.getters.fullName
}
}
}
</script>
复制代码
咱们通常把修改state值的一些方法放在mutation中,而后在组件中经过调用修改state
注意,mutation 只能传递两个参数,第一个是state对象,第二个是传参的对象,单个参数能够单独放入,若是要传递多个参数,则要放在一个对象中
其实咱们在组件中能够直接使用this.$store.state来进行修改,但这样不够规范,若是想防止这种状况就在实例化时将strict属性设置为true
export default () => { return new Vuex.Store({ strict:true }) } 复制代码
mutations只能同步操做,不能写入异步的代码,若是要执行异步操做,必需要写入actions中
例如咱们要根据传入的参数延时修改数据
//actions.js
export default {
updateCountAsync (store, data) {
setTimeout(() => {
store.commit('updateCount',data.num) //触发mutations的修改事件
}, data.time)
}
}
复制代码
咱们在vue文件中触发actions的方法与mutations有所不一样,触发mutation使用commit,触发action使用dispatch
//app.vue
export default {
...
mounted() {
this.$store.dispatch('updateCountAsync',{ num:5,time:2000})
}
}
复制代码
咱们有时调用store要存在多种场景,须要划分做用域,这时咱们就要使用到Vuex的模块
//store.js
export default () => {
return new Vuex.Store({
modules: {
a: {
namespaced: true, //使用这个在不一样的模块中可使用相同命名的mutations
state: {
text :1
},
mutations: {
updateText(state,text){
state.text = text;
}
},
getters: {
textPlus(state,getters,rootState){ //第二个参数是getter方法,第三个参数是全局state
return state.text + 1
}
},
actions:{
add({state,commit,rootState}){
commit('updateText',rootState.count,{root:true}) //使用{root:true} 就可让rootState为全局
}
}
},
b: {
text: 2
}
}
})
}
复制代码
在vue文件调用时
//app.vue
computed: {
textA() {
return this.$store.state.a.text //调用a模块的text值
},
textB() {
return this.$store.state.b.text //调用b模块的text值
}
}
复制代码
咱们在使用vuex时会发现,每当咱们修改vuex内的内容再保存时,vue不会热更替显示内容,而是会刷新一下,WTF,这么好用的功能难道Vuex用不了:horse:?
固然不是,咱们只须要在store.js加入部分代码便可
//store.js
import defaultState from './state/state'
import mutations from './mutations/mutations'
import getters from './getters/getters'
import actions from './actions/actions'
export default () => {
const store = new Vuex.Store({
state: defaultState,
mutations: mutations,
getters: getters,
actions: actions,
})
if (module.hot) {
module.hot.accept([
'./state/state',
'./mutations/mutations',
'./actions/actions',
'./getters/getters'
],() => {
const newState = require('./state/state').default,
const newMutations = require('./mutations/mutations').default
const newGetters = require('./getters/getters').default
const newActions = require('./actions/actions').default
store.hotUpdate({
state:newState,
mutations:newMutations,
actions:newActions,
getters:newGetters
})
})
}
return store
}
复制代码
一些更多的有关Vuex的API 能够查看
服务端渲染的优点:
但同时也要注意一些权衡之处: