Vue学习笔记

此学习笔记是看网易云课程的学习笔记。

Vue全套精品课 - 网易云课堂

#下载node,配置环境变量

#初始化一个vue项目
  npm install -g vue-cli  #安装 vue-cli
  vue init webpack test1  #初始化一个vue项目
  cd test1                #进入项目
  npm install             #安装依赖
  npm run dev             #运行项目

#项目目录结构
    index.html 项目根目录视图
    .postcssrc.js: postcss配置文件
    static: 静态文件目录

#模版语法
    Vue 组件
      包含三个部分:
        templete: 视图
        script: 逻辑
        style: 样式
    
    Mustache:模版
      表现语法: {{ 语法 }}  只能存在单行语句,并且不能作用在HTML属性
    
    Vue基本指令:
      v-html: 渲染文本
      v-text: 渲染文本
      v-bind: 绑定     简写: v-bind:title == :title
    

    条件渲染:
      v-if
      v-else
      v-else-if
      v-show
      v-if与v-show区别:
          v-if是"真正"的条件渲染,因为它会确保在切换过程中条件块内的事件监听器
        和子组件适当地被销毁和重建
          v-if 也是惰性的: 如果在初始渲染时条件为假,则什么也不做一直到条件第
        一次变为真时,才会开始渲染多件块。
          相比之下,v-show就简单得多,不管初始化条件是什么,元素总会被渲染,
        并且只是简单地基于css进行切换。
          一般来说,v-if有更高的切换开销,而v-show有更高的初始渲染开销。因此,
        如果需要非常频繁地切换,则使用v-show较好,如果在运行时条件很少改变,
        则使用v-if较好
    

    列表渲染:
      v-for:
        例子:
          names: ["lisa","qiqi","mali","deyi"]
          <ul>
                <li v-for="(name,index) in names">{{name}}--{{index}}</li>
              </ul>
    

    事件监听:
      v-on:    简写: v-on:click == @:click
      methods: 
      事件参数:
         可以加 $event参数,代表事件本身
         eg:
           <a @click="add">{{age}}</a>
        methods: {
            add: function(event) {
            this.age ++;
            console.log(event);
            }
        }

      修饰符:
         事件修饰符
         .stop     阻止冒泡
         .prevent  阻止默认方法
         .capture
         .self
         .once     事件只有一次
         .passive

         按键修饰符
         .enter
         .tab
         .delete (捕获“删除”和“退格”键)
         .esc
         ...


    数组更新检测:
       如果此数组总在了视图,使用下列方法触发数组,会对视图进行更新。
       push()
       pop()
       shift()
       unshift()
       splice()
       sort()
       reverse()
      eg:
              data () {
            return {
              names: ["lisa","qiqi","mali","deyi"]
            }
          },
          methods: {
            push: function () {
              this.names.push(["zhangsan"]);
            }
          <ul><li v-for="(name,index) in names" v-bind:key="index">{{name}}--{{index}}</li></ul>
          <a @click="push"> push ele</a>
      变异方法:上面方法,会引起视图更新
      替换数组:不会引起视图更新
    

    显示过滤/排序结果: filter
      for后面指定的是一个方法,方法中显式地使用了filter,对数组进行过滤并返回
         eg:
          <li v-for="n in evenNumbers">{{ n }}</li>

            data: {
          numbers: [ 1, 2, 3, 4, 5 ]
        },
        computed: {
          evenNumbers: function () {
            return this.numbers.filter(function (number) {
              return number % 2 === 0
            })
          }
        }

    计算属性和观察者
       computed
       计算属性和Methods区别:
            计算属性是基于它们的依赖进行缓存的。
        只在相关依赖发生改变时它们才会重新求值。
        这就意味着只要 message 还没有发生改变,
        多次访问 reversedMessage 计算属性会立即
        返回之前的计算结果,而不必再次执行函数。
    

    表单输入绑定: 双向数据绑定(用在表单输入)
      v-model
        eg:
           <input v-model="message">
               <p>Message is: {{ message }}</p>
      
      修饰符:
         .lazy    当输入完成后,在model中才显示
         .number  自动将Str -> number
         .trim    删除左右空额
        eg:
          <input v-model.lazy="message">
    

    绑定HTML Class
       v-bind:class
          eg:
            <div class="static" v-bind:class="{ active: isActive, 'text-danger': hasError }"></div>
        data: {
          isActive: true,
          hasError: false
        }
       v-bind:class="[activeClass, errorClass]"
       v-bind:class="[isActive ? activeClass : '', errorClass]"
       v-bind:class="[{ active: isActive }, errorClass]"   //与上面的相同


    绑定内联样式: v-bind:style 
      <div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
      data: {
        activeColor: 'red',
        fontSize: 30
      }


##单文件组件:  component
   1.三个部分组成
      1.Template
         只能存在一个根元素
      2.Script
      3.Style
         Scoped: 样式只在当前组件内生效 (npm)
   
   2.子父组件交互(通信)
      父 -> 子: props
         例子:静态数值
        Vue.component('blog-post', {
          // 在 JavaScript 中是 camelCase 的
          props: ['postTitle'],
          template: '<h3>{{ postTitle }}</h3>'
        })        
        <blog-post post-title="hello!"></blog-post>
      数组:
          props: ['title', 'likes', 'isPublished', 'commentIds', 'author']
      
      使用v-bind进行动态赋值:
         <blog-post v-bind:title="postTitle"></blog-post>
         data : {
           postTitle : 'this is  test!!';
         }

       Prop验证: 数据类型验证、多数据类型验证、必选项、默认值、obj,arr数据类型的默认值
        props: {
            // 基础的类型检查 (`null` 匹配任何类型)
            propA: Number,
            // 多个可能的类型
            propB: [String, Number],
            // 必填的字符串
            propC: {
              type: String,
              required: true
            },
            // 带有默认值的数字
            propD: {
              type: Number,
              default: 100
            },
            ,
            // 带有默认值的对象
            propE: {
              type: Object,
              // 对象或数组默认值必须从一个工厂函数获取
              default: function () {
            return { message: 'hello' }
              }
            },
            // 自定义验证函数
            propF: {
              validator: function (value) {
            // 这个值必须匹配下列字符串中的一个
            return ['success', 'warning', 'danger'].indexOf(value) !== -1
              }
            }
        }

      子 -> 父: emit Event
     


   3.插槽  父给子传组件,子父都可以渲染插槽内的组件
     eg:
      <slota> th is the parent</slota>   //父中用子组件,并在子组件中定义自定义内容
      <div class="slota">      //子组件定义 <slot>注解,父组件自定义内容在此显示
          this is the child
          <slot></slot>
      </div>

       具名插槽:当有多个插槽时,父类自定义内容需要传入不同的插槽内,就需要具名插槽
       <slota>    //父组件引用子组件
          <p slot="slot-a"> this is insert into slot-a</p>
          <p slot="slot-b"> this is insert into slot-b</p>
       </slota>

       <div class="slota">    //自定义子组件
          this is child
          <slot name="slot-a"></slot>
          ----------------------------
          <slot name="slot-b"></slot>
       </div>
    

    作用域插槽:子给父传递数据,展示效果由父来决定
        <p slot="slot-b" slot-scope="cope"> {{scope.text}}</p>   //父引用   //slot-scope从子组件获取数据
        <slot name="slot-b" text="儿子数据"></slot>              //自定义   //text定义子要传递给父的内容
    
    
    动态组件:keep-alive
        组件之间切换的时候,你有时会想保持这些组件的状态,以避免反复重渲染导致的性能问题,就需要使用到keep-alive
        当不是实时更新的的组件的话,可以使用缓存,像table动态获取,表单动态提交,就不能使用缓存
       
       <keep-alive>{{comp_view}}</keep-alive>
           <button @click="changeView">切换组件</button>

       import comp1 from './components/comp1';
       import comp2 from './components/comp2';
      export default {
        name: 'App',
        components: {
          comp1,
          comp2
        },
        data () {
          return {
            comp_view: "comp1"
          }
        },
        methods:{
          changeView() {
             if (this.comp_view == 'comp1'){
             this.comp_view = "comp2";
             }  else{
           this.comp_view = "comp1";
             }
          }
        }
      }


###css过度与动画      定义<transition> name属性,并将动画的进出的css名为:.name-enter{}
   在CSS过渡和动画中自动应用 class
        过渡类名:
       v-enter: 进入开始
       v-enter-active:执行过程中
       v-enter-to:结束动画
       v-leave:离开开始
       v-leave-active:执行过程中
       v-leave-to:结束动画
      eg:
          <button @click="show = !show">
        Toggle render
          </button>
          <transition name="slide-fade">
            <p v-if="show">hello</p>
          </transition>

          .slide-fade-enter, .slide-fade-leave-to
          {
             transform: translateX(10px);
          opacity: 0;
          }

   使用动画:  可以使用reverse,进行将动画反向操作
       <transition name="bounce">
         <p v-if="show"> this is the xichuan test</p>
       </transition>
    .bounce-leave-active{
      animation:bounce-in 3s ease reverse ;
    }
    @keyframes bounce-in {
      0% {
        transform: scale(0);
      }
      50% {
        transform: scale(1.5);
      }
      100% {
        transform: scale(1);
      }
    }

   自定义过渡的类名 : 使用第三方库: animate.css
      <link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
      <transition name="xichuan" enter-active-class="animated flipX" leave-active-class="animated flipY">
         <p v-if="show">this is the xichuan test two!!!!!!</p>
      </transition>


###自定义指令  directive
   全局指令:
    <input v-focus>

    Vue.directive('focus', {
      // 当被绑定的元素插入到 DOM 中时……
      inserted: function (el) {
        // 聚焦元素
        el.focus()
      }
    })
   局部指令:
    export default {
      name: 'App',
      data () {
        return {
          show : true
        }
      },
      directives: {
        focus: {
          // 指令的定义
          inserted: function (el) {
        el.focus()
          }
        }
      }
    }

   钩子函数: 钩子函数可以传多个参数(在官网;了解)
      bind:指令第一次绑定到元素时调用
      inserted:被绑定元素插入父节点时调用
      update: 
      componentUpdated:
      unbind:  指令与元素解绑时调用
     

### 过滤器  filter
   全局过滤:
    {{name | lowCase}}
    Vue.filter('lowCase', function (value) {
      return value.toLowerCase()
    })

    局部过滤:
    export default {
      name: 'App',
      data () {
        return {
          name : 'this is the tesT!'
        }
      },
      filters:{
        upCase : function (val) {
        return val.toUpperCase();
        }
      }

###Axios
  1.安装: npm install axios
  2.引用加载:
      import Axios from "axios"
      Vue.prototype.$axios = Axios
  3请求:
     GET请求:
    this.$axios.get('http://127.0.0.1/api/saying',{
       params:{
         ID: xichuan
       }
    })
    .then(function (response) {
        console.log(response.data);
    }).catch(function (error) {
        console.log(error);
    });
     
     POST请求:  url后面直接加参数
        form-data: ?name=xichuan&age=20
    x-www-urlencoded: {name:"xichuan",age:20}
        axios接收的post请求参数的格式是form-data格式

    import qs from "qs"

      axios.post('/user', qs.stringify({
        firstName: 'Fred',
        lastName: 'Flintstone'
      }))
      .then(function (response) {
        console.log(response);
      })
      .catch(function (error) {
        console.log(error);
      });
 
   4.全局设置参数:
    Axios.defaults.baseURL = 'http://127.0.0.1';
    Axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

    5.拦截请求
       import qs from 'qs'

    // 添加请求拦截器
    Axios.interceptors.request.use(function (config) {
        if(config.method == "post"){
          config.data == qs.stringify(config.data)
        }
        return config;
      }, function (error) {
        return Promise.reject(error);
      });

    // 添加响应拦截器
    Axios.interceptors.response.use(function (response) {
        // 对响应数据做点什么
        return response;
      }, function (error) {
        // 对响应错误做点什么
        return Promise.reject(error);
      });
    
    6.跨域问题


###Mock 数据模型
    1.自己创建JSON文件,使用get请求形式访问数据
       有点: 方便,快捷
       缺点:只能存在get请求
    2.项目中集成服务器,模拟各种接口
       优点:模拟真实线上环境
       缺点:增加开发成本
    3.直接使用线上数据
       优点;真实
       缺点:不一定每一个项目都存在
   
    1.安装与初始化
    npm install mockjs
    2.使用
       import Mock from "mockjs"
       Vue.prototype.Mock = Mock

    var data = this.Mock.mock({
          'list|1-10': [{
        'id|+1': 1
          }]
        });
    console.log(data)

####Router
    1.安装
      npm install vue-router
    2.引用:
      import VueRouter from 'vue-router'
      Vue.use(VueRouter)
    3.使用
    const router = new VueRouter({
      routes:[
        {path: "/",component: HelloWorld}
      ]
    })

    new Vue({
      el: '#app',
      router,
      components: { App },
      template: '<App/>'
    })

    4.视图
        <router-view/>

    5.跳转(导航)   相当于<a>标签,但最好不要使用<a>标签
        <router-link>

    <router-link to="/">Go to Foo</router-link>
 

    6.路由嵌套
    在父父中定义组件
    const router = new VueRouter({
      routes:[
        {path: "/",component: HelloWorld},
        {
          path:"/helloVue",
          component:HelloVue,
          children:[
        {path: "child1",component: Child1},   //这里的child1使用的是名称,并不是相对路径
        {path: "child2",component: Child2}
          ]
        }
      ]
    })

    在父父页面显示父组件
    <div id="app">
        <router-link to="/">hello1</router-link>
        <router-link to="/helloVue">hello2</router-link>
        <router-view/>
      </div>

    在父组件显示子组件
    <div class="helloVue">
        this is the test helloVue
        <router-link to="/helloVue/child1">chld1</router-link>    //这里to使用的是相对路径
        <router-link to="/helloVue/child2">child2</router-link>
        <router-view></router-view>
    </div>

    7.路由传递参数
       const router = new VueRouter({
    routes:[
       {name:"helloWorld",path: "/hello/:count",component: HelloWorld}   //传递参数,必须加上name这个字段,且参数名:count形式
    ]});
    
    <router-link :to="'/content/'+i.id"></router-link> //这个写法也可以
    <router-link :to="{name:'helloWorld',params:{count:200}}">hello1</router-link> //router-link中要改为  :to,且参数为json格式

    在子元素中展示数据:
    {{$route.params.count}}

    8.路由高亮效果
    1.在index.js 中, 添加 路由选中class名
    默认是 router-link-active, 更改
    const router = new VueRouter({
      mode: "history",    //
      linkActiveClass: "active",   //将router-link-active名字改为active
      routes:[
         {name:"helloWorld",path: "/hello/:count",component: HelloWorld}   //传递参数,必须加上name这个字段,且参数名:count形式
    ]});
      
    2.在全局中配置, css 样式
      .active {
        color: red
      }
    3.对于匹配 / 的, 会始终显示高亮, 需要添加 exact 属性; 
     <li><router-link :to="index" exact>首页</router-link></li>


###Element-UI 
    1.安装:
       npm i element-ui -S
    
    2.安装按需加载依赖
        npm install babel-plugin-component -D
    
    3.修改 .babelrc文件
    {
      "presets": [["es2015", { "modules": false }]],
      "plugins": [
        [
          "component",
          {
        "libraryName": "element-ui",
        "styleLibraryName": "theme-chalk"
          }
        ]
      ]
    }

  
### VueX
    Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。
      它采用集中式存储管理应用的所有组件的状态,
      并以相应的规则保证状态以一种可预测的方式发生变化
   
    1.什么时候使用Vuex?
    虽然 Vuex 可以帮助我们管理共享状态,
    但也附带了更多的概念和框架。这需要对短期和长期效益进行权衡。

    如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。
    确实是如此——如果您的应用够简单,您最好不要使用 Vuex。
    一个简单的 store 模式就足够您所需了。但是,如果您需要构建一个中大型单页应用,
    您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。
    
    2.Vuex状态管理
      View -> (dispatch) Action ->(Commit) Mutations ->(Mustate)Sate -> View
      注意:Action不是必需品,如果有异步操作才能用到Action,否则可以不使用
    
    3.Actions:  
      Action 提交的是mutation,而不是直接变更状态。
      Action 可以包含任意异步操作。    当前本地操作,使用Mutations,有异步操作使用Action

1.index.js

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

Vue.use(Vuex)

const store = new Vuex.Store({
  state:{          //定义公共变量的地方
    count: 5
  },
  // 更改store的状态
  mutations: {
    increment (state) {
      state.count++
    },
    decrement (state) {
      state.count--
    }
  },
  // 有异步的时候, 需要action
  actions: {
    increment(context) {
      context.commit('increment')
    },
    decrement (context) {
      setTimeout(function () {
        context.commit("decrement")
      }, 10)
    }
  },
  // 通过getter 进行数据获取
  getters: {
    getState(state) {
      return state.count > 0 ? state.count : 0;
    }
  }
})
export default store


2.在main方法中引用

import store from './index'
new Vue({
  el: '#app',
  store,
  components: { App },
  template: '<App/>'
})


3.引用
<div>
      获取值 --
      {{ getCount }} <br/>
      <button @click="add">inc</button>
      <button @click="des">decri</button>
    </div>
computed: {
    // 避免编程负数, 需要通过方法进行获取
    getCount() {
      // return this.$store.state.count
      return this.$store.getters.getState;
    }
  },
  methods: {
    add() {
      this.$store.commit("increment")
    },
    des() {
      // 使用 action中的异步方法
      this.$store.dispatch("decrement")
    }
  }


##iView  
    1.安装
       npm install iview --save
    2.按需引用·
       npm install babel-plugin-import --save-dev

    // .babelrc
    {
      "plugins": [["import", {
        "libraryName": "iview",
        "libraryDirectory": "src/components"
      }]]
    }
    
    //main.js

    import { Button, Table } from 'iview';
    Vue.component('Button', Button);
    Vue.component('Table', Table);

   github上有更多的笔记:Raray-chuan (兮川) · GitHub

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值