vue的一些知识整理

父子组件传值

  • 父组件向子组件传值

      //html
      //1.父组件通过v-bind给子组件传值
      <todo-item v-bind:content="data1"></todo-item>
    
      //script
      //定义全局组件
      Vue.component("TodoItem", {
          //2.子组件通过props接收
          props: ['content']
          //也可以用对象形式进行参数校验
          //props: {content: String}//只允许接受string
          template: "<li>{{content}}</li>"
      })
    
      var app = new Vue({
          ...
          data: {
              data1: "ted" 
          }
      })
    
  • 子组件向父组件传值

      //html
      //2.父组件使用子组件时,通过v-on监听触发的事件
      //一旦子组件delete触发,就会触发父组件handleItemDelete这个方法
      <todo-item v-on:delete="handleItemDelete">
      </todo-item>
    
      //script
      var TodoItem = {
          data: {
              data1: 'ted'
          },
          template: "<li v-on:click='handleButtonClick'>点我删除</li>",
          methods: {
              handleButtonClick: function() {
                  //1.子组件通过$emit向外触发delete事件,并传出data1
                  this.$emit("delete", data1)
              }
          }
      }
    
      var app = new Vue({
          ...
          methods: {
              //3.父组件使用子组件的值
              handleItemDelete: function(data1) {
                  alert("data1")
              }
          }
      })
    

非父子组件传值

  • 观察者模式

      <!-- 非父子组件传值 -->
    <!-- 通过观察者模式实现,两个子组件之间传值,点击其中一个组件,另一个组件的值变成这个被点击组件的值-->
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="./vue.js"></script>
    </head>
    <body>
    <div id="root">
      <child :content="content1"></child>
      <child :content="content2"></child>
    </div>
    <script>
      //1. 在Vue的prototype上定义一个bus
      Vue.prototype.bus = new Vue()
    
      Vue.component('child', {
        props: {
          content: String
        },
        template: '<div v-on:click="handleClick">{{content}}</div>',
        methods: {
          handleClick: function() {
            //使用bus向外触发事件
            this.bus.$emit('change', this.content)
          }
        },
        //利用钩子函数,监听change事件
        mounted: function() {
          var this_ = this
          this.bus.$on('change', function(msg) {
            this_.content = msg
          })
        }
      })
    
      var vm = new Vue({
        el: "#root",
        data: {
          content1: "tedqin",
          content2: "teddymoon"
        }
      })
    </script>
    </body>
    </html>
    
    
  • vuex

全局组件和局部组件

  • 全局组件:用Vue.component()方法定义,其他组件可以直接使用

      //html
      //父组件通过v-bind给子组件传值
      <todo-item v-bind:content="data1"></todo-item>
    
      //script
      //定义全局组件
      Vue.component("TodoItem", {
          //子组件通过props接收
          props: ['content']
          template: "<li>{{content}}</li>"
      })
    
      var app = new Vue({
          ...
          data: {
              data1: "ted" 
          }
      })
    
  • 局部组件:像普通对象一样定义,其他组件引用的时候需要注册

      //html
      //父组件通过v-bind给子组件传值
      <todo-item v-bind:content="data1"></todo-item>
    
      //script
      //定义局部组件
      var TodoItem = {
          props: ['content']
          template: "<li>{{content}}</li>"
      }
    
      var app = new Vue({
          ...
          //把局部逐渐注册到到需要引用它的组件的vue实例中
          components: {
              TodoItem: TodoItem
          }
          data: {
              data1: "ted" 
          }
      })
    

