vue官网-01 基础

vue安装:

1.直接用script引入

  • script标签引入(本地下载vue.js)
  • CDN引入。 eg:
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>

2.npm

// 空文件夹中可以直接安装的
npm install vue    // 最新稳定版

文件:
\node_modules\vue:
dist,src,types,package.json,readme.md等

3.vue-cli
Vue 提供了一个官方的 CLI,为单页面应用 (SPA) 快速搭建繁杂的脚手架。

vue介绍:

Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。
eg:插值,属性,结构控制(if,for,),事件,v-model,组件树思想。

vue实例

  • 创建vue实例
  • 数据和方法
  • 生命周期钩子

创建一个vue实例:

var vm = new Vue({
	// 选项
})

数据和方法:

var vm = new Vue({
	el: '#example',
	data:{
		msg:"我是msg",
	},
	methods:{
	}
})

生命周期钩子:
参考基础知识第8项(在下面)

基础知识:

插值语法:

eg:{{msg}}

  • 响应式
  • vue暴露的属性和方法,eg:$el$data$watch$set等。
  • $watch中this的问题。
  • v-oncev-html='msg'
  • 表达式

mustache // n.胡子;须状物;
英 [mə’stɑ:ʃ];美 [ˈmʌsˌtæʃ, məˈstæʃ]

<div id="app">
    {{msg}}
</div>

<script>
    var app=new Vue({
        el:"#app",
        data:{
            msg:"我是hello world",
        }
    })
    console.log(app.msg);
</script>

当一个 Vue 实例被创建时,它将 data 对象中的所有的属性加入到 Vue 的响应式系统中。当这些属性的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。

现在数据和 DOM 已经被建立了关联,所有东西都是响应式的

响应式是指:在控制台修改app.msg=“lks”,那么页面也是会自动刷新的。eg:

    var data={a:1};
    var vm=new Vue({
        el:"#app",
        data:data,
    })
    // vm.a===data.a   =>true 
    
	// 设置属性也会影响到原始数据
	vm.a = 2
	data.a // => 2

	// ……反之亦然
	data.a = 3
	vm.a // => 3
    
	vm.b=4;
	console.log("vm.b:",vm.b); // 4
	console.log("data.b:",data.b); // undefined
	// 页面上b的值会显示4(现在不会显示了,报错;但是可以打印出来);但是只显示初始化后的值,如果再改变vm.b的值,不会更新视图,已经断开连接了;

值得注意的是只有当实例被创建时 data 中存在的属性才是响应式的。也就是说如果你添加一个新的属性,将不会触发任何视图的更新。

除了数据属性,Vue 实例还暴露了一些有用的实例属性与方法。它们都有前缀 $,以便与用户定义的属性区分开来。

var data = { a: 1 }
var vm = new Vue({
  el: '#example',
  data: data
})

vm.$data === data        // => true
vm.$el === document.getElementById('example')       // => true

// $watch 是一个实例方法
vm.$watch('a', function (newValue, oldValue) {
  // 这个回调将在 `vm.a` 改变后调用,初始化的时候,没有执行的。
})

$watch执行的顺序问题:

vm.a=333;
vm.$watch('a',function(n,o){
    console.log(n);
    console.log(o);
    console.log(this===vm);
})
// $watch是没有执行的;只有vm.a放在$watch后面,那么才会执行;
	// 没有使用箭头函数,this指向vm对象
    vm.$watch('a',function(n,o){
        console.log("新值:",n,"旧值:",o);
        console.log("this指向问题:",this===vm);   // 返回true
        this.test();
    })
/* vm.$watch('a',function(n,o){
         console.log("新值:",n,"旧值:",o);
         console.log("this:",this===vm);
         this.test();
})*/
// 使用了箭头函数,this执行window
vm.$watch('a', n => {
    console.log("this:",this);
    console.log("this===Window:",this===Window); // false
    console.log("this===window:",this===window); // true  window:Window类型。
    console.log("this===this.window:",this===this.window); // true
    console.log("this.vm===vm:",this.vm===vm); // true
    console.log("this.vm:",this.vm); // 就是vm对象
    this.vm.test(); // 执行了
})

扩展:

v-once // 属性
v-html="msg"  // 属性,msg没有花括号

v-once的使用:

<span v-once>这个将不会改变: {{ msg }}</span>  // 一次性的插值

v-html的使用: => 很容易导致 XSS 攻击

// msg 是 "<h2>我是标题</h2>",
<span v-html="msg">我是span标签</span>

msg中的html片段会插入到span中,span中本来的内容被替换掉了(“我是span标签”没有了),效果如下:

<span><h2>我是标题</h2></span>

可以使用js表达式:

{{number+1}}
{{ok?'YES':'NO'}}
<div v-bind:id="'list-'+id"></div>

错误示例:

<!-- 这是语句,不是表达式 -->
{{ var a = 1 }}

<!-- 流控制也不会生效,请使用三元表达式 -->
{{ if (ok) { return message } }}
绑定属性

v-bind:title=“msg”

<span title="msg">鼠标悬浮几秒试试</span>   // msg
<span title="{msg}">鼠标悬浮几秒试试</span> // {msg}
<span title="{{msg}}">鼠标悬浮几秒试试</span> // {{msg}},并且会报错,不认识{{}}
<span v-bind:title="msg">鼠标悬浮几秒试试</span> // 正确,提示:msg的内容
<div v-bind:id="'list-'+id"></div>
<!-- 完整语法 -->
<a v-bind:href="url">...</a>

<!-- 缩写 -->
<a :href="url">...</a>
条件渲染
v-if="seen"
  • v-if="count>1"v-else-if="count>0"v-else
  • 用key管理可复用的元素
  • v-show

v-if 如果想切换多个元素呢?此时可以把一个 元素当做不可见的包裹元素,并在上面使用 v-if。最终的渲染结果将不包含 元素(类似angular中ng-container)。

<div v-if="seen">
    <p> 你能看到我吗?</p>
</div>
<div v-else>
	NO!!!
</div>

app.seen=true/false;

注:v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别。

用 key 管理可复用的元素

eg:此时:共享input,只是更换了placeholder而已

<template v-if="loginType === 'username'">
  <label>Username</label>
  <input placeholder="Enter your username">
</template>
<template v-else>
  <label>Email</label>
  <input placeholder="Enter your email address">
</template>

以下,由于有key,那么input是没有共享的

<template v-if="loginType === 'username'">
  <label>Username</label>
  <input placeholder="Enter your username" key="username-input">
</template>
<template v-else>
  <label>Email</label>
  <input placeholder="Enter your email address" key="email-input">
</template>

// 此时:自己的input值也不会保留了(切换的时候,被清空了)。

v-show:

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

不同的是带有 v-show 的元素始终会被渲染并保留在 DOM 中。v-show 只是简单地切换元素的 CSS 属性 display。

注意,v-show 不支持 元素,也不支持 v-else。

循环渲染
  • 数组的v-for,
  • 对象的v-for
  • 数组未检测变更(数组改变某一项的值或者修改length)
  • 对象未检测变更(增加或者删除属性)(修改属性还是响应式的)
v-for="item in items"
v-for="item of items"  // of也是可以的

加索引:

  <li v-for="(item, index) in items">
     {{ index }} - {{ item.message }}
  </li>

使用key:

<div v-for="item in items" v-bind:key="item.id">
  <!-- 内容 -->
</div>

建议尽可能在使用 v-for 时提供 key,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。

一个对象的 v-for

<ul id="v-for-object" class="demo">
  <li v-for="value in object">
    {{ value }}
  </li>
</ul>
// js:
new Vue({
  el: '#v-for-object',
  data: {
    object: {
      firstName: 'John',
      lastName: 'Doe',
      age: 30
    }
  }
})

你也可以提供第二个的参数为键名:

<div v-for="(value, key) in object">
  {{ key }}: {{ value }}
</div>

第三个参数为索引:

<div v-for="(value, key, index) in object">
  {{ index }}. {{ key }}: {{ value }}
</div>

注:vue不能检测以下数组的变动:
1.当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
2.当你修改数组的长度时,例如:vm.items.length = newLength

var vm = new Vue({
  data: {
    items: ['a', 'b', 'c']
  }
})

vm.items[1] = 'x' // 不是响应性的
vm.items.length = 2 // 不是响应性的

解决第一类问题:

// 方法一:Vue.set
Vue.set(vm.items, indexOfItem, newValue)
vm.$set(vm.items, indexOfItem, newValue)

