Vue项目

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. 返回顶部按钮

  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>
    
  2. 组件的使用

    • 组件的滚动区域的标签上添加属性 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() // 继续执行后续的业务逻辑
  },

进入列表详情,返回还在原来的位置

  1. 先在router.js文件中开启keepAlive这个属性

    meta: {
        keepAlive: true
    }
    
  2. 在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>
    
  3. 在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
posted @ 2019-08-15 11:02  机智的小恐龙  阅读(460)  评论(0编辑  收藏  举报