v-bind,v-model,v-for和v-on

  • v-bind:用于给标签/组件绑定属性,实现动态管理标签的属性

      //html
      <a v-bind:href="url">网络测试</a>  //v-bind绑定href
    
      //script
      var app = new Vue({
          ...
          data {
              url: "http://www.baidu.com"
              }
      })
    
      //html
      //父组件通过v-bind给子组件传值
      <todo-item v-bind:content="data1"></todo-item>
    
      //script
      Vue.component("TodoItem", {
          //子组件通过props接收
          props: ['content']
          template: "<li>{{content}}</li>"
      })
    
      var app = new Vue({
          ...
          data: {
              data1: "ted" 
          }
      })
    
  • v-model:实现数据和视图层的双向绑定,只能定义在input,select,textarea上,绑定之后随着input输入的变化,对应绑定的内容也变化,反之也变化

      //html
      <input type="text" v-model="inputValue" />
    
      //script
      var app = new Vue({
          ...
          data: {
              inputValue: ''
          }
      })
    
  • v-for:循环data

      //循环数组
      //html
      <li v-for="item of list">{{item.text}}</li>
      <li v-for="(item, index) of list">{{item.text}}---{{index}}</li>
      <li v-for="(item, index) of list" :key="item.id">{{item.text}}---{{index}}</li>  <!--用index的时候最好再用key唯一标识-->
    
      //script
      var app = new Vue({
          ...
          data: {
              list: [{
                  id: "1",
                  text: "ted"
              }, {
                  id: "2",
                  text: "xxy"
              }]
          }
      })
    
      //循环对象
      //html
      <li v-for="(item, key, index) of list">{{item}}--{{key}}--{{index}}</li>
      <!--输出"ted--name--0 23--age--1"-->
    
      //script
      var app = new Vue({
          ...
          data: {
              list: {
                  name: "ted",
                  age: "23"
              }
          }
      })
    
  • v-on:绑定事件

      //html
      <button v-on:click="handleButtonClick">提交</button>
    
      //script
      var app = new Vue({
          ...
          methods: {
              handleButtonClick: function() {
                  alert("click!")
              }
          }
      })
    

v-text和v-html的区别

  • v-text: 等同于插值表达式双括号,绑定当前元素的innerText,会原封不动的输出纯文本
  • v-html: 绑定当前元素的innerText,会以html规则编译文本内容后输出

      //html
      <div v-text="name"></div>    <!--输出<h1>ted</h1>-->
      <div v-html="name"></div>    <!--输出h1大小的ted-->
    
      //script
      var vm = new Vue({
          el:"#app",
          data: {
              name:"<h1>ted</h1>"
          }
      })
    

计算属性 computed

和逻辑有关的计算都放在computed中,不方便直接在模版中计算

例子:

  • get属性

      <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('')
          }
        }
      })
    
  • set属性

      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]
          }
        }
      }
    

上面代码中,get作用是通过监听firstName和lastName的改变,获取fullName的值;
set的所用是传入需要改变的fullName,并根据参数更新firstName和lastName的值

  • 和method的不同:
    • 计算属性中的值依赖data中相关联的值
    • computed存在缓存机制:每次重新渲染时,对于method,每次都会重新计算;对于计算属性,仅当data中依赖的值改变时,计算属性的值才改变,

侦听器 watch

和computed相似,同样是监听data中的值,当data发生改变时,执行相应的操作
也具有缓存效果

  • 和computed的不同:
    • computed是定义并计算一个新的值,这个值依赖data中的某些值
    • watch是监听data中已经存在的变量,并在data发生改变的时候做相应的操作
    • computed比watch更加简洁

样式绑定

  • class绑定::class=等价于: v-bind:class= ,将class绑定在一个标签上,可以控制class的显示与否

    • class的对象绑定 :class="{activated: isActivated}"

        <style>
            .activated {color: red}
        </style>
      
        <div @click="handleDivClick>  
              :class="{activated: isActivated}"></div>
      
          var vm = new Vue({
              el: "#app",
              data: {
                  isActicated: false
              },
              method: {
                  handleDivClick: function() {
                      this.isActivated = true
                  }
              }
          })
      
      
    • class的数组绑定 :class="[activated]"
    ```
    <style>
        .activated {color: red}
    </style>

    <div @click="handleDivClick>  
          :class="{activated: isActivated}"></div>

      var vm = new Vue({
          el: "#app",
          data: {
              activated: ""
          },
          method: {
              handleDivClick: function() {
                  this.activated = "activated"
              }
          }
      })

    ``` 
  • 内联样式绑定

    • style的对象绑定

        <div :style="styleObj" v-on:click="handleDivClick"></div>
      
          var vm = new Vue({
              el: "#app",
              data: {
                  styleObj: {
                      color: red
                  }
              },
              methods: {
                  handleDivClick: function() {
                      this.styleObj.color = red
                  }
              }
          })
      
    • style的数组绑定

      只需要把<div :style="styleObj"换成<div :style=[styleObj, {fontSize: '20px'}]

