Vue学习总结(Vue基础,VueCli3,VueRouter,Vuex)

Vue学习总结(Vue基础,VueCli3,VueRouter,Vuex)

目录

  • vue基础知识(1-13)
    • vue 引入,实例化
    • vue 数据 & 方法
    • vue 绑定(:)
    • vue 事件(@)
    • vue 事件修饰符(.once.prevent.stop等)
    • vue 按键修饰符(@keyup.alt.enter)
    • vue 数据双向绑定(ref,v-model)
    • vue 计算属性computed
    • vue 动态绑定css样式
    • vue v-if & v-show
    • vue v-for
    • vue 实例化多个Vue对象
    • vue 初识组件的应用
  • 运用脚手架及组件知识(14-21)
    • 脚手架初识
    • SRC文件
    • 组件嵌套
    • 组件CSS作用域
    • 属性传值Props(父组件向子组件传值)
    • 传值和传引用
    • 事件传值(子组件to父组件)
    • Vue生命周期(钩子函数)
  • vue路由知识点(22-32)
    • Vue 路由和HTTP
    • Vue 只用 Bootstrap4 中的样式
    • 路由跳转
    • 路由小细节(redirect和tag)
    • 路由name属性及跳转方法
    • 路由嵌套
    • 导航守卫(全局守卫)
    • 导航守卫(路由独享-组件内守卫)
    • 复用router-view
    • 路由控制滚动行为
    • 跨域
  • vue-cli3新特性(33-37)
    • 项目搭建及介绍
    • 新出的添加插件方法
    • 全局环境变量的使用
    • 独立运行.vue文件
    • 图形页面构建项目
  • vuex基础知识(38-43)
    • State
    • Getter
    • Mutation
    • Action
    • mapMutations & mapActions
    • Module

basics

1.vue引入,实例化

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
let vue-app = new Vue({
  ...
})

2.vue数据 & 方法

// 数据
data(){
  data1:'xxx'
},
// 方法
methods: {
  methodName(){
    return this.data1;
  }
}
<button @click='methodName'>点击</button>
<!-- 或者 -->
<div>{{ methodName() }}</div>

方法中用data中的属性,直接使用this.*,不用this.data.*

3.vue绑定(v-bind:, :, v-html:)

(1)属性绑定(用 v-bind:: )

website: 'https://github.com/'
<a v-bind:href="website">websit</a>
<!-- 或者简写 -->
<a :href="website">websit</a>

(2)标签绑定(用v-html:)

websiteTag: "<a href='https://github.com/'>websit</a>"
<!-- 正确 -->
<p v-html="websiteTag">websit</a>
<!-- 错误 -->
{{ websiteTag }}
<!-- 显示如下 -->
<!-- <a href='https://github.com/'>websit</a> -->

4.vue事件(用 v-on:@)

♥ 绑定事件里方法不传参可以不加括号仍然识别为方法,但在{{}}里一定要写括号才会识别为方法

eg: 传参单击双击事件

methods: {
  add: function(val){
    this.age += val;
  },
  dec: function(val){
    this.age -= val;
  },
}
<button v-on:click='add(1)'>加一岁</button>
<button @click='dec(1)'>减一岁</button>
<button v-on:dblclick='add(10)'>加十岁</button>
<button @dblclick='dec(10)'>减十岁</button>

5.vue事件修饰符(.once.prevent.stop等)

在事件处理程序中调用 event.preventDefault()event.stopPropagation() 是非常常见的需求。尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。

为了解决这个问题,Vue.js 为 v-on 提供了事件修饰符。之前提过,修饰符是由点开头的指令后缀来表示的。

  • .stop
  • .prevent
  • .capture
  • .self
  • .once
  • .passive
<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>

<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>

<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>

<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>

<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即元素自身触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>

<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>

♥ 使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent 只会阻止对元素自身的点击。

6.vue按键修饰符(@keyup.alt.enter)

在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为 v-on 在监听键盘事件时添加按键修饰符:

<!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
<input v-on:keyup.enter="submit">

你可以直接将 KeyboardEvent.key 暴露的任意有效按键名转换为 kebab-case 来作为修饰符。

<input v-on:keyup.page-down="onPageDown">

在上述示例中,处理函数只会在 $event.key 等于 PageDown 时被调用。

