【一起来烧脑】一步学会Vue.js系统

Vuejs是一个构建数据驱动的web界面的库,通过api实现响应的数据绑定和组合的视图组件,Vue.js的核心是一个响应的数据绑定系统,它让数据与DOM保持同步非常简单,一旦创建了绑定,DOM 将与数据保持同步。


Vue.js 安装

<script> 标签
CDN
NPM

# 最新稳定版本
$ npm install vue
# 最新稳定CSP兼容版本
$ npm install vue@csp

vue.js提供了一个官方命令工具,可以快速搭建大型单页应用。

# 全局安装 vue-cli
$ npm install -g vue-cli
# 创建一个基于 "webpack" 模板的新项目
$ vue init webpack my-project
# 安装依赖
$ cd my-project
$ npm install
$ npm run dev

开发版本

git clone https://github.com/vuejs/vue.git node_modules/vue
cd node_modules/vue
npm install
npm run build

Bower

# 最新稳定版本
$ bower install vue

语法格式如下:

var vm = new Vue({
  // 选项
})
<div id="vue_det">
    <h1>site : {{site}}</h1>
    <h1>url : {{url}}</h1>
    <h1>{{details()}}</h1>
</div>
<script type="text/javascript">
    var vm = new Vue({
        el: '#vue_det',
        data: {
            site: "",
            url: "",
            alexa: ""
        },
        methods: {
            details: function() {
                return  this.site + " 程序员";
            }
        }
    })
</script>

Vue构造器中有一个el参数
它是DOM元素中的id

<div id = "vue_det"></div>
<div id="vue_det">
    <h1>site : {{site}}</h1>
    <h1>url : {{url}}</h1>
    <h1>Alexa : {{alexa}}</h1>
</div>
<script type="text/javascript">
// 数据对象
var data = { site: "", url: "", alexa: 10000}
var vm = new Vue({
    el: '#vue_det',
    data: data
})
// 它们引用相同的对象
document.write(vm.a === data.a) // true
document.write("<br>")
// 设置属性也会影响到原始数据
vm.site = "imooc"
document.write(data.site + "<br>") // imooc
// ……反之亦然
data.alexa = 1234
document.write(vm.alexa) // 1234
</script>

Vue 实例
提供了一些有用的实例属性与方法

前缀 $

<div id="vue_det">
    <h1>site : {{site}}</h1>
    <h1>url : {{url}}</h1>
    <h1>Alexa : {{alexa}}</h1>
</div>
<script type="text/javascript">
// 数据对象
var data = { site: "", url: "", alexa: 10000}
var vm = new Vue({
    el: '#vue_det',
    data: data
})
document.write(vm.$data === data) // true
document.write("<br>") // true
document.write(vm.$el === document.getElementById('vue_det')) // true
</script>

目录