条件渲染

  • v-if: 隐藏的元素不会被渲染到页面上,还可以用v-else
  • v-show: 隐藏的元素已经被渲染到页面上,只是用了display:none来隐藏

      <div v-if="show">{{name}}</div>
      <div v-else="show">Bye</div>
      <div v-if="show===a">a</div>
      <div v-else-if="show===b">b</div>
      <div v-else>bye</div>
    
      <div v-show="show">{{name}}</div>
    
      var vm = new Vue({
          el: "#app",
          data: {
              name: 'ted',
              show: false
          },
      })
    

vue中的set方法

arr=[1,2,3,4,5]
data={
    name: "ted",
    age: "23"
}

改变页面中的渲染出来的对象或数组,不能直接用arr[3]=5这样直接改,只能修改数组/对象的引用,即this.arr=[1,2,5,4,5]全部修改

  • 也可以用Vue.set()方法修改,set方法也可以添加新的数据

      //改数组
      Vue.set(this.arr, 0, 11) //[11,2,3,4,5]
      //改对象
      Vue.set(this.data, "name", "teddy") //{name:"teddy", age: "23"}
    

slot插槽:

父组件向子组件传递dom结构: 直接在子组件中定义,然后在template中引入

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <script src="./vue.js"></script>
</head>
<body>
  <div id="app">
    <child>
      <h1>tedqin</h1>
    </child>
  </div>
  <script>
    Vue.component('child', {
      template: `<div>
                          <p>hello</p>
                      <slot></slot>
                  </div>
                `
    })

    var vm = new Vue({
      el: "#app"
    })
  </script>

</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <script src="./vue.js"></script>
</head>
<body>
  <div id="app">
    <child>
      <header slot="header"></header>
      <footer slot="footer"></footer>
    </child>
  </div>
  <script>
    Vue.component('child', {
      template: `<div>
                          <slot name="header"></slot>
                          <p>hello</p>
                      <slot name="footer"></slot>
                  </div>
                `
    })

    var vm = new Vue({
      el: "#app"
    })
  </script>

</body>
</html>

动态组件

<component :is="type"></component>

//
Vue.component('type1', {
    template: '<div>type1</div>'
})
Vue.component('type2', {
    template: '<div>type2</div>'
})

//
data:{
    type: 'type1'
}

//
methods: {
    handleBtnClick: function(){
        this.type = (this.type==="type1" ? 'type2' : 'type1')
    }
}

根据is属性绑定的data数据中的type动态切换组件

v-once

将第一次展示在页面中的资源保存在内存中,下次直接从内存中取资源,可以优化性能,提高静态页面展示效率

##vue的路由

  • src/main.js

    • 入口文件,定义了一个根实例

      import Vue from 'vue'
      import App from './App'
      import router from './router'
      
      new Vue({
        el: "app", //app挂载点在./index.html上
        router, //使用router,在路由配置文件index.js中配置路由
        components: { App }, //使用子组件App
        template: '<App/>' //渲染App这个局部组件
      })
      
  • src/App.js

    • App局部组件,也就是main.js渲染的页面,也就是主页面

      <template>
        <div id="app>
            <router-view> //显示当前路由地址所对应的路由内容
        </div>
      </template>
      
      <script>
      export default {
        name: 'App'
      }
      <sctipt>
      
      <style>
      #app {
        ...
      }
      <style>
      
  • src/router/index.js

    • 路由配置项

      `
      import Vue from ‘vue’
      import Router from ‘vue-router’
      import Home from ‘@/pages/home/Home’
      import Home from ‘@/pages/list/List’

Vue.use(Router)

export default new Router({
    routes: [
        {
            path: '/', //1.当用户访问根路径的时候
            name: 'Home', 
            components: Home // 2.访问home这个单文件组件
        }, {
            //增加其他页面的配置项
            path: '/list',
            name: 'List',
            components: List
        }
    ]
})
```     
  • @/pages/home/Home.vue

    • 主页,单文件组件

      <template>
        <div>home</div>
      </template>
      
      <script>
      export default {
        name: 'Home'
      }
      </script>
      
      <style>
      </style>
      
  • @/pages/list/List.vue

    • list页面,单文件组件

      <template>
        <div>list</div>
      </template>
      
      <script>
      export default {
        name: 'List'
      }
      </script>
      
      <style>
      </style>
      

vue是单页面应用,用替换a标签

<router-link to="/list">点击跳转</router-link>