♥ 按键码 keyCode 的事件用法已经被废弃了并可能不会被最新的浏览器支持。

使用 keyCode 特性也是允许的:

<input v-on:keyup.13="submit">

为了在必要的情况下支持旧浏览器,Vue 提供了绝大多数常用的按键码的别名:

  • .enter
  • .tab
  • .delete (捕获“删除”和“退格”键)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

7.vue数据双向绑定(ref,v-model)

方法一

  <input ref='name' type="text" @keyup='logName'>
  this.name = this.$refs.name.value;

方法二

  <input v-model='age' type="text">

8.vue计算属性computed

methods 中的每个方法每次渲染dom都会执行 调用 {{xxx()}}

computed 中的每个方法只会在自己触发时执行 调用 {{xxx}},案例中拷贝的值与虚拟dom不同,就执行。

9.vue动态绑定css样式

<!-- active类名,isActive类值 -->
<div v-bind:class="{ active: isActive }"></div>

10.v-if & v-show

条件不成立时:v-if在dom中直接删除元素;v-show改变class为display:none

eg:

  <button @click='err=!err'>err</button>
  <button @click='success=!success'>success</button>
  <p v-if='err'>err</p>
  <p v-else-if='success'>200</p>
  <p v-show='err'>err</p>
  <p v-show='success'>200</p>

11.v-for

♥ 记得绑定key值

  data: {
    users:[
      {name:'hurry',age:20},
      {name:'luccy',age:25},
      {name:'zero',age:18},
    ]
  },
  <ul v-for='(item,index) in users' :key='index'>
    <li>{{index+1}} - {{item.name}} - {{item.age}}</li>
  </ul>
  <!-- 会多出3个div -->
  <div v-for='(item,index) in users' :key='index'>
    <h2>{{item.name}}</h2>
    <p>{{index+1}} - {{item.age}}</p>
  </div>
  <!-- 不会多出3个template -->
  <template v-for='(item,index) in users' :key='index'>
    <h2>{{item.name}}</h2>
    <p>{{index+1}} - {{item.age}}</p>
  </template>

12.实例化多个Vue对象

多个vue对象实例化

var one = new Vue({...})

var two = new Vue({...})

不同对象使用其他对象数据

one.data

eg:

var one = new Vue({
  el: '#vue-app-one',
  data: {
    title: 'one 的内容'
  },
  methods: {
    
  },
  computed: {
    greet:function(){
      return 'hello app one';
    }
  },
});

var two = new Vue({
  el: '#vue-app-two',
  data: {
    title: 'two 的内容'
  },
  methods: {
    changeTitle:function(){
      one.title = 'title one changed by app two!!!';
    }
  },
  computed: {
    greet:function(){
      return 'hello app one';
    }
  },
});

13.vue初识组件的应用

js中:

// greeting 是组件名,可在 #vue-app-one,#vue-app-two 中使用
Vue.component("greeting",{
  // 所有标签必须在一个大标签下
  template:`
  <div>
    <p> {{name}}:大家好,给大家介绍一下我的朋友@关晓彤</p>
    <button @click='changeName'>点我</button> 
  </div>
  `,
  // return一个对象则在组件内是私有的,不会暴露出去
  data:function(){
    return {
      name:'鹿晗'
    }
  },
  methods:{
    changeName:function(){
      this.name = this.name == '鹿晗'?'Hery':'鹿晗'
    }
  }
})

new Vue({
  el: '#vue-app-one'
});

new Vue({
  el: '#vue-app-two'
});

HTML中:

<greeting></greeting>

vue-cli

14.vue脚手架初识

部分特点

  • 脚手架是通过webpack搭建的开发环境
  • 使用es6语法
  • 打包和压缩js为一个文件
  • 项目在环境中编译,而不是浏览器
  • 实现页面自动刷新
  • ...

