vue.js 基础知识


1. 使用工具和学习路径

中文官网地址: https://cn.vuejs.org/v2/guide/

使用工具 Hbuilder X

2. 基础知识

  • 常用指令
    • v-bind
    • v-mode
    • v-for
      <dev id=appx>
      <ul>
        <li v-for="item in items">
            {{ itme.title }}
        </li>
      </ul>
      </dev>
      <script>
      var vm = new Vue({
      el:"#appx",
      data:{
        items: [
            {"title": "张三"}
            {"title": "李四"}
            {"title": "王五"}
        ]
      })
      </script>
      
    • v-if
  • 单项数据绑定和双向数据绑定 xxxxx
  • Vue()子类的使用

  • 对象实例以及对象实例的调用

    <script>
    var vm = new Vue({
      el:"#appxxx",
      data:{
          title:"我vuejs学习",
          url:"http://www.baidu.com"
      }
    })
    // vm.$el 就相当于 document.getElementById("appxxx")
    //样式设置为红色
    vm.$.el.style.color = "red";
    </script>
    
  • vue.js 文件引用

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title></title>
    <script src="vue.js" type="text/javascript" charset="utf-8"></script>
    </head>
    <body>
      <div id="app">
        {{ message }} {{name}}
      </div>
    
      <script type="text/javascript">
      var app = new Vue({
          el: '#app',
          data: {
              message: 'Hello Vue!',
              name : "Vue"
          }
      });
      </script>
    </body>
    </html>
    
  • 数据和方法(用实例的方法 $watch 观察变量值改变前后情况 )
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title></title>
    <script src="vue.js" type="text/javascript" charset="utf-8"></script>
    </head>
    <body>
    <div id="app">
      {{a}}
    </div>
    <script type="text/javascript">
    var data = { a : 1 };
    var vm = new Vue({
      el   : "#app",
      data : data
    });
    vm.$watch('a', function(newVal, oldVal){
      console.log(newVal, oldVal);
    })
    vm.$data.a = "test...."
    </script>
    </body>
    </html>
    
  • 实例生命周期

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title></title>
    <script src="vue.js" type="text/javascript" charset="utf-8"></script>
    </head>
    <body>
    <div id="app">
      {{msg}}
    </div>
    <script type="text/javascript">
    var vm = new Vue({
      el : "#app",
      data : {
          msg : "hi vue",
      },
      //在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
      beforeCreate:function(){
          console.log('beforeCreate');
      },
      /* 在实例创建完成后被立即调用。
      在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。
      然而,挂载阶段还没开始,$el 属性目前不可见。 */
      created :function(){
          console.log('created');
      },
      //在挂载开始之前被调用:相关的渲染函数首次被调用
      beforeMount : function(){
          console.log('beforeMount');
    
      },
      //el 被新创建的 vm.$el 替换, 挂在成功  
      mounted : function(){
          console.log('mounted');
    
      },
      //数据更新时调用
      beforeUpdate : function(){
          console.log('beforeUpdate');
    
      },
      //组件 DOM 已经更新, 组件更新完毕 
      updated : function(){
          console.log('updated');
    
      }
    });
    setTimeout(function(){
      vm.msg = "change ......";
    }, 3000);
    </script>
    </body>
    </html>
    

  • 模板语法-插值

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title></title>
    <script src="vue.js" type="text/javascript" charset="utf-8"></script>
    </head>
    <body>
    <div id="app">
      {{msg}}
      <p>Using mustaches: {{ rawHtml }}</p>
      <p v-html="rawHtml"></p>
      <div v-bind:class="color">test...</div>
      <p>{{ number + 1 }}</p>
      <p>{{ 1 == 1 ? 'YES' : 'NO' }}</p>
      <p>{{ message.split('').reverse().join('') }}</p>
    </div>
    <script type="text/javascript">
    var vm = new Vue({
      el : "#app",
      data : {
          msg : "hi vue",
          rawHtml : '<span style="color:red">this is should be red</span>',
          color:'blue',
          number : 10,
          ok : 1,
          message : "vue"
      }
    });
    vm.msg = "hi....";
    </script>
    <style type="text/css">
    .red{color:red;}
    .blue{color:blue; font-size:100px;}
    </style>
    </body>
    </html>
    

  • 模板属性-指令

v-bind 绑定的是属性, v-on 绑定的是事件

<! -- 动态参数 -->
<a v-bind:[attributeName]="url"> ... </a>
<a v-on:[eventName]="doSomething"> ... </a>
<-! Vue 实例有一个 data--></-!>
data : {
    attributeName:  "href",
    eventName: "click"
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
    <p v-if="seen">现在你看到我了</p>
    <a v-bind:href="url">...</a>
    <div @click="click1">
        <div @click.stop="click2">
            click me
        </div>
    </div>
</div>
<script type="text/javascript">
var vm = new Vue({
    el : "#app",
    data : {
        seen : false,
        url : "https://cn.vuejs.org/v2/guide/syntax.html#%E6%8C%87%E4%BB%A4"
    },
    methods:{
        click1 : function () {
            console.log('click1......');
        },
        click2 : function () {
            console.log('click2......');
        }
    }
});
</script>
<style type="text/css">

</style>
</body>
</html>
  • 计算属性和侦听器

<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('')
    }
  }
})

