vue官网-01 基础

文章目录

      • vue安装:
      • vue介绍:
      • vue实例
      • 基础知识:
          • 插值语法:
          • 绑定属性
          • 条件渲染
          • 循环渲染
          • 事件
            • 事件修饰符
            • 按键修饰符
            • 系统修饰键
            • 鼠标按钮修饰符
          • 双向绑定:
            • 修饰符:lazy,number,trim
          • 生命周期函数
          • 概念性东西:指令,参数
          • 计算属性和侦听器
            • 计算属性缓存 VS 方法:
            • 计算属性 VS 侦听属性
      • html绑定class
          • class的对象语法:
          • class的数组语法
          • 在数组语法中也可以使用对象语法(数组+对象):
      • html绑定style
          • 对象语法:
          • 数组语法:

vue安装:

1.直接用script引入

  • script标签引入(本地下载vue.js)
  • CDN引入。 eg:

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 是 "

我是标题

",
<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”

鼠标悬浮几秒试试   // msg
鼠标悬浮几秒试试 // {msg}
鼠标悬浮几秒试试 // {{msg}},并且会报错,不认识{{}}
鼠标悬浮几秒试试 // 正确,提示: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)。

你能看到我吗?

NO!!!

app.seen=true/false;

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

用 key 管理可复用的元素

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



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




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

v-show:

Hello!

不同的是带有 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也是可以的

加索引:

  
  • {{ index }} - {{ item.message }}
  • 使用key:

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

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

    一个对象的 v-for

    • {{ value }}
    // js: new Vue({ el: '#v-for-object', data: { object: { firstName: 'John', lastName: 'Doe', age: 30 } } })

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

    {{ key }}: {{ value }}

    第三个参数为索引:

    {{ index }}. {{ key }}: {{ value }}

    注: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: `
  • {{title}}
  • `
    , 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>
    
     // 阻止默认事件(阻止元素发生默认的行为)
    
    <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>
    
    <div id="app">
    
        
        <div style="width: 100px;height: 100px;border: 1px solid red;" @click.self="onClick">
    
            
            <button @click="onBtnClick">我是按钮button>
            
    
    
            <form @submit.prevent="onSubmit">
                
                <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:

    
    
    按键修饰符

    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@change@keyup.enter@blur;angular中:ngModelChange
    参考:https://blog.csdn.net/zuoyiran520081/article/details/86611608

    修饰符:lazy,number,trim

    .lazy,.number,.trim。

    
    <input v-model.lazy="msg" >
    
    
    <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。

    现在你看到我了

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

    ...
    
    计算属性和侦听器

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

    eg:

    {{ message.split('').reverse().join('') }}

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

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

    // html:
    

    Original message: "{{ message }}"

    Computed reversed message: "{{ reversedMessage }}"

    // 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:
    

    Reversed message: "{{ reversedMessage() }}"

    // js // 在组件中 methods: { reversedMessage: function () { return this.message.split('').reverse().join('') } }

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

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

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

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

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

    直接写:
     
    我是正文
    或者:
    // js: data: { activeClass: 'active', errorClass: 'text-danger' }

    渲染为:

    2.三元:

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

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

    // html
    
    // js:
    Vue.component('my-component', {
      template: '

    Hi

    ' })

    HTML 将被渲染为:

    Hi

    html绑定style

    对象语法:
    data: { activeColor: 'red', fontSize: 30 }

    直接绑定到一个样式对象通常更好,这会让模板更清晰:

    data: { styleObject: { color: 'red', fontSize: '14px' } }
    数组语法:

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

    // html:
    我是style数组的样式
    // js: data:{ style1:{ color:'red' }, style2:{ fontSize:'20px', } },

    你可能感兴趣的:(vue-官网)