vue-cli的使用

  • 安装 nodejs ,一般选择安装LTS(长期稳定版)版本。官网:https://nodejs.org/en/
    # 在terminal、cmd、powershell 中
    # 输入 `node -v` 查看 node 版本号
    node -v
    
    # 输入 `npm -v` 查看 npm 版本号
    npm -v
    
  • 安装 cnpm
    npm install -g cnpm --registry=https://registry.npm.taobao.org
    
  • 安装 Vue CLI 3.x
    npm install -g @vue/cli
    # OR
    yarn global add @vue/cli
    
    # 输入 `vue --version` 查看 npm 版本号
    vue --version
    # OR
    vue -V
    
  • 创建一个 Vue 项目
    vue create projectName
    
    cd projectName
    
    npm run serve
    
    # 创建项目相关帮助
    vue create --help
    
  • 运行相关
    # Project setup
    npm install
    # Compiles and hot-reloads for development
    npm run serve
    # Compiles and minifies for production
    npm run build
    # Run your tests
    npm run test
    # Lints and fixes files
    npm run lint
    
  • (PS)旧版本 Vue CLI 2.x
    npm install -g @vue/cli-init
    # `vue init` 的运行效果将会跟 `vue-cli@2.x` 相同
    vue init webpack my-project
    

15.介绍脚手架搭建的项目中SRC文件流程及根组件App

client
│  .gitignore
│  babel.config.js
│  package.json
│  README.md
│
├─public
│    favicon.ico
│    index.html
│
└─src
    │  App.vue
    │  main.js
    │  router.js
    │
    ├─assets
    │      bg.jpg
    │
    └─components
           Component1.vue
           Component2.vue

index.html -> main.js -> App.vue ()

<!-- 模板 -->
<template></template>
<!-- 逻辑 -->
<script></script>
<!-- 样式 -->
<style></style>

16.组件嵌套

可以在main.js中注册全局组件

import Users from './component/Users'

Vue.component('users',Users);

也可以在某些组件中调用

<template>
  <div id="app">
    <Users></Users>
  </div>
</template>

<script>
import Users from './components/Users'
export default {
  components:{
    'Users':Users
  }
}
</script>

17.组件CSS作用域

<style scoped>
/* `scoped`该组件作用域内有效 */
/* 否则子组件相同选项样式会覆盖根组件的 */
</style>

18.属性传值Props(父组件向子组件传值)

父组件:

在调用子组件的位置,绑定自己的属性,第一个是子组件中的名称第二个是父组件中的名称

eg:

<Users :usersSon='users'></Users>

子组件:

子组件属性 props:['usersSon'], 接收传值。或者用标准写法

props:{
  users:{
    type:Array;
    requied:true;
  },
  position:{
    type:Array;
    requied:true;
  },
},

eg:

<template>
  <div class="users">
    <ul>
      <li v-for="(user,index) in usersSon" :key="index" @click="user.show = !user.show">
        <h2>{{user.name}}</h2>
        <h3 v-show="user.show">{{user.position}}</h3>
      </li>
    </ul>
  </div>
</template>

<script>
  export default {
    name:'users',
    props:['usersSon'],
  }
</script>

19.传值和传引用

传值:string number boolean,一处变,全部变

引用:array object,一处变,局部变

20.事件传值(子组件to父组件)

子组件

<h1 @click="tofather">{{title1}} {{title}}</h1>
<script>
export default {
  methods: {
    tofather: function(){
      this.$emit('changed','son to father') //第1个参数是事件名,第2个参数是传递的值
    }
  },
}
</script>

父组件

<Header @changed='update($event)' :title="title"></Header>
<!-- $event不能改 -->

<script>
export default {
  methods: {
    update:function(title){
      this.title = title;
    }
  },
}
</script>

21.Vue生命周期(钩子函数)

作用:可以找错误,可以解决需求

生命周期图示(红色为生命周期函数):

生命周期图示

// 8个钩子函数与 methods 并列。

// 创建对象之前(比如加载动画)
beforeCreate(){}

// 创建vue对象
new Vue()

// 组件创建成功,属性已经绑定,dom还未生成(比如获取数据,待会儿展示到dom,结束加载)
created(){}

// 检查 el 或者 new({...}).$mount('#app) ,都没有则生命周期结束

// 检查有没 template 或者 outerHTML ,都没有则生命周期结束

// 开始编译模板 template 里的内容,挂载前,虚拟dom中执行,看不到
beforeMount(){}

// el 中已经放入 template ,编译结束,此方法执行后,页面显示
mounted(){}

// 组件更新之前
beforeUpdate(){}

// 组件更新之后
updated(){}

// 组件销毁之前
beforeDestroy(){}

// 组件销毁之后
destroyed(){}

router

22.Vue路由和HTTP

(1) 安装路由模块及引入

npm install vue-router --save