// 方法二:Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)

解决第二类问题:

vm.items.splice(newLength)

注:

1.this.list[2].title=44444;这样的设置,还是响应式的。
2.angular的*ngFor中,不会存在for循环渲染的问题。

由于 JavaScript 的限制,Vue 不能检测对象属性的添加删除

var vm = new Vue({
  data: {
    a: 1
  }
})
// `vm.a` 现在是响应式的

vm.b = 2
// `vm.b` 不是响应式的

对于已经创建的实例,Vue 不允许动态添加根级别的响应式属性。但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式属性。例如

// 会报错的
vm.$set(vm,'b',333);
vm.$set(vm.$data,'b',333);

报错信息如下:

[Vue warn]: Avoid adding reactive properties to a Vue instance or its root $data at runtime - declare it upfront in the data option.
var vm = new Vue({
  data: {
    userProfile: {
      name: 'Anika'
    }
  }
})


Vue.set(vm.userProfile, 'age', 27) // 
// 或者:
vm.$set(vm.userProfile, 'age', 27)

注:属性key,是带引号的,要不然报错,当变量了。

// 这样添加,不是响应式的,页面不会更新
vm.userProfile.age=333;

有时你可能需要为已有对象赋值多个新属性,比如使用 Object.assign() 或 _.extend()。在这种情况下,你应该用两个对象的属性创建一个新的对象。所以,如果你想添加新的响应式属性,不要像这样:

Object.assign(vm.userProfile, {
  age: 27,
  favoriteColor: 'Vue Green'
})

你应该这样做(创建一个新对象):

vm.userProfile = Object.assign({}, vm.userProfile, {
  age: 27,
  favoriteColor: 'Vue Green'
})

类似于 v-if,你也可以利用带有 v-for 的 来循环渲染一段包含多个元素的内容。

todoItem案例:


<div id="app">
    <form @submit.prevent='addItem'>
        <label>新item</label>
        <input type="text" v-model="newItem">
        <button>新增</button>
    </form>
    <ul>
        <todo-item v-for="(item,index) in list"
                   :title="item.title"
                   :key="item.id"
                   @remove='removeItem($event,index)'>
        </todo-item>
    </ul>
</div>


Vue.component('todo-item', {
    template: `<li>
        {{title}}
        <button @click="$emit('remove','ok')">删除</button>
        </li>`,
    props: ['title']
})


var vm = new Vue({
    el: '#app',
    data: {
        newItem:'',
        newItemId:5,
        list: [
            {id: 1, title: "title1111"},
            {id: 2, title: "title2222"},
            {id: 3, title: "title3333"},
        ]
    },
    methods: {
        addItem(){
            this.list.push({id:this.newItemId++,title:this.newItem})
            this.newItem='';
        },
        removeItem(e,index) {
            console.log(e);
            console.log("removeItem:",index);
            this.list.splice(index,1);
        }
    }
})

事件

v-on:click=“reverseMsg”

<button @click="reverseMsg">逆转消息</button>

// js
 methods:{
     reverseMsg:function(){
         this.msg=this.msg.split("").reverse().join("");
     }
}
<!-- 完整语法 -->
<a v-on:click="doSomething">...</a>

<!-- 缩写 -->
<a @click="doSomething">...</a>
事件修饰符

.stop,.prevent,.capture,.self,.once,.passive

<!-- 阻止单击事件继续传播 -->// 组织冒泡
<a v-on:click.stop="doThis"></a>

<!-- 提交事件不再重载页面 --> // 阻止默认事件(阻止元素发生默认的行为)
<!-- .prevent 修饰符告诉 v-on 指令对于触发的事件调用 `event.preventDefault()` -->
<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>
<div id="app">

    <!--点击 我是按钮 的时候,onClick也会执行;有了self之后,不会了;-->
    <div style="width: 100px;height: 100px;border: 1px solid red;" @click.self="onClick">

        <!--点击 我是按钮 的时候,onClick也会执行,冒泡;有了stop只有,不会了;-->
        <button @click="onBtnClick">我是按钮</button>
        <!--<button @click.stop="onBtnClick">按钮</button>-->


        <form @submit.prevent="onSubmit">
            <!--点击 提交 的时候,会刷新页面;有了revent,就不会了;-->
            <button>提交</button>
        </form>
    </div>