计算属性缓存 vs 方法

<p>Reversed message: "{{ reversedMessage() }}"</p>
// 在组件中
methods: {
  reversedMessage: function () {
    return this.message.split('').reverse().join('')
  }
}

我们可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。

这也同样意味着下面的计算属性将不再更新,因为 Date.now() 不是响应式依赖:

computed: {
  now: function () {
    return Date.now()
  }
}

计算属性和侦听器的对比

<div id="demo">{{ fullName }}</div>
var vm = new Vue({
  el: '#demo',
  data: {
    firstName: 'Foo',
    lastName: 'Bar',
    fullName: 'Foo Bar'
  },
  watch: {
    firstName: function (val) {
      this.fullName = val + ' ' + this.lastName
    },
    lastName: function (val) {
      this.fullName = this.firstName + ' ' + val
    }
  }
})
var vm = new Vue({
  el: '#demo',
  data: {
    firstName: 'Foo',
    lastName: 'Bar'
  },
  computed: {
    fullName: function () {
      return this.firstName + ' ' + this.lastName
    }
  }
})
  • 计算属性的setter
// ...
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]
    }
  }
}
// ...
  • 侦听器

当需要在数据变化时执行异步或开销较侦听器watch

<div id="watch-example">
  <p>
    Ask a yes/no question:
    <input v-model="question">
  </p>
  <p>{{ answer }}</p>
</div>
<!-- 因为 AJAX 库和通用工具的生态已经相当丰富Vue 核心代码没有重复 -->
<!-- 提供这些功能以保持精简这也可以让你自由选择自己更熟悉的工具 -->
<script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
<script>
var watchExampleVM = new Vue({
  el: '#watch-example',
  data: {
    question: '',
    answer: 'I cannot give you an answer until you ask a question!'
  },
  watch: {
    // 如果 `question` 发生改变,这个函数就会运行
    question: function (newQuestion, oldQuestion) {
      this.answer = 'Waiting for you to stop typing...'
      this.debouncedGetAnswer()
    }
  },
  created: function () {
    // `_.debounce` 是一个通过 Lodash 限制操作频率的函数。
    // 在这个例子中,我们希望限制访问 yesno.wtf/api 的频率
    // AJAX 请求直到用户输入完毕才会发出。想要了解更多关于
    // `_.debounce` 函数 (及其近亲 `_.throttle`) 的知识,
    // 请参考:https://lodash.com/docs#debounce
    this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
  },
  methods: {
    getAnswer: function () {
      if (this.question.indexOf('?') === -1) {
        this.answer = 'Questions usually contain a question mark. ;-)'
        return
      }
      this.answer = 'Thinking...'
      var vm = this
      axios.get('https://yesno.wtf/api')
        .then(function (response) {
          vm.answer = _.capitalize(response.data.answer)
        })
        .catch(function (error) {
          vm.answer = 'Error! Could not reach the API. ' + error
        })
    }
  }
})
</script>
  • Class 与 Style 绑定
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
    <div 
    class="test" 
    v-bind:class="[ isActive ? 'active' : '', isGreen ? 'green' : '']" 
    style="width:200px; height:200px; text-align:center; line-height:200px;">
        hi vue
    </div>

    <div 
    :style="{color:color, fontSize:size, background: isRed ? '#FF0000' : ''}">
        hi vue
    </div>