router.js中

import Vue from 'vue'
import Router from 'vue-router'
import Home from './components/Home.vue'
import HelloWorld from './components/HelloWorld.vue'

Vue.use(Router);

export default new Router({
  mode: 'history', // 没有#符号
  base: process.env.BASE_URL,
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home
    },
    {
      path: '/helloworld',
      name: '',
      component: HelloWorld
    }
  ]
})

main.js中

import router from './router';

new Vue({
  router,
  ...
});

App.vue

    <ul>
      <li><a href="/">Home</a></li>
      <li><a href="/helloworld">Hello</a></li>
      <!-- 或者 -->
      <li><router-link to="/">Home</router-link></li>
      <li><router-link to="/helloworld">Hello</router-link></li>
    </ul>
    <router-view></router-view>

(2) HTTP

安装依赖:

npm i vue-resource --save

使用:

main.js中

import VueResource from 'vue-resource';
Vue.use(VueResource);

Home.vue中

  created(){
    this.$http.get('http://jsonplaceholder.typicode.com/users')
    .then((data)=>{
      // console.log(data);
      this.users = data.body;
    })
  },

23.vue中只用 Bootstrap4 中的样式

index.html中引入

<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">

24.路由跳转

router.js

import Vue from 'vue'
import Router from 'vue-router'
import Home from './components/Home'
import About from './components/about/About'

Vue.use(Router)

export default new Router({
  mode: 'history',
  base: process.env.BASE_URL,
  routes: [
    {path:'/',component:Home},
    {path:'/about',component:About},
  ]
})

Header.vue

<router-link to="/about"></router-link>

App.vue

<router-view></router-view>

25.路由小细节(redirect和tag)

Header.vue

<!-- 默认a标签 -->
<router-link to="/about"></router-link>

<!-- 修改为div标签 -->
<router-link tag='div' to="/about"></router-link>

<!-- 动态绑定属性路由 -->
<router-link tag='div' :to="router"></router-link>
<script>
  export default {
    data(){
      return{
        router:'/'
      }
    }
  }
</script>

router.js

export default new Router({
  mode: 'history',
  base: process.env.BASE_URL,
  routes: [
    {path:'/',component:Home},
    {path:'/about',component:About},
    {path:'*',redirect:'/'}, //错误输入重定向
  ]
})

26.路由name属性及跳转方法

name

{path:'/',name:'homelink',component:Home},
<!-- 注意这几个符号 : {} " '' " -->
<li><router-link :to="{name:'homelink'}" class="nav-link">主页</router-link></li>

跳转

  <button @click="goOlder" class='btn btn-success'>goOlder</button>
  <button @click="goMenu" class='btn btn-success'>goMenu</button>
  <button @click="goAdmin" class='btn btn-success'>goAdmin</button>

<script>
export default {
  methods:{
    goOlder(){
      this.$router.go(-1); // 到前一个页面
    },
    goMenu(){
      // this.$router.replace('/menu');  // replace到指定路由页面
      this.$router.push('/menu');  // push到指定路由页面
    },
    goAdmin(){
      // this.$router.replace({name:'adminLink'});  // 到指定 name 页面
      this.$router.push({name:'adminLink'});  // 到指定 name 页面
    },
  }
}
</script>

27.路由嵌套

router.js

    {path:'/about',name:'aboutLink',redirect:'/about/histoey',component:About,
    // 二级路由
    children:[
      {path:'/about/histoey',name:'historyLink',component:History},
      {path:'/about/contact',name:'contactLink',redirect:'/phone',component:Contact,children:[
        // 三级路由
        {path:'/phone',name:'phoneNum',component:Phone},
        {path:'/personname',name:'personName',component:Personname},
      ]},
      {path:'/about/orderingguide',name:'orderingGuideLink',component:OrderingGuide},
      {path:'/about/delivery',name:'deliveryLink',component:Delivery},
    ]},

about.vue

<!-- 导航的内容 -->
<router-view></router-view>

28.导航守卫(全局守卫)

学习地址(https://router.vuejs.org/zh/guide/advanced/navigation-guards.html)

main.js中

// 全局守卫
router.beforeEach((to,from,next) => {
  if(to.path == '/login' || to.path == '/register'){
    next()
  }else{
    alert("还没有登录,请先登录!");
    next('/login');
  }
})

29.导航守卫(路由独享-组件内守卫)

后置钩子(不常用)

router.afterEach((to,from) => {
  alert("after each")
})

路由独享的守卫

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})