</div>


<script>

    var vm= new Vue({
        el:"#app",
        data:{

        },
        methods:{
            onClick(){
                console.log('onClick触发了');
            },
            onBtnClick(){
                console.log('onBtnClick触发了');
            },
            onSubmit(){
                console.log('onSubmit触发了');
            }
        }
    })
</script>


<!-- 点击事件将只会触发一次 -->
<a v-on:click.once="doThis"></a>

eg:

<button @click.prevent="test();">按钮</button>
按键修饰符

enter,tab,delete,esc,space,up,down,left,right,page-up,page-down,
其中:up,down,left,right才是上下左右的箭头键。

<!-- 只有在 `key``Enter` 时调用 `vm.submit()` -->
<input v-on:keyup.enter="submit">
// 不是上下箭头,就是pageUp和pageDown键

<input v-on:keyup.page-down="onPageDown">
<input v-on:keyup.page-up="onPageUp">
系统修饰键

.ctrl,.alt,.shift,.meta。
这几个键必须配合其他键才会生效,eg:ctrl+c。

鼠标按钮修饰符

.left,.right,.middle

<input type="text" @mouseup.right="onRight">
双向绑定:

v-model=“msg”

<input type="text" v-model="msg">

双向绑定的事件:@input@change@keyup.enter@blur;angular中:ngModelChange
参考:https://blog.csdn.net/zuoyiran520081/article/details/86611608

修饰符:lazy,number,trim

.lazy,.number,.trim。

<!-- 在“change”时而非“input”时更新 -->
<input v-model.lazy="msg" >
<!--如果想自动将用户的输入值转为数值类型,可以给 v-model 添加 number 修饰符-->
<input v-model.number="age" type="number">
<!--自动过滤用户输入的首尾空白字符-->
<input v-model.trim="msg">
生命周期函数
  • 不要使用箭头函数
  • 执行顺序
  • update:改变的变量 必须在html中使用了,才会执行钩子函数

不要在选项属性或回调上使用箭头函数,eg:
created: () => console.log(this.a)
vm.$watch('a', newValue => this.myMethod())
// this的指向改变了!指向window,那么使用this.vm.a是不是就可以打印了???不可以。
因为箭头函数并没有 this,this 会作为变量一直向上级词法作用域查找,直至找到为止。


var vm=new Vue({
    el:"#app",
    data:{
        count:0,
    },
    created(){
        console.log('this:',this); // Vue
        console.log('this:',this===vm); // false
        console.log('this.vm:',this.vm); // undefined
        console.log('this.count',this.count); // 0
    },
    // created:()=>{
    //     console.log('this:',this); // window:Window
    //     console.log('this:',this===window); // true
    //     console.log('this.vm:',this.vm); // undefined
    //     console.log('vm:',vm); // undefined
    //     console.log('created',this.vm.count); // 报错了
    // }
})

vm.$watch('count',(n,o)=>{
    console.log(this); // window:Window
    console.log(n,o); // 3 0
    console.log('this.vm.count',this.vm.count); // 3
    console.log('vm.count',vm.count); // 3
})

vm.count=3;

生命周期函数:create,mount,update,destory
new Vue() // 初始化Vue
beforeCreate,
created,
beforeMount,
mounted,
beforeUpdate,
updated,
beforeDestroy,
destroyed

页面刷新之后,执行:beforeCreate,created,beforeMount,mounted,
修改数据之后,执行:beforeUpdate,updated,
跳转到别的页面,执行:???


<div id="app"></div>
<script src="../vue.js"></script>
<script>
    var vm = new Vue({
        el: "#app",
        data: {
            count: 0,
        },
        methods: {},
        updated() {
            console.log("updated");
        }
    })
    vm.count=6;
</script>

// 此时,beforeUpdate和updated并不执行!!!!
// 只有html中用了变量,那么才会执行update的钩子函数。
概念性东西:指令,参数

指令 (Directives) 是带有 v- 前缀的特殊特性。指令特性的值预期是单个 JavaScript 表达式 (v-for 是例外情况,稍后我们再讨论)。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。

<p v-if="seen">现在你看到我了</p>

一些指令能够接收一个“参数”,在指令名称之后以冒号表示。例如,v-bind 指令可以用于响应式地更新 HTML 特性;
在这里 href 是参数,告知 v-bind 指令将该元素的 href 特性与表达式 url 的值绑定

