美文网首页前端开发前端周末
Vue学习总结(2019.7.31-8.4)

Vue学习总结(2019.7.31-8.4)

作者: Allenem | 来源:发表于2019-08-05 09:58 被阅读28次

    Vue学习总结

    目录

    • 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 的状态
    

    相关文章

      网友评论

        本文标题:Vue学习总结(2019.7.31-8.4)

        本文链接:https://www.haomeiwen.com/subject/ygjpdctx.html