组件内的守卫

  • beforeRouteEnter
  • beforeRouteUpdate (2.2 新增)
  • beforeRouteLeave
const Foo = {
  template: `...`,
  beforeRouteEnter (to, from, next) {
    // 在渲染该组件的对应路由被 confirm 前调用
    // 不!能!获取组件实例 `this`
    // 因为当守卫执行前,组件实例还没被创建
  },
  beforeRouteUpdate (to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 可以访问组件实例 `this`
  },
  beforeRouteLeave (to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 可以访问组件实例 `this`
  }
}

beforeRouteEnter 守卫 不能 访问 this,因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建。

不过,你可以通过传一个回调给 next来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数。

beforeRouteEnter (to, from, next) {
  next(vm => {
    // 通过 `vm` 访问组件实例
  })
}

注意 beforeRouteEnter 是支持给 next 传递回调的唯一守卫。对于 beforeRouteUpdate 和 beforeRouteLeave 来说,this 已经可用了,所以不支持传递回调,因为没有必要了。

beforeRouteUpdate (to, from, next) {
  // just use `this`
  this.name = to.params.name
  next()
}

这个离开守卫通常用来禁止用户在还未保存修改前突然离开。该导航可以通过 next(false) 来取消。

beforeRouteLeave (to, from , next) {
  const answer = window.confirm('Do you really want to leave? you have unsaved changes!')
  if (answer) {
    next()
  } else {
    next(false)
  }
}
beforeRouteLeave(to,from,next){
  if(confirm('确认离开吗?') == true){
    next()
  }else{
    next(false)
  }
}

30.复用router-view

router.js修改

{path:'/',name:'homeLink',component:Home,},

// 注意 components 的 s
{path:'/',name:'homeLink',components:{
  default:Home,
  'history':History,
  'orderingGuide':OrderingGuide,
  'delivery':Delivery
}},

App.vue添加

<div class="container">
  <div class="row">
    <div class="col-sm-12 col-md-4">
      <router-view name="history"></router-view>
    </div>
    <div class="col-sm-12 col-md-4">
      <router-view name="orderingGuide"></router-view>
    </div>
    <div class="col-sm-12 col-md-4">
      <router-view name="delivery"></router-view>
    </div>
  </div>
</div>

31.路由控制滚动行为

router.js中

const router = new VueRouter({
  routes: [...],
  scrollBehavior (to, from, savedPosition) {
    // return 期望滚动到哪个的位置
  }
})

eg:


  scrollBehavior (to, from, savedPosition) {
    // return {x:0,y:100};  // 滚动到(0,100)
    // return {selector:'.btn'}; // 滚动到 第一个.btn
    // 浏览器返回上一页面时,回到上次浏览的位置
    if(savedPosition){
      return savedPosition
    }else{
      return {x:0,y:0}
    }
  }

32.跨域

(0)预设

通过vue-cli3.x版本构建的项目使用proxy和以前的项目不同,而且3.x版本构建的时候可以选用typescript了。下面记录一下如何使用proxy跨域。
首先在根目录创建vue.config.js文件,这个配置文件在运行项目的时候自动加载。

// vue.config.js
module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'http://xxxx/device/', //对应自己的接口
        changeOrigin: true,
        ws: true,
        pathRewrite: {
          '^/api': ''
        }
      }
    }
  }
}

这个文件还可以配置其它信息,比如修改端口号,默认是8080等等。
最后在页面发送请求的时候:

axios.get('/api/getDataPoint').then(res => {
  console.log(res)
})

示例如下:

(1)预设

proxyTable:{
  ' /apis': {
      //测试环境
      target:'http://www.thenewstep.cn/', //接口域名
      change0rigin:true, //是否跨域
      pathRewrite: {
        '^/apis':'' //需要rewrite重写的,
      }
  }
},

(2)fetch

created(){
  // fetch
  fetch("/apis/test/testToken. php", {
    method:"post",
    headers: {
      "Content-type" :"application/json",
      "token" : "f4c902c9ae5a2a9d8f84868ad064e706"
    },
    body: JSON.stringify({username: "henry" , password :"321321"})
  })
  . then( result =>{
    // console. log( result)
    return result. json()
  })
  . then(data => {
    console. log ( data)
  })
}

