• vue的详解


    vue一些基本语法

    1、初始化一个vue项目

    > cnpm install -g vue-cli # 全局安装vue-cli 
    > vue -V #检查vue版本
    > vue init webpack vue-project #初始化一个vue项目
    > cnpm install #进入项目目录 安装需要的依赖
    > cnpm run dev #启动项目
    > npm config set registry https://registry.npm.taobao.org
    > npm config get registry
    • 父组件

      <Todo
       :message="我是父数据传给子组件"  #可以通过:message="父传子的数据"
       v-for="(item) in groceryList"
       v-bind:todo="item"  #可以通过v-bind 将数据传给子组件 todo是子组件的props
       v-bind:key="item.id"
      ></Todo>
      <script>
      import Todo from '@/components/Todo' #引入子组件
      export default {
       name: 'HelloWorld',
       data () {
       
      },
       components: {
         Todo #组件见
      }
      }  
      </script>
    • 子组件

      <template>
       <div class="hello">
        我是子组件
         <li>{{ todo.text }}</li>
       </div>
      </template>
      <script>
      export default {
       name: 'Todo',
       props: ['todo'] #父组件要一致
      }
      </script>
      • 子组件 子组件拥有自己的生命周期

        <template>
         <div class="hello">
          我是子组件
           <li @click="emitToparent">点击我传数据给父组件</li>
         </div>
        </template>

        <script>
        export default {
         name: 'Todo',
         methods: {
           emitToparent () {
             this.$emit('child-event', '我是子组件传数据给父组件')  #child-event是父组件绑定标示
          }
        }
        }
        </script>
      • 父组件

        <template>
         <div class="hello">
           <Todo
             @child-event="parentEvent"
           ></Todo>
         </div>
        </template>
        <script>
        import Todo from '@/components/Todo'
        export default {
         name: 'HelloWorld',
         data () {
           return {
          }
        },
         components: {
           Todo
        },
         methods: {
           parentEvent (data) {
             console.log('接入数据', data)
          }
        }
        }
        </script>
        - v-if   绑定判断关系 eg:<p v-if="seen">现在你看到我了</p>
        - v-bind 绑定html标签属性 eg:<a v-bind:href="url">...</a>
        - v-on 绑定on事件 eg:<a v-on:click="doSomething">...</a>
        - <a v-bind:[attributeName]="url"> ... </a> 动态绑定参数 data属性需有attributeName 其值为 "href",那么这个绑定将等价于 v-bind:href
        <input type="text" v-model.lazy="value"> #lazy这个修饰符会在光标离开input框才会更新数据
        <input type="text" v-model.trim="value"> #trim是输入框过滤首尾的空格
        <input type="text" v-model.number="value"> #number的功能是先输入数字就会限制输入只能是数字
        <button @click.stop="test">test</button> #stop是阻止事件冒泡
        <a @click.prevent="test">test</a> #prevent 阻止默认行为,相当于调用了event.preventDefault()方法,比如表单的提交、a标签的跳转就是默认事件
        <div @click.self="test"></div> #self 只有元素本身触发时才触发方法,就是只有点击元素本身才会触发
        <div @click.once="test"></div> #once 只能用一次,无论点击几次,执行一次之后都不会再执行
        - v-bind 缩写
        <!-- 完整语法 -->
        <a v-bind:href="url">...</a>
        <!-- 缩写 -->
        <a :href="url">...</a>
        - v-on 缩写
        <!-- 完整语法 -->
        <a v-on:click="doSomething">...</a>
        <!-- 缩写 -->
        <a @click="doSomething">...</a>
        <div id="example">
         <p>Original message: "{{ message }}"</p>
         <p>Computed reversed message: "{{ reversedMessage }}"</p>
        </div>
        var vm = new Vue({
        el: '#example',
        data: {
          message: 'Hello'
        },
        computed: {
          // 计算属性的 getter
          reversedMessage: function () {
            // `this` 指向 vm 实例
            return this.message.split('').reverse().join('')
          }
        }
        })
        new Vue({
         data: {
           n: 0,
           obj: {
             a: "a"
          }
        },
         template: `
           <div>
             <button @click="n += 1">n+1</button>
             <button @click="obj.a += 'hi'">obj.a + 'hi'</button>
             <button @click="obj = {a:'a'}">obj = 新对象</button>
           </div>
         `,
         watch: {
           n() {
             console.log("n 变了");
          },
           obj:{
             handler: function (val, oldVal) {
             console.log("obj 变了")
          },
             deep: true // 该属性设定在任何被侦听的对象的 property 改变时都要执行 handler 的回调,不论其被嵌套多深
          },
           "obj.a":{
             handler: function (val, oldVal) {
             console.log("obj.a 变了")
          },
             immediate: true // 该属性设定该回调将会在侦听开始之后被立即调用
          }
        }
        }).$mount("#app");
        • deep 控制是否要看这个对象里面的属性变化

        • immediate 控制是否在第一次渲染是执行这个函数

          vm.$watch() 的用法和 watch 回调类似

          • vm.$watch('data属性名', fn, {deep: .., immediate: ..})

          vm.$watch("n", function(val, newVal){
              console.log("n 变了");
          },{deep: true, immediate: true})
          vue.esm.js?efeb:628 [Vue warn]: Error in callback for watcher "fullName": "TypeError: Cannot read property 'call' of undefined"
          <div v-bind:class="[{ active: isActive }, errorClass]"></div>
          <my-component v-bind:class="{ active: isActive }"></my-component>
          <h1 v-show="ok">Hello!</h1>
          <ul id="example-1">
               <li v-for="(item,i) in items" :key="i"> #其中in可以使用of代替
                {{ item.message }}
               </li>
          </ul>
          <div v-for="(value, name, index) in object">
          {{ index }}. {{ name }}: {{ value }}
          </div>
          <li v-for="n in even(numbers)">{{ n }}</li>
          <div id="example-2">
           <!-- `greet` 是在下面定义的方法名 -->
           <button v-on:click="greet">Greet</button> #也可以传递数据 v-on:click="greet('abc',$event)"
          </div>
          methods: {
            greet: function (event) {
              // `this` 在方法里指向当前 Vue 实例
              alert('Hello ' + this.name + '!')
              // `event` 是原生 DOM 事件
              if (event) {
                alert(event.target.tagName) #得到原生事件
              }
            }
          }
          computed: {
          fullName: {
            // getter
            get: function () {
              return this.firstName + ' ' + this.lastName
            },
            // setter
            set: function (newValue) {
              var names = newValue.split(' ')
              this.firstName = names[0]
              this.lastName = names[names.length - 1]
            }
          }
          }
          <input v-on:keyup.enter="submit"> #按键修饰符
          <input v-on:keyup.13="submit"> #按键码
          <input v-on:keyup.k="submit" #k键
          <input v-model="message" placeholder="edit me">
          <p>Message is: {{ message }}</p>
          <!-- 在“change”时而非“input”时更新 -->
          <input v-model.lazy="msg" >  
          输入值转为数值类型
          <input v-model.number="age" type="number">
          如果要自动过滤用户输入的首尾空白字符
          <input v-model.trim="msg">
          <h3>{{ title }}</h3>
          <div v-html="content"></div> 这样会报错的 # every component must have a single root element
          正确 eg:
          <div class="blog-post">
           <h3>{{ title }}</h3>
           <div v-html="content"></div>
          </div>
          <div :style="{fontSize: postFontSize + 'em'}"></div> #在绑定的样式中要使用大小写
          <blog-post
                 v-for="post in posts"
                 v-bind:key="post.id"
                 v-bind:post="post"
                 v-on:enlarge-text="postFontSize += 1"
               ></blog-post>
          <input v-model="searchText"> 
          这里雷同于:
          <div id="app">
             <custom-input :value="searchText" @input="searchText = $event"></custom-input>
          </div>

          <template>
           <div>
             <input :value="value" @input="$emit('input', $event.target.value)"/>
           </div>
          </template>
          <script>
          export default {
           name: 'BlogPost',
           props: ['post', 'value'],
           data () {
             return {
               seen: true,
               obj: {
                 content: '这个是子组件'
              }
            }
          }
          }
          </script>
          Vue.component('my-component-name', { /* ... */ })
          Vue.component('MyComponentName', { /* ... */ })
          Vue.component('component-a', { /* ... */ })
          Vue.component('component-b', { /* ... */ })
          Vue.component('component-c', { /* ... */ })
          new Vue({ el: '#app' })
          <div id="app">
           <component-a></component-a>
           <component-b><component-a></component-a></component-b>
           <component-c></component-c>
          </div>
          #笔者经过测试 只能后加载能使用前面加载的 比如在a使用b组件会报错的,应该是顺序加载的原因吧
          props: {
          title: String,
          likes: Number,
          isPublished: Boolean,
          commentIds: Array,
          author: Object,
          callback: Function,
          contactsPromise: Promise // or any other constructor
          }
          父组件
          <base-checkbox :checked="lovingVue"  @change="lovingVueFunc" ></base-checkbox> #checked接收是一个bool值的变量,change接收是一个影响lovingVue的方法,
          子组件
          Vue.component('base-checkbox', {
          model: {
            prop: 'checked',
            event: 'change'
          },
          props: {
            checked: Boolean
          },
          template: `
             <input
               type="checkbox"
               v-bind:checked="checked"
               v-on:change="$emit('change', $event.target.checked)"
             >
          `
          })
          [Vue warn]: Error in v-on handler: "TypeError: handler.apply is not a function
          eg:
          this.checked = this.checked === false ? true : false; #报错Unnecessary use of boolean literals in conditional expression
          应该替代为:
          this.checked = !this.cheked
           12% building modules 22/31 modules 9 active ...pace/vue_demo/Vue-Project/src/App.vue{ parser: "babylon" } is deprecated; we now treat it as { parser: "babel" }.
          95% emitting
          > 这个是因为 prettier版本有问题导致的 更换版本即可
          > 在当前项目中直接cnpm install prettier@~1.12.0 -D 或者cnpm install prettier@~1.12.0 --save-dev 然后重新npm run dev
          <template>
           <div id="example">
             <button @click="decrement">-</button>
             {{count}}
             {{dataCount}}
             <button @click="increment">+</button>
             <div>{{sex}}</div>
             <div>{{from}}</div>
             <div>{{myCmpted}}</div>
           </div>
          </template>
          <script>
          import { mapState } from 'vuex'
          export default {
           data () {
             return {
               str: '国籍',
               dataCount: this.$store.state.count
            }
          },
           computed: mapState({
             count: 'count', // 第一种写法
             sex: (state) => state.sex, // 第二种写法
             from: function (state) { // 用普通函数this指向vue实例,要注意
               return this.str + ':' + state.from
            },
             // 注意下面的写法看起来和上面相同,事实上箭头函数的this指针并没有指向vue实例,因此不要滥用箭头函数
             // from: (state) => this.str + ':' + state.from
             myCmpted: function () {
               // 这里不需要state,测试一下computed的原有用法
               return '测试' + this.str
            }
          }),
           methods: {
             increment () {
               this.$store.commit('increment')
            },
             decrement () {
               this.$store.commit('decrement')
            }
          },
           created () {
             // 写个定时器,发现computed依旧保持了只要内部有相关属性发生改变不管是当前实例data中的改变,还是vuex中的值改变都会触发dom和值更新
             setTimeout(() => {
               this.str = '国家'
            }, 1000)
          }
          }
           computed也可以写
           computed: mapState([
             // 映射 this.count 为 store.state.count
             'count'
          ])
          </script>
          const store = new Vuex.Store({
          state: {
            todos: [
              { id: 1, text: '...', done: true },
              { id: 2, text: '...', done: false }
            ]
          },
          getters: {
            doneTodos: state => {
              return state.todos.filter(todo => todo.done)
            }
          }
          })
          其他组件可以使用:
          store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]
          mapGetters 辅助函数
          import { mapGetters } from 'vuex'
          export default {
          // ...
          computed: {
          // 使用对象展开运算符将 getter 混入 computed 对象中
            ...mapGetters([
              'doneTodosCount',
              'anotherGetter',
              // ...
            ])
          }
          }
          // ...
          mutations: {
          increment (state, n) { #n为increment的第一个参数
            state.count += n
          }
          }
          store.commit('increment', 10) #直接调用传入参数
          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')`
            })
          }
          }
          const store = new Vuex.Store({
          state: {
            count: 0
          },
          mutations: {
            increment (state) {
              state.count++
            }
          },
          actions: {
            increment (context) { #context则代表是所有的store 但不是store
              context.commit('increment')
            }
          }
          })
          <template>
           <div id="app">
            Hello app.vue!
             <!-- 显示路由组件的位置 -->
             <router-view></router-view>
           </div>
          </template>
          export default new Router({
          // mode: 'history', #默认是使用history模式的 在new VueRouter的时候配置mode值为history来改变路由模式,本质使用H5的histroy.pushState方法来更改url,不会引起刷新 ,直接访问路由是默认是首页,关闭即可
          routes: [
            {
              path: '/',
              name: 'HelloWorld',
              component: HelloWorld
            }
          }]
          <div>
               <router-link to = "/home">首页</router-link>
          </div>
          // 路由的懒加载方式
            { path :"/home",component:()=>import("../views/Home")},// 当我访问/home首页时,页面才去加载Home组件,减少首页加载的时长
            { path :"/list",component:()=>import("../views/List")}, //也可以使用 component:()=>import('@/views/List')
            { path :"/mine",component:()=>import("../views/Mine")}
          { path :"/list",component:()=>import("../views/List"),children:[
                // 二级路由前不需要加“/”
              { path: "audio", component: () => import("../views/Audio") },
              { path: "video", component: () => import("../views/Video") }
            ]}
          <div>
           <router-link to = "/list/audio">音频</router-link>
           <router-link to = "/list/video">视频</router-link>
          </div>
          <router-view></router-view>
          <router-link tag = "li" :to = "{name:'detail',params:{id:'1'},query:{title:'最近播放'}}">我的歌单</router-link>

           

           

           

           

           

           

          路由跳转中 路由1,2同个路由节点,路由1设置了replace ,则先点击路由2再到路由1 ,用户点击浏览器退回按钮在路由2会被替换

          路由跳转到不同的url默认是push的过程,当用户点击浏览器后退按钮式时,则回到之前url,replace属性可以控制router-link的跳转不被记录。

          7、replace

          注解:name是要跳转的路由的名字,也可以写path来指定路径,但是用path的时候就不能使用params传参,params是传路由参数,query传queryString参数

          router-link的to属性,默认写的是path(路由的路径),可以通过设置一个对象,来匹配更多。

          6、to

          注:二级路由组件的切换位置依然由router-view来指定(指定在父级路由组件的模板中)。

          在创建路由表的时候,可以为每一个路由对象创建children属性,值为数组,在这个里面又可以配置一些路由对象来使用多级路由,注意:一级路由path前加'/',二级路由前不需要加'/'。

          5、二级路由:

          懒加载也叫延迟加载,即在需要的时候进行加载,随用随载。在单页应用中,如果没有应用懒加载,运用webpack打包后的文件将会异常的大,造成进入首页时,需要加载的内容过多,延时过长,会出现长时间的白屏

          4、路由懒加载

          3、使用route-link来创建切换路由工具

          2、在route中使用的mode是history模式

          1、路由切换须使用route-view

          vue的路由

          6、分发action mutation 执行的都是同步,但是action则可以执行异步

          5、可以使用mapMutations映射到vue

          4、改变store且传入参数

          3、mapGetter使用

          2、vuex 的getter使用

          1、获取多个状态的时候可以使用mapstate处理

           

          vue官方调试工具:https://github.com/vuejs/vue-devtools

          Flux文档:https://facebook.github.io/flux/docs/overview

          Redux文档:https://redux.js.org/

          vuex课程:https://scrimba.com/learn/vuex

          一些link

          vuex的一些基本语法

          注:开发项目中遇到的bug处理

           

          37、在eslint中 当存在简单替代方案时,不允许使用三元运算符

          36、在vue中函数不能与变量名一致,否则报错

          35、checkbox 中替代v-model的写法

          34、子组件的prop数据是单向流动的,意味着不能通过子组件去改变父组件的元素

          33、在prop的子组件中可以传入动态或者静态的prop

          32、prop定义数据的类型

          31、在prop中使用大写 在浏览器中可以直接转为小写的

          30、组件的全局注册

          29、组件名称:短横线或者是驼峰命名

          28、在父子组件中使用事件 可以使用v-model 来绑定事件

          27、在元素中添加js事件

          26、在style中添加变量

          25、每个组件都是新的实例,每个实例可以维护一份被返回对象的独立的拷贝,因为每个组件数据互不影响,组件元素比较只有一个根元素、否则报错

          组件可与v-model使用

          24、修饰符

          23、表单输入使用v-model

          22、按键修饰符

            可以理解为该修饰符的作用就是把一个vue组件转化为一个普通的HTML标签,并且该修饰符对普通HTML标签是没有任何作用的。

              img

              此时点击就会弹窗:

              img

               添加修饰符:

             此时点击页面中的按钮无任何反应。

              img

          (7). native:在父组件中给子组件绑定一个原生的事件,就将子组件变成了普通的HTML标签,不加'. native'事件是无法触 发的。

          (6). passive:该修饰符大概意思用于对DOM的默认事件进行性能优化,根据官网的例子比如超出最大范围的滚动条滚动的。

          (5). once:设置事件只能触发一次,比如按钮的点击等。

          img

          img 此时点击最内层:

          (4). self:将事件绑定到自身,只有自身才能触发,通常用于避免冒泡事件的影响

              img

          点击最内层结果:

          多个获取事件 :     img

              img

          此时点击最内层div,结果如下:

              img

          (3). capture:捕获冒泡,即有冒泡发生时,有该修饰符的dom元素会先执行,如果有多个,从外到内依次执行,然后再按自然顺序执行触发的事件。

            默认事件指对DOM的操作会引起自动执行的动作,比如点击超链接的时候会进行页面的跳转,点击表单提交按钮时会重新加载页面等,使用".prevent"修饰符可以阻止这些事件的发生。     img 此时点击超链接不会进行页面的跳转。

          (2). prevent:阻止默认事件的发生

              img

            再次点击内层div的结果如下:

              img

            修改代码,为内层点击事件添加事件".stop"修饰符:

              img

            点击外层div的结果:

              img

          点击内层div的结果:

          img

          (1). stop:阻止冒泡(通俗讲就是阻止事件向上级DOM元素传递)

          21、修饰符

           

           

           

          20、v-on 在事件中获取元素属性

          19、v-for中可以使用方法

          18、对已有对象赋值多个新属性 使用Object.assign() 、_.extend()

          17、v-for 中使用对象

          16、v-for 进行循环

          15、如果频繁的话使用v-show 如果条件复杂则使用v-if

          14、v-show 判断元素是否显示 类似于display

          Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。这么做除了使 Vue 变得非常快之外

          13、用 key 管理可复用的元素

          12、html绑定class 可以使用object 、可以使用[]三元表达式、 {}做类似if判断

          11、在vue中属性data跟methods方法名称不一样

          watch 是可以有setter getter 方法的 笔者使用会报错

        注意:不应该使用箭头函数来定义 watcher 函数,因为箭头函数没有 this,它的 this 会继承它的父级函数,但是它的父级函数是 window,导致箭头函数的 this 指向 window,而不是 Vue 实例

        一个对象,键是 data 对应的数据,值是对应的回调函数。值也可以是方法名,或者包含选项的对象,当 data 的数据发生变化时,就会发生一个回调,他有两个参数,一个 val (修改后的 data 数据),一个 oldVal(原来的 data 数据) Vue 实例将会在实例化时调用$watch(),遍历 watch 对象的每一个属性

        10、watch

        9、computed 通过计算出来的属性不需要调用直接可以在 DOM 里使用 页面渲染就会执行的

        8、v-缩写

        7 、修饰符

        6、绑定指令

        {{ }} 可以进行简单的运算以及三运表达式 {{ message.split('').reverse().join('') }}

        5、插入数据中使用双大括号

      4、子组件传数据给父组件

    3、父组件传数据给子组件

    2、配置本地的vue的淘宝镜像

  • 相关阅读:
    Servlet过滤器----Filter
    Servlet监听器详解及举例
    Servlet学习笔记(四)之请求转发与重定向(RequestDispatcher与sendRedirect)
    Servlet学习笔记(二)之Servlet路径映射配置、Servlet接口、ServletConfig、ServletContext
    Servlet学习笔记(三)之HttpServletResponse
    Servlet学习笔记(三)之HttpServletRequest
    Servlet学习笔记(一)之Servlet原理、初始化、生命周期、结构体系
    Python文件(File)及读写操作及生成器yield
    Python学习笔记摘要(一)类型 字符串 函数 列表 深浅拷贝
    Vue如何新建一个项目
  • 原文地址:https://www.cnblogs.com/guokefa/p/14155171.html
Copyright © 2020-2023  润新知