</div>
<script type="text/javascript">
var vm = new Vue({
    el : "#app",
    data : {
        isActive : true,
        isGreen : true,
        color : "#FFFFFF",
        size : '50px',
        isRed : true
    }
});
</script>
<style>
.test{font-size:30px;}
.green{color:#00FF00;}
.active{background:#FF0000;}
</style>
</body>
</html>
<-! 如果isActive 的值为true 那么class 就是 active如果为false 就是空如果isGreen 的值为false 那么class就是green如果为false 就是空--></-!>
v-bind:class="[ isActive ? 'active' : '', isGreen ? 'green' : '']"
<-! isRed 的值为true那么background 就是 #FF0000的颜色如果是false 那么background 就是空--></-!>
:style="{color:color, fontSize:size, background: isRed ? '#FF0000' : ''}">
  • 条件渲染
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
    <div v-if="type === 'A'">
      A
    </div>
    <div v-else-if="type === 'B'">
      B
    </div>
    <div v-else-if="type === 'C'">
      C
    </div>
    <div v-else>
      Not A/B/C
    </div>
    <h1 v-show="ok">Hello!</h1>
</div>
<script type="text/javascript">
var vm = new Vue({
    el : "#app",
    data : {
        type : "B",
        ok : false
    }
});
</script>
<style type="text/css">

</style>
</body>
</html>
<-! v-if 是真正意义的条件渲染v-show 并不是v-show 是会都渲染出来只不过通过css样式display 属性进行控制是否显示在页面></-!>
  • 列表渲染
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
    <ul>
        <li v-for="item,index in items" :key="index">
        {{index}}{{ item.message }}
        </li>
    </ul>
    <ul>
        <li v-for="value, key in object" :key="key">
            {{key}} : {{ value }}
        </li>
    </ul>
</div>
<script type="text/javascript">
var vm = new Vue({
    el : "#app",
    data : {
        items : [
            { message: 'Bar' },
            { message: 'I Fly'},
            { message: 'Foo' },
        ],
        object: {
            message: 'hello, vue.js!',
            title: 'How to do lists in Vue',
            author: 'Jane Doe',
            publishedAt: '2016-04-10'
        }
    }
});
</script>
</body>
</html>
  • 事件处理
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
    <div id="example-1">
        <button v-on:click="counter += 1"> 数值 :  {{ counter }} </button><br />
        <button v-on:dblclick="greet('abc', $event)">Greet</button>
    </div>
</div>
<script type="text/javascript">
var vm = new Vue({
    el : "#app",
    data : {
        counter: 0,
        name : "vue"
    },
    methods:{
        greet : function (str, e) {
            alert(str);
            console.log(e);
        }
    }
});
</script>
<style type="text/css">

</style>
</body>
</html>

Vue.js 为 v-on 提供了事件修饰符

<!-- 阻止单击事件继续传播 -->
<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>
  • 表单输入绑定
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
    <div id="example-1">
        <input v-model="message" placeholder="edit me">
        <p>Message is: {{ message }}</p>
        <textarea v-model="message2" placeholder="add multiple lines"></textarea>
        <p style="white-space: pre-line;">{{ message2 }}</p>
        <br />

        <div style="margin-top:20px;">
            <input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
            <label for="jack">Jack</label>
            <input type="checkbox" id="john" value="John" v-model="checkedNames">
            <label for="john">John</label>
            <input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
            <label for="mike">Mike</label>
            <br>
            <span>Checked names: {{ checkedNames }}</span>
        </div>

        <div style="margin-top:20px;">
            <input type="radio" id="one" value="One" v-model="picked">
            <label for="one">One</label>
            <br>
            <input type="radio" id="two" value="Two" v-model="picked">
            <label for="two">Two</label>
            <br>
            <span>Picked: {{ picked }}</span>
        </div>
        <button type="button" @click="submit">提交</button>
    </div>

</div>
<script type="text/javascript">
var vm = new Vue({
    el : "#app",
    data : {
        message : "test",
        message2 :"hi",
        checkedNames : ['Jack', 'John'],
        picked : "Two"
    },
    methods: {
        submit : function () {
            var submitObj = {
                msg1 : this.message,
                msg2 : this.message2,
                chckname : this.checkedNames,
                pck : this.picked
            };
            console.log(submitObj);

        }
    }
});
</script>
<style type="text/css">

</style>
</body>
</html>