(3)axios

main.js

import axios from 'axios'

axios.defaults.headers.common[ 'token '] = "f4c902c9ae5a2a9d8f84868ad064e706"
axios.defaults.headers.post ["Content-type"] = "application/j son"

Vue.prototype.$axios = axios

App.vue

this.$axios.post("/apis/test/testToken.php" , {username :"hello",password :"123456"})
  .then(data => {
    console. log(data)
  })

(4) 示例二加载美团外卖数据json

将包含 goods.json,ratings.json,seller.json 三个文件的 data 文件夹放到根目录下

还是vue.config.js文件

const goods = require(' ./data/goods.json');
const ratings = require(' ./data/ratings.json');
const seller = require(' ./data/seller.json');

module.exports = {
  //baseUrl: './', //根路径 //"baseUrl" option in vue.config.js is deprecated now, please use "publicPath" instead.
  publicPath: './', //根路径
  outputDir: 'dist2', //构建输出目录
  assetsDir: 'assets', //静态资源目录(js, css, img, fonts )
  lintOnSave: false, //是否开启eslint保存检测,有效值: true || false || ' error'

  devServer: {
    open: true, // 浏览器自动开启
    host: 'localhost', // 主机地址'127.0.0.0','0.0.0.0'也可以
    port: 8081, // 端口号
    https: false, // 是否启动https,启动会警告
    hot0nly: false, // 热更新,默认false
    proxy: {
      //配置跨域
      '/api': {
        target: 'http//localhost:5000/api/',
        ws: true,
        chang0rigin: true,
        pathRewrite: {
          '^/api': ''
        }
      }
    }
  },

  before(app) {
    // http: //loca lhost: 8081/api/goods
    app.get('/api/goods', (req, res) => {
      res. json(goods) ;
    });
    app.get( '/api/ratings', (req, res) => {
      res. json(ratings);
    });
    app.get( '/api/seller', (req, res) => {
      res. json(seller);
    });
  }

};

vuecli3

33.Vue-Cli3.0-项目搭建及介绍

找到脚手架的github仓库:https://github.com/vuejs/vue-cli

打开docs文件夹,拉到最后,按照步骤安装

Install:

npm install -g @vue/cli
# OR
yarn global add @vue/cli

Create a project:

vue create my-project
# OR
vue ui

Run a project

cd my-project
npm run serve

34.Vue-Cli3.0-新出的添加插件方法

  • 原来的插件安装方法
    npm install <plugin> --save
    
  • 新方法
    vue add <plugin>
    
    会有一些文件替换的插件(比如vuetify)会有提示,建议用该方法

35.Vue-Cli3.0-全局环境变量的使用

全局环境

根路径下创建.env文件,设置全局环境变量,比如:

VUE_APP_XXX = XXX

在需要的组件内

<script>
export default{
  data(){
    return{
      url: process.env.VUE_APP_XXX
    }
  }
}
</script>

.env数据变化要重新启动项目

开发环境

根路径下创建.env.development文件,设置开发环境变量,比如:

VUE_APP_XXX = XXX

npm run serve时用该文件的值。

生产环境

根路径下创建.env.production文件,设置开发环境变量,比如:

VUE_APP_XXX = XXX

npm run build时用该文件的值。

36.Vue-Cli3.0-独立运行.vue文件

npm install -g @vue/cli-service-global

vue serve XXX.vue

37.Vue-Cli3.0-图形页面构建项目

vue ui

打开GUI地址,进入图形页面,开始构建项目。

创建新项目:详情->预设->功能->配置

创建时 terminal 窗口会继续运行

创建好后gui界面会有:插件,依赖,配置,任务(serve,build,inspect) 4个菜单。

vuex

38.State(Vuex-搭建Vuex中央状态管理 & Vuex-使用computed获取store数据)

Vuex

Centralized State Management for Vue.js.

src 目录下新建 store 文件夹,下面新建 index.js 文件

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export const store = new Vuex.Store({
  state:{
    products:[
      {name:'马云',price:'200'},
      {name:'马化腾',price:'140'},
      {name:'马冬梅',price:'20'},
      {name:'马蓉',price:'10'},
    ]
  }
}) 

main.js 中引入