[外链图片转存失败(img-jDOJm1Ph-1563338047361)(https://upload-images.jianshu.io/upload_images/11158618-6a1fbaa8fb8a4d59.png?imageMogr2/auto-orient/strip|imageView2/2/w/1240)]

模板语法

文本插值

<div id="app">
  <p>{{ message }}</p>
</div>

HTML

<div id="app">
    <div v-html="message"></div>
</div>
<script>
new Vue({
  el: '#app',
  data: {
    message: '<h1></h1>'
  }
})
</script>

属性

<div id="app">
  <label for="r1">修改颜色</label><input type="checkbox" v-model="class1" id="r1">
  <br><br>
  <div v-bind:class="{'class1': class1}">
    directiva v-bind:class
  </div>
</div>
<script>
new Vue({
    el: '#app',
  data:{
      class1: false
  }
});
</script>

表达式

<div id="app">
    {{5+5}}<br>
    {{ ok ? 'YES' : 'NO' }}<br>
    {{ message.split('').reverse().join('') }}
    <div v-bind:id="'list-' + id"></div>
</div>
<script>
new Vue({
  el: '#app',
  data: {
    ok: true,
    message: '',
    id : 1
  }
})
</script>

指令

<div id="app">
    <p v-if="seen">现在你看到我了</p>
</div>
<script>
new Vue({
  el: '#app',
  data: {
    seen: true
  }
})
</script>

参数

<div id="app">
    <pre><a v-bind:href="url"></a></pre>
</div>
<script>
new Vue({
  el: '#app',
  data: {
    url: ''
  }
})
</script>
<a v-on:click="doSomething">

修饰符

<form v-on:submit.prevent="onSubmit"></form>

用户输入

<div id="app">
    <p>{{ message }}</p>
    <input v-model="message">
</div>
<script>
new Vue({
  el: '#app',
  data: {
    message: 'imooc'
  }
})
</script>
<div id="app">
    <p>{{ message }}</p>
    <button v-on:click="reverseMessage">反转字符串</button>
</div>
<script>
new Vue({
  el: '#app',
  data: {
    message: 'coding'
  },
  methods: {
    reverseMessage: function () {
      this.message = this.message.split('').reverse().join('')
    }
  }
})
</script>

过滤器

<!-- 在两个大括号中 -->
{{ message | capitalize }}
<!-- 在 v-bind 指令中 -->
<div v-bind:id="rawId | formatId"></div>
<div id="app">
  {{ message | capitalize }}
</div>
<script>
new Vue({
  el: '#app',
  data: {
    message: 'coding'
  },
  filters: {
    capitalize: function (value) {
      if (!value) return ''
      value = value.toString()
      return value.charAt(0).toUpperCase() + value.slice(1)
    }
  }
})
</script>

过滤器可以串联:

{{ message | filterA | filterB }}

过滤器是JavaScript函数,可以接受参数:

{{ message | filterA('arg1', arg2) }}

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="app">
    <p v-if="seen">现在看到了这句话</p>
    <template v-if="ok">
      <h1></h1>
      <p></p>
      <p></p>
    </template>
</div>
<script>
new Vue({
  el: '#app',
  data: {
    seen: true,
    ok: true
  }
})
</script>

v-else

<div id="app">
    <div v-if="Math.random() > 0.7">
      Sorry
    </div>
    <div v-else>
      Not sorry
    </div>
</div>
<script>
new Vue({
  el: '#app'
})
</script>

v-else-if

<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>
</div>
<script>
new Vue({
  el: '#app',
  data: {
    type: 'C'
  }
})
</script>

v-show

<h1 v-show="ok">Hello!</h1>

循环语句

v-for可以绑定数据到数组来渲染一个列表

<div id="app">
  <ol>
    <li v-for="site in sites">
      {{ site.name }}
    </li>
  </ol>
</div>
<script>
new Vue({
  el: '#app',
  data: {
    sites: [
      { name: 'course' },
      { name: 'class' },
      { name: 'coding' }
    ]
  }
})
</script>

v-for可以通过一个对象的属性来迭代数据

<div id="app">
  <ul>
    <li v-for="value in object">
    {{ value }}
    </li>
  </ul>
</div>
<script>
new Vue({
  el: '#app',
  data: {
    object: {
      name: '慕课网',
      url: 'http://www.imooc.com',
      slogan: '程序员的梦工厂!'
    }
  }
})
</script>

v-for也可以循环整数

<div id="app">
  <ul>
    <li v-for="n in 10">
     {{ n }}
    </li>
  </ul>
</div>

计算属性

<div id="app">
  <p>原始字符串: {{ message }}</p>
  <p>计算后反转字符串: {{ reversedMessage }}</p>
</div>
<script>
var vm = new Vue({
  el: '#app',
  data: {
    message: 'imooc'
  },
  computed: {
    // 计算属性的 getter
    reversedMessage: function () {
      // `this` 指向 vm 实例
      return this.message.split('').reverse().join('')
    }
  }
})
</script>

computed 是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值

methods ,在重新渲染的时候,函数总会重新调用执行

var vm = new Vue({
  el: '#app',  
  data: {
    name: '',
    url: ''
  },
   computed: {
    site: {
      // getter
      get: function () {
        return this.name + ' ' + this.url
      },
      // setter
      set: function (newValue) {
        var names = newValue.split(' ')
        this.name = names[0]
        this.url = names[names.length - 1]
      }
    }
  }})
// 调用 setter, vm.name 和 vm.url 也会被对应更新
vm.site = '实战 https:';
document.write('name: ' + vm.name);
document.write('<br>');
document.write('url: ' + vm.url);

监听属性

可以通过watch来响应数据的变化

<div id = "computed_props">
    千米 : <input type = "text" v-model = "kilometers">
    米 : <input type = "text" v-model = "meters">
</div>
<p id="info"></p>
<script type = "text/javascript">
    var vm = new Vue({
    el: '#computed_props',
    data: {
        kilometers : 0,
        meters:0
    },
    methods: {
    },
    computed :{
    },
    watch : {
        kilometers:function(val) {
            this.kilometers = val;
            this.meters = val * 1000;
        },
        meters : function (val) {
            this.kilometers = val/ 1000;
            this.meters = val;
        }
    }
    });
    // $watch 是一个实例方法
    vm.$watch('kilometers', function (newValue, oldValue) {
    // 这个回调将在 vm.kilometers 改变后调用
    document.getElementById ("info").innerHTML = "修改前的值" + oldValue + ",修改后的值" + newValue;
})
</script>

样式绑定

Class 与 Style 绑定

<div class="static" v-bind:class="{ 'class-a': isA, 'class-b': isB }"></div>
data: {
  isA: true,
  isB: false
}
<div v-bind:class="classObject"></div>
data: {
  classObject: {
      'class-a': true,
      'class-b': false
  }
}
<div v-bind:class="[classA, classB]">
data: {
  classA: 'class-a',
  classB: 'class-b'
}
<div v-bind:class="[classA, isB ? classB : '']">

绑定内联样式

<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
data: {
  activeColor: 'red',
  fontSize: 30
 }
<div v-bind:style="styleObject"></div>
data: {
  styleObject: {
    color: 'red',
    fontSize: '13px'
  }
}
<div v-bind:style="[styleObjectA, styleObjectB]">

事件处理器

v-on指令

<div id="app">
  <button v-on:click="counter += 1">增加1</button>
  <p>这个按钮被点击了 {{ counter }} 次。</p>
</div>
<script>
new Vue({
  el: '#app',
  data: {
    counter: 0
  }
})
</script>
<div id="app">
   <!-- `greet` 是在下面定义的方法名 -->
  <button v-on:click="greet">Greet</button>
</div>
<script>
var app = new Vue({
  el: '#app',
  data: {
    name: 'Vue.js'
  },
  // 在 `methods` 对象中定义方法
  methods: {
    greet: function (event) {
      // `this` 在方法里指当前 Vue 实例
      alert('Hello ' + this.name + '!')
      // `event` 是原生 DOM 事件
      if (event) {
          alert(event.target.tagName)
      }
    }
  }
})
// 也可以用 JavaScript 直接调用方法
app.greet() // -> 'Hello Vue.js!'
</script>
<div id="app">
  <button v-on:click="say('hi')">Say hi</button>
  <button v-on:click="say('what')">Say what</button></div>
<script>
new Vue({
  el: '#app',
  methods: {
    say: function (message) {
      alert(message)
    }
  }
})
</script>

事件修饰符

<!-- 阻止单击事件冒泡 -->
<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>
<!-- 只当事件在该元素本身(而不是子元素)触发时触发回调 -->
<div v-on:click.self="doThat">...</div>
<!-- click 事件只能点击一次,2.1.4版本新增 -->
<a v-on:click.once="doThis"></a>

按键修饰符

<!-- 只有在 keyCode 是 13 时调用 vm.submit() -->
<input v-on:keyup.enter="submit">
<!-- 缩写语法 -->
<input @keyup.enter="submit">
按键别名:
.enter、.tab、.delate、.esc、.space、.up、.down、.left、.right、.ctrl、.alt、.shift、.meta

表单

<div id="app">
  <p>input 元素:</p>
  <input v-model="message" placeholder="编辑这里">
  <p>消息是: {{ message }}</p>    
  <p>textarea 元素:</p>
  <p style="white-space: pre">{{ message2 }}</p>
  <textarea v-model="message2" placeholder="多行文本输入"></textarea>
</div>
<script>
new Vue({
  el: '#app',
  data: {
    message: '',
    message2: ''
  }
})
</script>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.bootcss.com/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="app">
  <select v-model="selected" name="fruit">
    <option value="">选择一个网站</option>
    <option value=""></option>
    <option value=""></option>
  </select>
 
  <div id="output">
      选择的网站是: {{selected}}
  </div>
</div>

<script>
new Vue({
  el: '#app',
  data: {
	selected: '' 
  }
})
</script>
</body>
</html>
<div id="app">
  <input type="radio" id="" value="" v-model="picked">
  <label for=""></label>
  <br>
  <input type="radio" id="" value="" v-model="picked">
  <label for=""></label>
  <br>
  <span>选中值为: {{ picked }}</span></div>
<script>
new Vue({
  el: '#app',
  data: {
    picked : 'coding'
  }
})
</script>
<div id="app">
  <p>单个复选框:</p>
  <input type="checkbox" id="checkbox" v-model="checked">
  <label for="checkbox">{{ checked }}</label>
     
  <p>多个复选框:</p>
  <input type="checkbox" id="course" value="course" v-model="checkedNames">
  <label for="course">course</label>
  <input type="checkbox" id="class" value="class" v-model="checkedNames">
  <label for="class">class</label>
  <input type="checkbox" id="coding" value="coding" v-model="checkedNames">
  <label for="coding">coding</label>
  <br>
  <span>选择的值为: {{ checkedNames }}</span></div>
 <script>new Vue({
  el: '#app',
  data: {
    checked : false,
    checkedNames: []
  }
})
</script>

过渡

<div v-if="show" transition="my-transition"></div>

组件

封装可重用的代码

注册一个全局组件语法格式如下:

Vue.component(tagName, options)

tagName 为组件名,options 为配置选项

<tagName></tagName>

全局组件

所有的实例都能用全局组件

<div id="app">
    <w></w>
</div>
<script>
// 注册
Vue.component('w', {
  template: '<h1>自定义组件!</h1>'
})
// 创建根实例
new Vue({
  el: '#app'
})
</script>

局部组件

<div id="app">
    <w></w>
</div>
<script>
var Child = {
  template: '<h1>自定义组件!</h1>'
} 
// 创建根实例
new Vue({
  el: '#app',
  components: {
    // <> 将只在父模板可用
    'w': Child
  }
})
</script>

Prop

Prop是父组件用来传递数据的一个自定义属性
父组件的数据需要通过props把数据传给子组件

子组件需要显式的用props选项声明prop

<div id="app">
    <child message="hello!"></child>
</div>
<script>
// 注册
Vue.component('child', {
  // 声明 props
  props: ['message'],
  // 同样也可以在 vm 实例中像 "this.message" 这样使用
  template: '<span>{{ message }}</span>'
})
// 创建根实例
new Vue({
  el: '#app'
})
</script>

动态prop

<div id="app">
    <div>
      <input v-model="parentMsg">
      <br>
      <child v-bind:message="parentMsg"></child>
    </div>
</div>
<script>
// 注册
Vue.component('child', {
  // 声明 props
  props: ['message'],
  // 同样也可以在 vm 实例中像 "this.message" 这样使用
  template: '<span>{{ message }}</span>'
})
// 创建根实例
new Vue({
  el: '#app',
  data: {
    parentMsg: '父组件内容'
  }
})
</script>
<div id="app">
    <ol>
    <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
      </ol>
</div>
<script>
Vue.component('todo-item', {
  props: ['todo'],
  template: '<li>{{ todo.text }}</li>'
})
new Vue({
  el: '#app',
  data: {
    sites: [
      { text: 'course' },
      { text: 'class' },
      { text: 'coding' }
    ]
  }
})
</script>
<div id="app">
    <ol>
    <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
      </ol>
</div>
<script>
Vue.component('todo-item', {
  props: ['todo'],
  template: '<li>{{ todo.text }}</li>'
})
new Vue({
  el: '#app',
  data: {
    sites: [
      { text: 'course' },
      { text: 'class' },
      { text: 'coding' }
    ]
  }
})
</script>

prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来

type可以是下面几种原生构造器:

String、Number、Boolean、Function、Object、Array

自定义指令

bind:只调用一次
unbind:只调用一次,在指令从元素上解绑时调用

Vue.directive(id, definition) 方法注册一个全局自定义指令

Vue.directive('my-directive', {
  bind: function () { 
    // 准备工作
    // 例如,添加事件处理器或只需要运行一次的高耗任务
  },
  update: function (newValue, oldValue) { 
    // 值更新时的工作
    // 也会以初始值为参数调用一次
  },
  unbind: function () {  
    // 清理工作
    // 例如,删除 bind() 添加的事件监听器
  }
})
<div v-my-directive="someValue"></div>
Vue.directive('my-directive', function (value) {
  // 这个函数用作 update()
})

自定义过滤器

Vue.filter()注册一个自定义过滤器

Vue.filter('reverse', function (value) { 
 return value.split('').reverse().join('')
})

Vue.js允许通过简单的方法来自定义过滤器,即,利用管道“|”来完成过滤

混合

分布复用功能

// 定义一个混合对象
var myMixin = {
  created: function () { 
     this.hello()
  },
  methods: {
    hello: function () {   
       console.log('hello from mixin!')
    }
  }
}
// 定义一个组件,使用这个混合对象
var Component = Vue.extend({
  mixins: [myMixin]
})
var component = new Component() // -> "hello from mixin!"

插件

install

第一个参数是 Vue 构造器
一个可选的选项对象

MyPlugin.install = function (Vue, options) {  
  // 1. 添加全局方法或属性
  Vue.myGlobalMethod = ... 
  // 2. 添加全局资源
  Vue.directive('my-directive', {}) 
  // 3. 添加实例方法
  Vue.prototype.$myMethod = ...
}

Vue.use()全局方法使用插件:

// 调用 `MyPlugin.install(Vue)`
Vue.use(MyPlugin)

也可以传入一个选项对象:

Vue.use(MyPlugin, { someOption: true })
// 通过 Browserify 或 Webpack 使用 CommonJS 兼容模块
var Vue = require('vue')
var VueRouter = require('vue-router')
// 不要忘了调用此方法
Vue.use(VueRouter)

路由

通过不同的HRL访问不同的内容

Vue.js路由需要载入vue-router库

CDN

https://unpkg.com/vue-router/dist/vue-router.js

Vue.js + vue-router 可以很简单的实现单页应用

<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<div id="app">
  <h1>Hello App!</h1>
  <p>
    <!-- 使用 router-link 组件来导航. -->
    <!-- 通过传入 `to` 属性指定链接. -->
    <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
    <router-link to="/foo">Go to Foo</router-link>
    <router-link to="/bar">Go to Bar</router-link>
  </p>
  <!-- 路由出口 -->
  <!-- 路由匹配到的组件将渲染在这里 -->
  <router-view></router-view>
</div>

请点赞!因为你们的赞同/鼓励是我写作的最大动力!

欢迎关注达叔小生的简书!

这是一个有质量,有态度的博客

[外链图片转存失败(img-BroAgdip-1563338047364)(https://upload-images.jianshu.io/upload_images/11158618-9ab0d3fef85d80ce?imageMogr2/auto-orient/strip|imageView2/2/w/1240)]

posted @ 2019-07-17 12:34  达达前端  阅读(197)  评论(0编辑  收藏  举报