Vue
安装Node.js
Node官网下载
安装vue:
npm install vue
安装webpack使用:
npm npm install webpack -g
安装vue-cli使用:
npm install vue-cli -g
新建基于webpack的vue-cli使用:
vue init webpack myProject(项目名称)
这里需要进行一些配置,默认回车
进入项目根目录,初始化项目使用:
cd myProject
npm install
运行项目使用:
npm run dev
vue目录介绍
- build:项目构建(webpack)相关代码
- config:配置目录,包括端口号等。我们初学可以使用默认的。
- src:这里是我们要开发的目录,基本上要做的事情都在这个目录里。里面包含了几个目录及文件:
- assets: 放置一些图片,如logo等。
- components: 目录里面放了一个组件文件,可以不用。
- App.vue: 项目入口文件,我们也可以直接将组件写这里,而不使用 components 目录。
- main.js: 项目的核心文件。
- static:
- test:初始测试目录
- .xxxx文件:这些是一些配置文件,包括语法配置,git配置等。
- index.html:首页入口文件,你可以添加一些 meta 信息或统计代码等。
- package.json:项目配置文件。
- README.md:项目的说明文档,markdown 格式
vue生命周期
什么是生命周期:从Vue实例创建、运行、到销毁期间,总是伴随着各种各样的事件,这些事件,统称为生命周期!
生命周期钩子 = 生命周期函数 = 生命周期事件
主要的生命周期函数分类:
- 创建期间的生命周期函数:
- beforeCreate:实例刚在内存中被创建出来,此时,还没有初始化好 data 和 methods 属性
- created:实例已经在内存中创建OK,此时 data 和 methods 已经创建OK,此时还没有开始 编译模板
- beforeMount:此时已经完成了模板的编译,但是还没有挂载到页面中
- mounted:此时,已经将编译好的模板,挂载到了页面指定的容器中显示
- 运行期间的生命周期函数:
- beforeUpdate:状态更新之前执行此函数, 此时 data 中的状态值是最新的,但是界面上显示的 数据还是旧的,因为此时还没有开始重新渲染DOM节点
- updated:实例更新完毕之后调用此函数,此时 data 中的状态值 和 界面上显示的数据,都已经完成了更新,界面已经被重新渲染好了!
- 销毁期间的生命周期函数:
- beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。
- destroyed:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
Vue-router的的安装使用
Vue.js 路由允许我们通过不同的 URL 访问不同的内容。
通过 Vue.js 可以实现多视图的单页Web应用(single page web application,SPA)。
Vue.js 路由需要载入 vue-router 库
npm 命令行安装vuevue-router:
- npm install vue-router
安装完成后,在main.js中引入vue-router
因为用的vue-cli所以不需要安装,直接生成router文件目录以及其中index.js
在main.js中是直接引用router文件
import router from './router'
new Vue({
el: '#app',
router,//此为简写,实际为router:router
components: { App },
template: '<App/>'
})
在router文件目录下的index.js中
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router),并且在vue对象属性中使用
const router = new Router({
//默认hash 模式,使用history,去掉路由前的#
mode: 'history',
routes: [
{
redirect: {name: 'childHome'}, // 重定向,使用name或者path方式{/home}
name: 'home', // 命名使用
path: '/home', // 路由路径使用
component: () => import('@/components/home'), // 按需加载方式
meta: {
title: '首页' // 可设置页面title
},
//children属性做路由嵌套,在home文件中设置router-view,父级页面重定向到这个子页面
children: [
name: 'childHome', // 命名使用
path: '/childHome', // 子页面path加 /为根路径,子页面path不加 / 为嵌套路径
component: () => import('@/components/home/childHome'), // 按需加载方式
meta: {
title: '嵌套页面'
}
]
}
]
})
export default router
Vue-router使用history模式,后台配合
要用这种模式,还需要后台配置支持。因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问 http://url/router ,就会返回 404,出现以上事故。
如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你下面项目依赖的页面。
目前我是使用tomcat,解决方法如下:
tomcat 目录下免得conf文件夹里面的web.xml文件加上下面的配置
<display-name>webapp</display-name>
<description>
webapp
</description>
<error-page>
<error-code>404</error-code>
<location>/</location>
</error-page>
Vue-router的beforeEach与afterEach钩子函数
在路由跳转的时候,我们需要一些权限判断或者其他操作。这个时候就需要使用路由的钩子函数。
定义:路由钩子主要是给使用者在路由发生变化时进行一些特殊的处理而定义的函数。
vue提供了三大类钩子:
- 全局钩子
- 某个路由的钩子
- 组件内钩子
两种函数: - Vue.beforeEach(function(to,form,next){}) /在跳转之前执行/
- Vue.afterEach(function(to,form)) /在跳转之后判断/
beforeEach函数有三个参数:
- to:router即将进入的路由对象
- from:当前导航即将离开的路由
- next:Function,进行管道中的一个钩子,如果执行完了,则导航的状态就是 confirmed (确认的);否则为false,终止导航。
afterEach函数不用传next()函数
全局钩子函数
router.beforeEach((to, from, next) => {
// 路由切换,加载动画开始
LoadingBar.start()
//pc端一般不改变title,移动端使用改变页面title
if (to.meta.title) {
document.title = to.meta.title
}
let token = localStorage.getItem('token')
if (!token) {
// token为空则跳转登录
next('/login')
} else {
return next()
}
return next()
})
router.afterEach((to, from) => {
// 加载动画停止
LoadingBar.finish()
})
router-link相关属性
- to
表示目标路由的链接。 当被点击后,内部会立刻把 to 的值传到 router.push(),所以这个值可以是一个字符串或者是描述目标位置的对象 - replace
设置 replace 属性的话,当点击时,会调用 router.replace() 而不是 router.push(),导航后不会留下 history 记录 - append
设置 append 属性后,则在当前 (相对) 路径前添加基路径。例如,我们从 /a 导航到一个相对路径 b,如果没有配置 append,则路径为 /b,如果配了,则为 /a/b - tag
有时候想要 router-link 渲染成某种标签,例如 li 。 于是我们使用 tag prop 类指定何种标签,同样它还是会监听点击,触发导航。
根据路由跳转添加class方式
在css设置.active.router-link-active {color: #358ee7;}
在 router-link 中添加class=”active”,则路由跳转到此页面时class生效
路由过渡动效
<router-link> 是基本的动态组件,所以我们可以用 <transition> 组件给它添加一些过渡效果:
<transition name="fade" mode="out-in">
<router-view/>
</transition>
CSS设置
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
}
.fade-enter, .fade-leave-to {
opacity: 0;
}
指令方法更改路由
router.push(location, onComplete?, onAbort?)
// 字符串
router.push(‘home’)
// 对象
router.push({ path: ‘home’ })
// 命名的路由
router.push({ name: ‘user’, params: { userId: ‘123’ }})
// 带查询参数,变成 /register?plan=private
router.push({ path: ‘register’, query: { plan: ‘private’ }})
注意:如果提供了 path,params 会被忽略,上述例子中的 query 并不属于这种情况。取而代之的是下面例子的做法,你需要提供路由的 name 或手写完整的带有参数的 path:
const userId = ‘123’
router.push({ name: ‘user’, params: { userId }}) // -> /user/123
router.push({ path: /user/${userId}
}) // -> /user/123
// 这里的 params 不生效
router.push({ path: ‘/user’, params: { userId }}) // -> /user
同样的规则也适用于 router-link 组件的 to 属性。
router.replace(location, onComplete?, onAbort?)
跟 router.push 很像,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录。
router.go(n)
// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)
// 后退一步记录,等同于 history.back()
router.go(-1)
// 前进 3 步记录
router.go(3)
// 如果 history 记录不够用,则失败
router.go(-100)
router.go(100)
Vuex核心概念
- state
- getters
- mutations
- actions
- modules
- 修改state的唯一方法是提交mutation,但是mutations中方法是同步的,actions可以提交mutations.
预渲染 prerender-spa-plugin
- SEO优化使用
- npm i prerender-spa-plugin -D
服务端渲染 SSR
- vue-server-renderer
- npm i vue-server-renderer -S
vue项目初次加载动画
首次加载太慢,进行感知优化,在入口的html文件里直接添加loading加载提示,让它在页面刚开始加载的时候默认显示,而隐藏主页面的root标签。
再在vue项目的入口vue里的created或mounted里将加载提示的标签删除或隐藏,再将主页面root标签显示。
入口HTML文件index.html:
<style type="text/css">
#appLoading { width: 100%; height: 100%; }
#appLoading img {
position: absolute;
top: 50%;
left: 50%;
width: 300px;
height: 300px;
-webkit-transform: translateY(-50%) translateX(-50%);
transform: translateY(-50%) translateX(-50%);
}
</style>
<body>
<div id="appLoading">
<img src="/static/img/loading.gif" alt="loading" />
</div>
<div id="app"></div>
</body>
入口vue文件App.vue:
<script>
export default {
name: 'app',
created () {
try {
document.body.removeChild(document.getElementById('appLoading'))
setTimeout(function () {
document.getElementById('app').style.display = 'block'
}, 500)
} catch (e) {
}
}
}
</script>