import {store} from './store'
new Vue({
  store,
  ...
}

组建中使用,computed 属性获取 store 中数据

<li v-for="product in products" :key='product'>
  <span class="name">{{product.name}}</span>
  <span class="price">${{product.price}}</span>
</li>

<script>
export default{
  computed: {
    products(){
      return this.$store.state.products
    }
  },
}
</script>

39.Getter

index.js 文件中,新增 getters 属性,里面放其他组件可以调用的方法

export const store = new Vuex.Store({
  state:{
    products:[
      {name:'马云',price:'200'},
      {name:'马化腾',price:'140'},
      {name:'马冬梅',price:'20'},
      {name:'马蓉',price:'10'},
    ]
  },
  getters:{
    saleProducts:(state)=>{
      var saleProducts = state.products.map(product =>{
        return{
          name: "**" + product.name + "**" ,
          price: product.price / 2
        }
      });
      return saleProducts;
    }
  }
}) 

组件对 store 中方法的调用

<li v-for="product in saleProducts" :key='product'>
  <span class="name">{{product.name}}</span>
  <span class="price">${{product.price}}</span>
</li>

<script>
export default{
  computed: {
    saleProducts(){
      return this.$store.getters.saleProducts;
    }
  },
}
</script>

40.Mutation

谷歌浏览器添加插件Vue.js devtools可以跟踪vuex状态

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数。

store/index.js 中添加 mutations 属性

  mutations:{
    reducePriceV:state=>{
      state.products.forEach(product =>{
        product.price -= 1;
      })
    }
  }

组建中调用方法 reducePriceV

<button @click="reducePrice">降价</button>
<script>
export default {
  methods: {
    reducePrice(){
      this.$store.commit('reducePriceM') // mutations中的方法
    }
  },
}
</script>

41.Action

Action 类似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作。(vuex调试器中方法和变化同时出来)

注册action

Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.statecontext.getters 来获取 state 和 getters。

组件触发action

Action 通过 store.dispatch 方法触发

接收第二个参数 payload

eg:

store/index.js 中添加 actions 属性

  actions:{
    reducePriceA:context=>{
      setTimeout(function(){
        context.commit('reducePriceM')
      },2000)
    }
  }

组建中调用方法 reducePriceM

<button @click="reducePrice">降价</button>
<script>
export default {
  methods: {
    reducePrice(){
      this.$store.dispatch('reducePriceA') // actions中的方法
    }
  },
}
</script>

42.Vuex-mapMutations & mapActions

在组件中提交 Mutation

你可以在组件中使用 this.$store.commit('xxx') 提交 mutation,或者使用 mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用(需要在根节点注入 store)。

import { mapMutations } from 'vuex'

export default {
  // ...
  methods: {
    ...mapMutations([
      'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`

      // `mapMutations` 也支持载荷:
      'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
    ]),
    ...mapMutations({
      add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
    })
  }
}

在组件中分发 Action

你在组件中使用 this.$store.dispatch('xxx') 分发 action,或者使用 mapActions 辅助函数将组件的 methods 映射为 store.dispatch 调用(需要先在根节点注入 store):

import { mapActions } from 'vuex'

export default {
  // ...
  methods: {
    ...mapActions([
      'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`

      // `mapActions` 也支持载荷:
      'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
    ]),
    ...mapActions({
      add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
    })
  }
}

43.Module

由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。

为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • Vue知识点的总结 Vue中的指令及其基本语法: 第一步:从官网上下载vue开发版本的js文件 引入js文件 ...
    往前走莫回头_2cd6阅读 1,422评论 0 1
  • ## 框架和库的区别?> 框架(framework):一套完整的软件设计架构和**解决方案**。> > 库(lib...
    Rui_bdad阅读 2,855评论 1 4
  • 基于Vue的一些资料 内容 UI组件 开发框架 实用库 服务端 辅助工具 应用实例 Demo示例 element★...
    尝了又尝阅读 1,119评论 0 1
  • vue-cli搭建项目 确保安装了node与npm 再目标文件夹下打开终端 执行cnpm i vue-cli -g...
    Akiko_秋子阅读 3,188评论 1 22
  • 键盘高度是不一样的所以不能写死 需要根据弹出的键盘动态获取 第一步 在需要的地方注册监听 第二步 实现监听的方法
    野生塔塔酱阅读 2,679评论 0 4