<a v-bind:href="url">...</a>
计算属性和侦听器

计算属性,侦听属性,方法的区别???

eg:

<div id="example">
  {{ message.split('').reverse().join('') }}
</div>

在这个地方,模板不再是简单的声明式逻辑。你必须看一段时间才能意识到,这里是想要显示变量 message 的翻转字符串。当你想要在模板中多次引用此处的翻转字符串时,就会更加难以处理。

所以,对于任何复杂逻辑,你都应当使用计算属性。
eg:

// html:
<div id="example">
  <p>Original message: "{{ message }}"</p>
  <p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>

// js:
var vm = new Vue({
  el: '#example',
  data: {
    message: 'Hello'
  },
  computed: {
    // 计算属性的 getter
    reversedMessage: function () {
      // `this` 指向 vm 实例
      return this.message.split('').reverse().join('')
    }
  }
})

你可以像绑定普通属性一样在模板中绑定计算属性。Vue 知道 vm.reversedMessage 依赖于 vm.message,因此当 vm.message 发生改变时,所有依赖 vm.reversedMessage 的绑定也会更新。

计算属性缓存 VS 方法:

计算属性:会缓存,如果依赖变量不变化,那么返回值不变;
方法:每次都会重新执行。

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

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

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

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

相比之下,每当触发重新渲染时,调用方法将总会再次执行函数。

计算属性 VS 侦听属性
  • 计算属性:即computed。同时侦听多个值,都可以一个属性搞定。
  • 侦听属性:即watch。如果侦听多个值?写多个侦听?且是重复的代码。
<div id="demo">{{ fullName }}</div>
// js:
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
    }
  }
})

计算属性默认只有 getter ,不过在需要时你也可以提供一个 setter :

11.class与style绑定:

操作元素的 class 列表和内联样式是数据绑定的一个常见需求。因为它们都是属性,所以我们可以用 v-bind 处理它们:只需要通过表达式计算出字符串结果即可。不过,字符串拼接麻烦且易错。因此,在将 v-bind 用于 class 和 style 时,Vue.js 做了专门的增强。表达式结果的类型除了字符串之外,还可以是对象或数组。

html绑定class

class的对象语法:
// 1.单个
<div v-bind:class="{active:isActive}">我是div标签</div>
 
// 2.多个:class名字,可以加引号,也可以不加。
<div v-bind:class="{active:isActive,'text-danger':hasError}">我是div标签</div>
 
// 3. 对象
<div v-bind:class="classObj">我是div标签</div>

此时对应的js为:
data: {
    classObj:{
         active:true,
         'text-danger':true
    }
}

其中:data中不可以使用data的属性的,eg:

data: {
    isRed: true,
    isBlue: true,
    isWeight: true,
    isFz: true,
    classObj2: {
        'red': this.isRed, // 不可以使用this
        fw9: this.isWeight,
        fz14: is.isFz,
    },
},

可以使用计算属性

class的数组语法

1.数组:

直接写:
 <div :class="['active','text-danger']">我是正文</div>
 
 或者:
<div v-bind:class="[activeClass, errorClass]"></div>
// js:
data: {
  activeClass: 'active',
  errorClass: 'text-danger'
}

渲染为:

<div class="active text-danger"></div>

2.三元:

<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
在数组语法中也可以使用对象语法(数组+对象):
<div v-bind:class="[{ active: isActive }, errorClass]"></div>

当在一个自定义组件上使用 class 属性时,这些类将被添加到该组件的根元素上面。这个元素上已经存在的类不会被覆盖。
eg:

// html
<my-component class="baz boo"></my-component>
// js:
Vue.component('my-component', {
  template: '<p class="foo bar">Hi</p>'
})


HTML 将被渲染为:

<p class="foo bar baz boo">Hi</p>

html绑定style

对象语法:
<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: '14px'
  }
}
数组语法:

v-bind:style 的数组语法可以将多个样式对象应用到同一个元素上:

<div v-bind:style="[baseStyles, overridingStyles]"></div>

// html:
<div :style="[style1,style2]">我是style数组的样式</div>

// js:
data:{
    style1:{
        color:'red'
    },
    style2:{
        fontSize:'20px',
    }
},
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值