Vue项目:
vue全家桶
vue-cli + vue核心 + axios/featch+ vue-router + vuex(vue全家桶)
+webpack + es6 + scss的项目架构成为了越来越多大公司的第一选择。
Vue2大核心思想:组件化和数据驱动
组件化:把整个拆分为各个可以复用的个体
数据驱动:通过数据的变化直接影响bom展示 ,避免dom操作。
生成一个vue项目(可以选择formalprohect1111预设)
上传到git上时要写一个忽略文件,先删除里面的所有代码,然后赋值
.DS_Store
/node_modules即可
1.安装一个vue@cli的脚手架, cnpm install -g @vue/cli 电脑安装过一次就不用安装了
2.创建项目 vue create myapp(名字不能包含大写)
可以选择之前的预设,也可以自己重新设置(Manually select features)
如果是复制vue脚手架模板需要cnpm i 安装依赖 (注意电脑卡的话最好别在vscode里面安装依赖,可以直接在文件夹中安装)
3.更改package.json文件,加上一个dev : "npm run serve"
4.将src目录下的App.vue中的部分代码删了
5.书写
-
App.vue文件中写html结构
-
找到lib文件,赋值到src目录下
-
在App.vue文件中引入
-
如果需要引入小图标的话可以引入图标的scss库,public>index
-
<link rel="stylesheet" href="//at.alicdn.com/t/font_1211795_gfmrt26v3ws.css">
6.基本页面写好了,就开始抽离页面组件。
- 在view文件夹下创建一个home文件夹,在文件夹内创建一个index.vue文件
- 然后复制成4份,4个页面组件
7.找到router.js文件,配置路由
8.在app.vue页面中更改需要抽离的内容
<router-view></router-view>//跳转到指定模块
9.在common文件夹下创建一个common文件夹,新建一个Prolist.vue组件,
10.在home文件下,写入请求数据,请求到数据后
import Prolist from '@/components/common/Prolist'
引入子组件,并在components里面注册,注册完后将data中写入请求到的数据,并在
子组件中绑定数据,数据绑定成功后去子组件中接收数据,props:['prolist']接收数据
编程式导航和声明式导航
编程式跳转:用于在js中处理逻辑后需要页面进行跳转
vue的路由我们可以看做是一个数组,每次添加一个页面可以看成是向数组中push一个地址,当点击返回时就是向数组中的上一个值查找。
编程式跳转其实就是调用: this.$router.push( )
在li
标签中加入点击函数@click="goDetail(item.id)"
<!-- 编程式跳转 -->
<li class="proitem" v-for="(item, index) of prolist" @click="goDetail(item.id)" :key="index">
<div class="itemimg">
<img :src="item.images.small" :alt="item.alt" />
</div>
<div class="iteminfo">
<h3>{{ item.title }} --- {{ item.rating.average }}</h3>
<div class="directors">
导演:<span v-for="(itm, idx) of item.directors" :key="idx">{{ itm.name }}/</span>
</div>
<div class="casts">
演员: <span v-for="(itm, idx) of item.casts" :key="idx">{{ itm.name }}/</span>
</div>
<Rating :rating="(item.rating.average / 2).toFixed(1)"/>
</div>
</li>
在export default中的methods中加入
goDetail(id) {
//this.$router.push( '/detail/' + id ) //string类型的参数
//this.$router.push( { name: 'detail', params: { id } } ) //object类型参数
this.$router.push( { path: '/detail/' + id } ) //object类型
声明式导航:用于直接渲染到页面中,
声明式跳转中的to参数怎么写,编程式跳转中参数就怎么写
<router-link tag="li" :to="{ name: 'detail', params: { id: item.id } }" class="proitem" v-for="(item, index) of prolist" :key="index">
</router-link>
Vue调用vant-ui库api
vue引入vant ui库
1.安装依赖
cnpm / npm i vant -S
2.按需加载(推荐)
cnpm i babel-plugin-import -D
3.在babel.config.js文件下配置
4.在需要使用的文件内的script中引入
<script>
import Vue from 'vue'
import { Button } from 'vant'
Vue.use(Button)
export default {
}
</script>
5.编写样式即可
例如按钮
<van-button type="default">默认按钮</van-button>
<van-button type="primary">主要按钮</van-button>
1. 返回顶部按钮
-
先在
components
文件夹下创建一个Backtop.vue
写一个返回顶部按钮组件<template> <div class="backTop" v-show="vShow" @click="backtop"> <van-icon name="upgrade" size="40px"/> </div> </template>
<script> import Vue from 'vue' import { Icon } from 'vant' Vue.use(Icon) export default { props: ['vShow'], methods: { backtop () { const content = document.getElementById('content') content.scrollTop = 0 } } </script>
-
组件的使用
- 组件的滚动区域的标签上添加属性 id="content"
- 在script标签中引入
import Backtop from '@/components/Backtop'
- 在components中注册组件
Backtop
- 在滚动区域标签底部加上
<Backtop v-show="flag"/>
* 哪一个页面需要使用返回顶部 * 组件的滚动区域的标签上添加属性 id="content" * v-show代表的是返回顶部按钮 显示还是隐藏 * 在组件内部 mounted 的钩子函数内部,监听滚动条的变化 * data () { * return { * flag: false * } * } * mounted () { * const content = document.querySelector('#content') // 开启监听滚动条的滚动事件 content.addEventListener('scroll', this.scrollFn) * } 实现滚动的函数 methods: { scrollFn () { if (event.target.scrollTop > 150) { this.flag = true } else { this.flag = false } } } * * <div class="content" id="content"> * <Backtop v-show="flag"/> * </div>
路由守卫
1.全局的路由守卫
1.声明一个路由 const router = new Router{....}
,
2.调用这个路由的全局导航守卫
router.beforeEach((to, from, next) => {
//全局导航守卫,一般不推荐使用,但是后台管理系统中可以用
})
3.导出这个模块 export default router
export default 只能导出一个默认模块,这条main.js就能import导入这个路由了
例如:
const router = new Router({
......
})
// 全局导航守卫 ------- 一般不推荐使用 -------后台管理系统会用
router.beforeEach((to, from, next) => {
if (to.name === 'login' || to.name === 'register') { // 如果没有这一句会造成死循环,登录页面也是路由,造成内存溢出
next()
} else {
if (localStorage.getItem('isLogin') === 'ok') {
next()
} else {
next('/login')
}
}
})
export default router //export default 只能导出一个默认模块,这个模块可以匿名
2.路由独享的守卫
在需要进行判断是否登录的页面的路由定义中定义
{
path: '/cart', // 浏览器地址输入/cart时
name: 'cart', // 路由的名字
// component: () => import('./views/cart/index.vue')
components: {
default: () => import('./views/cart/index.vue'),
footer: Footer
},
// 路由独享守卫 ---本来就是一个路由的配置文件,写什么业务逻辑
beforeEnter (to, from, next) {
if (localStorage.getItem('isLogin') === 'ok') {
next()
} else {
next('/login') //注意这里不能加点,加点容易出bug,点表示当前目录下子文件跳转,比如user中也有一个login,我在user中点购物车,就进入了user/login,出现bug
}
}
},
3.组件级别的导航守卫
在需要导航守卫的页面中加入导航守卫即可
beforeRouteLeave (to, from, next) { // 在离开这个导航之前 ---导航守卫者
const content = document.getElementById('content')
content.removeEventListener('scroll', this.scrollFn)
let position = content.scrollTop
localStorage.setItem('position', position)
next() // 继续执行后续的业务逻辑
},
进入列表详情,返回还在原来的位置
-
先在router.js文件中开启keepAlive这个属性
meta: { keepAlive: true }
-
在App.vue中判断keepAlive是否为true
<keep-alive> <router-view v-if="$route.meta.keepAlive"></router-view> </keep-alive> <router-view v-if="!$route.meta.keepAlive"></router-view>
-
在home.vue中监听滚动条的位置
beforeRouteLeave (to, from, next) { // 在离开这个导航之前 ---导航守卫者 const content = document.getElementById('content') let position = content.scrollTop localStorage.setItem('position', position) next() // 继续执行后续的业务逻辑 }, watch: { $route (newVal, oldVal) { if (newVal.name === 'home') { const content = document.getElementById('content') content.scrollTop = localStorage.getItem('position') } } }
VueX状态管理器
1.先在store.js文件中布置好状态管理器
export default new Vuex.Store({
state: { // 需要管理的组件的状态
loginState: ''
},
mutations: { // 唯一改变状态的地方
changeLoginState (state, data) { // state代表的是初始化的数据
state.loginState = data
}
},
actions: {
}
})
2.获取状态管理器中的值 state
1.用变量直接接收获取的值
const { $store: { state: { loginState } } } = this
if (loginState === 'ok') {
console.log('加入购物车')
}
2.mapState辅助函数
import { mapState } from 'vuex' //引入模块
computed: { //计算属性
...mapState({
//loginState: (state) => { return state.loginState }
loginState: 'loginState'
})
},
if (this.loginState === 'ok') { // 直接使用
console.log('立即购买')
}
3.mapGetters (mapGeters相当于mapState的计算属性,能理解就用,不理解也可以不用。既然我们可以通过mapState拿到属性值,我们也可以直接在compute里面写计算属性,就不用、mapGetters了。)
第一种写法:
在store.js文件中
state: { // 需要管理的组件的状态
loginState: '',
list: [1, 2, 3, 4, 5, 6]
},
getters: { // 可以看做是state的计算属性,类似组件中的 data 与 compute
len (state) {
return state.list.length
}
},
在获取值页面直接获取
{{ this.$store.getters.len }}
第二种写法:
获取值
import { mapState, mapGetters } from 'vuex' //引入mapGetters模块
computed: {
...mapGetters({ // 获取值不能使用函数
len: 'len'
})
},
{{ len }} //直接使用
第三种写法:即不用mapGetter
computed: {
...mapState({
list: 'list' //通过mapState拿到属性值
}),
len () { // 计算属性
return this.list.length
}
3.提交至状态管理器中的值 mutations 改变数据的方式(必须是同步的函数,只干同步的事,改值)
**this.$store.commit() ** //提交数据方式
1.直接提交
this.$store.commit('changeLoginState', 'ok')
this.$store.commit('changeLoginState', {
result: 'ok' //提交一个对象
})
2.使用 ES6 风格的计算属性命名功能来使用一个常量作为函数名 //没啥实际意义就是感觉逼格不一样了
创建一个mutation-types.js文件
内容:export const CHANGE_LOGIN_STATE = 'changeLoginState' //定义一个函数名
在store.js中用常量代替函数名
[CHANGE_LOGIN_STATE] (state, data) {
state.loginState = data.result
}
在提交值页面引入
import { CHANGE_LOGIN_STATE } from '@/mutation-types'
提交代码:
this.$store.commit({
type: CHANGE_LOGIN_STATE,//函数名改为常量定义的名字。
result: 'ok'
})
注:如果自定义的常量函数名过多,我们可以换一种方法引入
import * as types from '@/mutation-types'
提交代码:
this.$store.commit({
type: types.CHANGE_LOGIN_STATE,//函数名改为常量定义的名字。
result: 'ok'
})
4. actions 异步操作
第一种方法:
1.在store.js页面中的actions添加回调函数
actions: { // 异步操作
getKindListData (context) { // 可以理解为this.$store,但不是this.$store
fetch('https://www.daxunxun.com/douban').then(res => res.json()).then(data => {
context.commit(types.CHANGE_KIND_LIST, {
result: data
})
})
}
}
})
2.在需要提交的页面中
mounted () { //组件内部通过dispatch触发store中的action
this.$store.dispatch('getKindListData')
}
第二种方法:利用mapActions辅助函数
import { mapState, mapActions } from 'vuex' //引入组件
methods: { //利用mapActions将事件复制到一个变量
...mapActions({
getKindListData: 'getKindListData' // 前者代表当前组件生成getKindListData自定义函数,后者代表状态管理器中的actions
})
},
mounted () { //组件内部直接调用这个函数
this.getKindListData()
}
混入mixin
1.创建文件夹mixins,创建文件mymixins
import Header from '@/components/common/Header'
export default {
components: {
Header
}
}
2.在需要引入的页面引入
import mymixins from '@/mixins/mymixins'
3.在export default 中声明,即可使用注册的模块
mixins: [mymixins],
自定义指令
1.全局自定义指令,在main.js中自定义
Vue.directive('focus', {
inserted: function (e) {
e.focus()
}
})
在需要使用的标签中,直接输入 v-focus
2.局部自定义指令,在需要使用的页面的export default中自定义
export default {
directives: {
'focus': {
inserted (e) {
e.focus()
}
}
},
在需要使用的标签中,直接输入 v-focus