脚手架
-
Vue CLI
-
解决繁琐的webpack
-
依赖node环境
-
使用webpack模板
安装
npm install -g @vue/cli
npm install -g @vue/cli
-
拉取旧模板
-
npm install -g @vue/cli-init
-
创建项目
-
//2
vue init webpack my-project
//3
vue create my-project
-
project name
-
projecct description
-
author
-
//一般选择这项
Runtime + Compiler: recommended for most users
//后者小 效率高 推荐
> Runtime-only: about 6KB lighter min+gzip, but templates (or any Vue-specific HTML) are ONLY allowed in .vue files - render functions are required elsewhere -
vue-router
-
Use ESLint to lint your code?// ESLint js代码限制(规范)
-
//规范选择
Standard (https://github.com/standard/standard) //标准规范 选择
Airbnb (https://github.com/airbnb/javascript) //
none (configure it yourself) -
Set up unit tests (Y/n) 单元测试 一般不用
-
Setup e2e tests with Nightwatch? (Y/n) end to end (端到端测试) 依赖Nightwatch 结合selenlum 进行自动化测试 (自动测试操作) 一般给测试
-
? Should we run
npm install
for you after the project has been created? (recommended) (Use arrow keys)//管理项目使用什么 -
创建
node支撑环境
-
node提供一个服务器 是的js代码能在本地服务器上直接运行,而不用跑在浏览器上
-
node的V8引擎
-
chrome的V8引擎
-
使得js从原始的js-->字节码-->浏览器
-
变为 js --> 二进制码-->浏览器 效率更高
-
文件解析
-
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
re 即remove 清空原来的dist里的文件 在进行打包 -
相关配置文件夹
-
build
-
config
-
-
一些规范
-
.editorconfig
-
-
忽略js的限制
-
.eslintignore
-
-
css的转化0配置
-
.postcssrc.js
-
-
模板
-
index.html
-
关掉esLint
-
config/index.js
-
useEslint: false,
runtime+compiler和runtimeonly的区别
-
区别只在main.js
-
runtime+compiler App组件先注册
-
在使用App
-
步骤
-
template -> ast(抽象语法树) -> render -> virtual dom(虚拟DOM) -> 真实DOM(UI)
-
使用v1 代使用量多
-
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
components: { App },
template: '<App/>'
})
-
runtimeonly 没有注册
-
使用render 使用箭头函数
-
参数h 是createElement
-
render: function(createElement){ return createElement('h2',{class:'box'},['hello world']) }
生成
<div class="box">hello world</div>
替换
<div id="app"></div>render: function(createElement){
return createElement('h2',{class:'box'},['hello world',createElement('button',['按钮']])
}
生成
<div class="box">
hello world
<button>按钮</button>
</div>//可以传入主键
createElement(Cpn);
import Vue from 'vue' import App from './App'Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
render: h => h(App)
})
-
步骤 性能更高
-
render -> virtual dom(虚拟DOM) -> 真实DOM(UI)
-
使用v2 代码使用量少 少6kb就是这么来的
-
那么.vue的template是怎么处理的呢 怎么变为render函数
-
vue-loader用于加载.vue文件
-
vue-template-compler
用于解析.vue文件里的template-->render函数 开发时依赖 -
所以运行时不需要runtime+compiler 因为开发时已经解析过了
vue-cli 3 与 2版本的区别
-
3 是基于webpack 4 打造的, 2 是webpack3
-
3 的设计原则是
0 配置
移除的配置文件根目录下的, build和config等目录 -
3 提供vue ui命令 提供可视化配置, 更加人性化
-
移除 static文件夹 新增public文件夹,并且index.html移动到public中
vue create vuetestcli3
-
preset配置
-
default 默认
-
Manually 手动
-
-
空格选择取消
-
Babel Es6 -> Es5
-
TypeScript
-
Progressive Web App (PWA) Support 更新的App
-
Router
-
Vuex
-
CSS Pre-Processors
-
Linter /Formatter
-
Unit Testing
-
E2E Testing
-
-
配置文件存放
-
in dedicated 单独配置
-
in package.json
-
-
是否保存为自定义的模板
-
创建
-
运行 npm run serve
-
main.js
-
import Vue from 'vue' import App from './App.vue'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
Vue.config.productionTip = false表示提示信息
.$mount('#app')
挂载和el:'#app'是一样的
-
启动配置服务器 vue ui
-
可以创建vue.config.js 配置自己的一些配置 名字是固定的
-
module.exports = {
}
或自动合并
路由
-
就是通过互联的网络把信息从源地址传输到目的地的活动
后端路由
-
后端渲染阶段
-
后端路由 后端处理URL和页面之间的映射关系
-
早期 服务器存的已经是渲染好的网页了
-
jsp/php
-
html+css
-
-
前后端分离阶段(前端渲染)
-
后端只提供数据, 提供API接口
-
前端拿到html+css+js
-
前端ajax请求好数据通过js代码在浏览器中执行渲染网页
-
-
单页面富应用阶段
-
SPA
-
在前后端分离的基础上加上前端路由
-
整个网页只有一个html页面
-
请求的html+css+js只有一份
-
通过url网页抽取对应的相关东西
-
所以前端管理url->页面
-
改变url 页面不需要刷新
-
url的location.hash = "home"
-
html5里的history.pushState({},"","home"); //底层栈结构 先进后出
-
history.back();验证
-
-
html5里的history.replaceState({},"","home");//替换 就不能返回了
-
html5里的history.go();//跳的是栈 需要pushState()支撑
-
history.go(-1) -> history.back(); 等价
-
history.go(1) -> history.forward() 等价
-
数值可正可负
-
-
-
认识vue-router
-
路由插件
-
配置映射关系
-
安装 --save 运行时依赖
-
npm install vue-router --save
-
router文件夹
-
index.js 配置路由相关
-
import VueRouter from "vue-router"; import Vue from 'vue';
import Home from "../components/Home";
import About from "../components/About";//1.通过Vue.use(插件) , 安装插件
Vue.use(VueRouter);//2.创建VueRouter对象
const routes= [
{
path:'/home',
component:Home
},
{
path:'/about',
component:About
},
];const router = new VueRouter({
routes,
});//3.将router对象传入到Vue实例中
export default router; -
main.js
-
import Vue from 'vue' import App from './App.vue'
import router from "./router";
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App),
}).$mount('#app')
-
App.vue
-
<template> <div id="app"> //连接 <router-link to="/home">首页</router-link> <router-link to="/about">关于</router-link> //占位 <router-view></router-view> </div> </template>
<script>
export default {
name: 'App'
}
</script><style>
</style>
-
Home.vue
-
<template> <div> <h2>我是首页</h2> <p>我是首页内容, 哈哈哈</p> </div> </template>
<script>
export default {
name:"Home"
}
</script><style scoped>
</style>
-
About.vue
-
<template> <div> <h2>我是关于</h2> <p>我是关于内容, 呵呵呵</p> </div> </template>
<script>
export default {
name:"About"
}
</script><style scoped>
</style>
-
路由默认路径及HTML5 history模式
-
{ path:'', //重定向 redirect:"/home" },
-
HTML5的histroy模式
-
const router = new VueRouter({ routes, mode:'history', });
router-link补充
-
to
-
tag 渲染
-
<router-link to="/home" tag="button">首页</router-link> <router-link to="/about" tag="button">关于</router-link>
-
底层用的是pushState
-
怎么改成replaceState
-
<router-link to="/home" tag="button" replace>首页</router-link> <router-link to="/about" tag="button" replace>关于</router-link>
-
当前选择的路由有个classs
-
router-link-active
-
添加样式 改变按钮颜色
-
.router-link-active{ color:#00f; }
-
修改自己的class 不常用
-
<router-link to="/home" tag="button" replace active-class="active">首页</router-link> <router-link to="/about" tag="button" replace active-class="active">关于</router-link>
-
统一修改
-
const router = new VueRouter({ routes, mode:'history', linkActiveClass:'active', });
通过代码实现跳转
export default { name: 'App', methods:{ homeClick(){ // 通过代码方式跳转 this.$router.push("/home") //this.$router.replace("/home") }, aboutClick(){ // 通过代码方式跳转 this.$router.push("/about") //this.$router.replace("/about") }, } }
-
解决重复点击报错问题 抛异常
export default { name: 'App', methods:{ homeClick() { // 通过代码方式跳转 this.$router.replace("/home").catch(err => { }); }, aboutClick() { // 通过代码方式跳转 this.$router.replace("/about").catch(err => { }); }, } }
动态路由
-
/user/id
-
配置/user
{ path:'/user/:userId', component:User }, 使用v-bind 动态拼接
<router-link :to="'/user/'+userId">用户界面</router-link>
data(){
return {
userId:'lisi'
}
},//User.vue中
//$route拿到正在活跃的路由 注意不是$router<h2>{{$route.params.userId}}</h2>
路由的懒加载
-
打包时js文件会分离开
-
解决用户请求庞大的js文件 而出现短暂空白的情况
-
懒加载 路由对应的文件分块 用谁加载谁
-
//旧写法 const Home = resolve => { require.ensure(["./components/Home.vue"], ()=> {resolve(require("../components/Home.vue"))})};
//AMD写法
const About = resolve => require(['../components/About.vue'],resolve);//ES6写法 用到路由时动态加载
const Home = () => import('../components/Home.vue')// 路由懒加载
const Home = () => import('../components/Home.vue')
const About = () => import('../components/About.vue')
const User = () => import('../components/User.vue') -
主要是缩小庞大的js文件
路由的嵌套
-
创建对应的子组件, 并且在路由映射中配置对应的子路由
-
在组件内部使用
<router-view>
标签 -
<template> <div> <ul> <li>新闻1</li> <li>新闻2</li> <li>新闻3</li> <li>新闻4</li> </ul> </div> </template>
<script>
export default {
name:"HomeNews"
}
</script><style scoped>
</style>
<template>
<div>
<ul>
<li>消息1</li>
<li>消息2</li>
<li>消息3</li>
<li>消息4</li>
</ul>
</div>
</template><script>
export default {
name:"HomeMessage"
}
</script><style scoped>
</style>
import VueRouter from "vue-router"; import Vue from 'vue'; // 路由懒加载 动态导入 const Home = () => import('../components/Home.vue') const HomeNews = () => import('../components/HomeNews.vue') const HomeMessage = () => import('../components/HomeMessage.vue') const About = () => import('../components/About.vue') const User = () => import('../components/User.vue') //1.通过Vue.use(插件) , 安装插件 Vue.use(VueRouter); //2.创建VueRouter对象 const routes= [ { path:'', //重定向 redirect:"/home" }, { path:'/home', component:Home, children:[ {//这里不需要/news path:'news', component:HomeNews, }, { path:'message', component:HomeMessage, } ] }, { path:'/about', component:About }, { path:'/user/:userId', component:User }, ]; const router = new VueRouter({ routes, mode:'history', linkActiveClass:'active', }); //3.将router对象传入到Vue实例中 export default router;
<template> <div> <h2>我是首页</h2> <p>我是首页内容, 哈哈哈</p> <router-link to="/home/news">新闻</router-link> <router-link to="/home/message">消息</router-link> <router-view></router-view> </div> </template> <script> export default { name:"Home" } </script> <style scoped> </style>
-
重定向
-
import VueRouter from "vue-router"; import Vue from 'vue';
// 路由懒加载 动态导入
const Home = () => import('../components/Home.vue')
const HomeNews = () => import('../components/HomeNews.vue')
const HomeMessage = () => import('../components/HomeMessage.vue')
const About = () => import('../components/About.vue')
const User = () => import('../components/User.vue')//1.通过Vue.use(插件) , 安装插件
Vue.use(VueRouter);//2.创建VueRouter对象
const routes= [
{
path:'',
//重定向
redirect:"/home"
},
{
path:'/home',
component:Home,
children:[
{
path:'',
//重定向
redirect:"/home/news"
},
{
path:'news',
component:HomeNews,
},
{
path:'message',
component:HomeMessage,
}
]
},
{
path:'/about',
component:About
},
{
path:'/user/:userId',
component:User
},
];const router = new VueRouter({
routes,
mode:'history',
linkActiveClass:'active',
});//3.将router对象传入到Vue实例中
export default router;路由参数传递
-
params
-
//路由 { path:'/user/:userId', component:User },
//App.vue <router-link :to="'/user/'+userId">用户界面</router-link> //User.vue <h2>{{$route.params.userId}}</h2></pre>
-
query
-
//路由 { path:'/user', component:User },
//App.vue <router-link :to="{path:'/profile',query:{name:'nick',age:18,height:1.88}}" >档案</router-link> //浏览器 http://localhost:8080/profile?name=nick&age=18&height=1.88 //User.vue <h2>{{$route.query.name}}</h2></pre>
-
按钮形式
-
<button @click="userClick">用户</button> <button @click="profileClick">档案</button>
-
userClick() { // 通过代码方式跳转 this.$router.replace("/user/"+this.userId).catch(err => { }); }, profileClick() { // 通过代码方式跳转 this.$router.replace({ path:'/profile', query:{ name:"nick", age:18, height:1.88, } }).catch(err => { }); },
-
-
$router和$route的区别
-
$router 配置的整个路由
-
$route 当前处于活跃状态路由
-
<HomeNews></HomeNews>
等价于<Home-news></Home-news>
-
所有的组件都继承Vue类的原型
-
//在Vue的原上加上一个方法 , 所有组件都可以调用
Vue.prototype.test = function(){
console.log("test")
}//组件都可以调用
this.test(); -
所以原码中定义了的属性
导航守卫
-
监听路由跳转的过程
-
跳转的过程中修改页面title
-
生命周期(created,mounted,updated)或者导航守卫来做
-
前者繁琐需要每个添加所以不用
-
使用全局导航守卫
-
{ path:'/user/:userId', component:User, meta:{ title:"用户" }, },
-
//前置钩子 router.beforeEach((to,from,next)=>{
//从from跳转到to document.title = to.matched[0].meta.title; //必须调用 next();
})
-
import VueRouter from "vue-router"; import Vue from 'vue';
// 路由懒加载 动态导入
const Home = () => import('../components/Home.vue')
const HomeNews = () => import('../components/HomeNews.vue')
const HomeMessage = () => import('../components/HomeMessage.vue')
const About = () => import('../components/About.vue')
const User = () => import('../components/User.vue')
const Profile = () => import('../components/Proflie.vue')//1.通过Vue.use(插件) , 安装插件
Vue.use(VueRouter);//2.创建VueRouter对象
const routes= [
{
path:'',
//重定向
redirect:"/home"
},
{
path:'/home',
component:Home,
meta:{
title:"首页"
},
children:[
{
path:'',
//重定向
redirect:"/home/news"
},
{
path:'news',
component:HomeNews,
},
{
path:'message',
component:HomeMessage,
}
]
},
{
path:'/about',
component:About,
meta:{
title:"关于"
},
},
{
path:'/user/:userId',
component:User,
meta:{
title:"用户"
},
},
{
path:'/profile',
component:Profile,
meta:{
title:"档案"
},
},
];const router = new VueRouter({
routes,
mode:'history',
linkActiveClass:'active',
});//全局导航守卫
router.beforeEach((to,from,next)=>{//从from跳转到to document.title = to.matched[0].meta.title; //必须调用 next();//下一个 //其他用法等 next(false);//不跳转 next('/login')//跳转指定
})
//3.将router对象传入到Vue实例中
export default router; -
后置钩子(后置守卫)
-
//后置钩子 没有next router.afterEach((to,from)=>{
})
-
这两者称之为 路由全局守卫
-
还有
-
路由独享守卫
-
{ path:'/user/:userId', component:User, meta:{ title:"用户" }, beforeEnter:(to,from,next)=>{ next(); } },
-
组件内的守卫
-
export default {
name:"Home",
beforeRouteEnter (to, from, next){
},
beforeRouteUpdate (to, from, next){
},
beforeRouteLeave (to, from, next){
}
}
keep-alive
-
保留用户状态 而不是每次跳转都重新创建一个组件
-
keep-alive 是 Vue内置的一个组件, 可以使被包含的组件保留状态,或避免重新渲染
-
router-view也是一个组件 如果直接被包在keep-alive里面 所有路径匹配的视图组件都会被缓存
-
<keep-alive>
<router-view></router-view>
</keep-alive> -
keep-alive还涉及到两个函数
-
-
需求 排除某一项不需要缓存
-
include属性
-
exclude属性
-
//组件的name
//Profile,User中间不允许空格
<keep-alive exclude="Profile,User">
<router-view></router-view>
</keep-alive>
TabBar的封装实现
-
路径问题 起别名
-