Vue笔记

Vue笔记

Vue的指令

  • v-for 循环
<li v-for="item in list">{{ item }}</li>
<!-- 循环 list,将list里面的每一项赋值给 item -->
  • v-on 事件绑定 (执行事件的函数要写在 Vue 实例中的 methods 中,简写@,如:@click)
<button v-on:click="handleBtnClick">提交</button>
<!-- handleBtnClick 方法要写在 Vue 实例的 methods 中 -->
  • v-model 在表单控件或者组件上创建双向绑定
<input type="text" v-model="inputValue" />
<!-- inputValue 是 Vue 实例中 data 里的值 -->
  • v-bind 数据绑定 (简写直接冒号)
<todo-item v-bind:content="item" v-for="item in list"></todo-ittem>
<!-- 父组件循环 list,将 list 的每一项赋给 item,然后子组件将 item 的值赋给 content -->

例子1:简单的 todolist

<div id="app">
    <input type="text" v-model="inputValue" />
    <button v-on:click="handleBtnClick">提交</button>
    <ul>
        <li v-for="item in list">{{ item }}</li>
    </ul>
</div>

<script>
    const app = new Vue({
        el: '#app',
        data: {
            list: [],
            inputValue: ''
        },
        methods: {
            handleBtnClick: function () {
                this.list.push(this.inputValue)
                this.inputValue = ''
            }
        } 
    })
</script>

例子2: todolist组件化——全局组件

<div id="app">
    <input type="text" v-model="inputValue" />
    <button v-on:click="handleBtnClick">提交</button>
    <ul>
        <!--  <li v-for="item in list">{{ item }}</li> -->
        <todo-item v-bind:content="item" v-for="item in list"></todo-ittem>
    </ul>
</div>

<script>
    // 全局组件  
    Vue.component('TodoItem', {
        props: ['content'],
        template: `<li>{{content}}</li>`
    })
    const app = new Vue({
        el: '#app',
        data: {
            list: [],
            inputValue: ''
        },
        methods: {
            handleBtnClick: function () {
                this.list.push(this.inputValue)
                this.inputValue = ''
            }
        } 
    })
</script>

例子3: todolist组件化——局部组件

<div id="app">
    <input type="text" v-model="inputValue" />
    <button v-on:click="handleBtnClick">提交</button>
    <ul>
        <!--  <li v-for="item in list">{{ item }}</li> -->
        <todo-item v-bind:content="item" v-for="item in list"></todo-ittem>
    </ul>
</div>

<script>

    // 局部组件
    const TodoItem = {
        props: ['content'],
        template: `<li>{{content}}</li>`
    }
    const app = new Vue({
        el: '#app',
        components: {
            TodoItem
        },
        data: {
            list: [],
            inputValue: ''
        },
        methods: {
            handleBtnClick: function () {
                this.list.push(this.inputValue)
                this.inputValue = ''
            }
        } 
    })
</script>

例子3: todolist组件化——父子组件的相互传值

子组件可以通过 $emit 向外触发事件

<div id="app">
    <input type="text" v-model="inputValue" />
    <button v-on:click="handleBtnClick">提交</button>
    <ul>
        <!--  <li v-for="item in list">{{ item }}</li> -->
        <todo-item v-bind:content="item" 
                    v-for="(item, index) in list"
                    @delete="handleItemDelete"
                    v-bind:index="index"
        ></todo-ittem>
    </ul>
</div>

<script>
    
    // 局部组件
    const TodoItem = {
        props: ['content', 'index'],
        template: `<li @click='handleItemClick'>{{content}}</li>`,
        methods: {
            handleItemClick: function() {
                this.$emit('delete', this.index)
                // $emit 向外触发事件
            }
        }
    }
    const app = new Vue({
        el: '#app',
        components: {
            TodoItem
        },
        data: {
            list: [],
            inputValue: ''
        },
        methods: {
            handleBtnClick: function () {
                this.list.push(this.inputValue)
                this.inputValue = ''
            },
            handleItemDelete: function (index) {
                this.list.splice(index, 1)
            }
        } 
    })
</script>

vue 的生命周期函数

<div id="app"></div>
<script>
    const vm = new Vue({
        el: '#app',
        template: `<div>{{ test }}</div>`,
        data: {
            test: 'hello world'
        },
        beforeCreate() {
            console.log('beforeCreate')
        },
        created() {
            console.log('created')
        },
        beforeMount() {
            console.log('beforeMount')
        },
        mounted() {
            console.log('mounted')
        },
        beforeDestroy() {
            console.log('beforeDestroy')
        },
        destroyed() {
            console.log('destroyed')
        },
        beforeUpdate() {
            console.log('beforeUpdate')
        },
        updated() {
            console.log('updated')
        },
    })
</script>

计算属性,方法和监听器

| 如果某个功能可以用 计算属性,方法和监听器 三种方式实现,优先选择计算属性

  • 计算属性
    计算属性内置缓存,没有改变计算需要用到的变量的值时,就不会重新计算
<div id="app">
    {{ fullName }}
    {{ age }}
</div>

<script>
    const vm = new Vue({
        el: '#app',
        data: {
            firstName: 'Xianggang',
            lastName: 'Diao',
            age: 21
        },
        computed: { // 计算属性(内置缓存)
            fullName() {
                console.log('计算了一次') // 没有用到 age,即便修改age的值,也不会重新计算,只有修改 firstName和lastName的时候,才会重新计算
                return `${this.firstName} ${this.lastName}`
            },
        }
    })
</script>
  • 方法(计算属性的方法实现)
    没有内置缓存,改变任意值都会重新计算
<div id="app">
    {{ fullName() }} <!-- 调用方法,加括号 -->
    {{ age }}
</div>

<script>
    const vm = new Vue({
        el: '#app',
        data: {
            firstName: 'Xianggang',
            lastName: 'Diao',
            age: 21
        },
        methods: {
            fullName(){
                console.log('计算了一次')
                return `${this.firstName} ${this.lastName}`
            } 
        }
    })
</script>
  • 监听器
<div id="app">
    {{ fullName }}
    {{ age }}
</div>

<script>
    const vm = new Vue({
        el: '#app',
        data: {
            firstName: 'Xianggang',
            lastName: 'Diao',
            fullName: 'Xianggang Diao',
            age: 21
        },
        watch: {
            // 监听 firstName 和 lastName, 一旦firstName 和 lastName改变,就重新计算fullName
            firstName() {
                console.log('计算了一次')
                this.fullName = `${this.firstName} ${this.lastName}`
            },
            lastName() {
                console.log('计算了一次')
                this.fullName = `${this.firstName} ${this.lastName}`
            }
        }
    })
</script>

计算属性的 getter 和 setter

<div id="app">
    {{ fullName }}
    {{ age }}
</div>

<script>
    const vm = new Vue({
        el: '#app',
        data: {
            firstName: 'Xianggang',
            lastName: 'Diao',
            age: 21
        },
        computed: {
            fullName: {
                get() {
                    return `${this.firstName} ${this.lastName}`
                },
                set(value) {
                    console.log(value)
                    const arr = value.split(' ')
                    this.firstName = arr[0]
                    this.lastName = arr[1]
                }
            },
        }
    })
</script>

Vue的条件渲染

在 Vue 中通过 v-ifv-show 可以控制元素是否显示,他们的区别是:v-if 的条件为 false 时,DOM 根本不会渲染元素,及根本不存在此元素,v-show 的条件是 false 时,只是将它CSS设成了 display: none ,因此v-show 的性能要高一些

<div id="app">
    <div v-if="show">{{ message }}</div>
    <div v-show="show">{{ message }}</div>
</div>

<script>
    const vm = new Vue({
        el: '#app',
        data: {
            show: false,
            message: 'hello World'
        }
    })
</script>

v-ifv-else 指令的使用

<div id="app">
    <div v-if="show">{{ message }}</div>
    <div v-else>Bye World</div>
</div>

<script>
    const vm = new Vue({
        el: '#app',
        data: {
            show: false,
            message: 'hello World'
        }
    })
</script>

注意 v-if 和 v-else 之间不能有标签
错误举例

<div id="app">
    <div v-if="show">{{ message }}</div>
    <div>v-if 和 v-else 之间不能有标签,会报错</div>
    <div v-else>Bye World</div>
</div>

<script>
    const vm = new Vue({
        el: '#app',
        data: {
            show: false,
            message: 'hello World'
        }
    })
</script>

连写多个 v-ifv-else-if

<div id="app">
    <div v-if="show === 'a'">This is a</div>
    <div v-else-if="show === 'b'">This is b</div>
    <div v-else>This is others</div>
</div>

<script>
    const vm = new Vue({
        el: '#app',
        data: {
            show: 'a',
        }
    })
</script>

Vue 数组的注意事项

在 Vue 中使用数组时要注意,不要用更改数组具体的某一项来改变数组,如:list[0] = 'hello',因为 Vue 会将数组的某一项进行封装,实际使用的不再是你定义时的东西了,数组的每一项都是一个 Vue 封装的对象。
想要修改数组的某一项时,要使用 Vue 提供的方法 pop, splice, shift, unshift, sort, push, reserve
也可以用 set 方法改变值:

// 将数组 userInfo 中的 第二项 的值改成 5
Vue.set(vm.userInfo, 1, 5)
// 或者是
vm.$set(vm.userInfo, 1, 5)

/*
     <div id="app">
        <template v-for="(value, key, index) of userInfo">
            <div>{{ value }} --- {{ key }}</div>
            <span>{{ index }}</span>
        </template>
    </div>
 
    <script>
        const vm = new Vue({
            el: '#app',
            data: {
                userInfo: {
                    name: 'diao',
                    age: '21',
                    sex: 'male'
                }
            }
        })
    </script>
*/
// 对对象也适用
// 给 userInfo 对象添加一条数据,键为:'address', 值为 'beijing'
Vue.set(vm.userInfo, 'address', 'beijing')
// 把 userInfo 对象中键为:'name' 的值改为 'li'
vm.$set(vm.userInfo, 'name', 'li')

Vue 的一些注意事项

h5规定在 table 标签下要有 tbody,tbody下面要有 tr,因此在某些情况下,使用Vue的组件会导致DOM结构和设想的不一致,可以使用 is 来解决

<div id="app">
    <table>
        <tbody>
            <tr is="row"></tr>
        </tbody>
    </table>
</div>

<script>
    Vue.component('row', {
        template: `<tr><td>this is row</td></tr>`
    })
    const vm = new Vue({
        el: '#app'
    })
</script>

在 Vue 中,根组件是可以直接使用 data 对象,但是子组件不能使用 data 对象,应该使用 data方法,该方法返回一个对象来‘定义’变量

<div id="app">
        <table>
            <tbody>
                <tr is="row"></tr>
            </tbody>
        </table>
</div>

<script>
    Vue.component('row', {
        data() {
            return {
                content: '不能直接使用,必须是个方法,返回对象'
            }
        },
        template: `<tr><td>{{ content }}</td></tr>`
    })
    const vm = new Vue({
        el: '#app',
        data: {
            text: '可以直接使用'
        }
    })
</script>

在 Vue 中获取 DOM 节点,可以使用 ref 引用来获取。$refs 可以获取全部的引用

<div id="app">
    <div 
        ref='hello'
        @click="handleClick"
    >
        hello world
    </div>
</div>

<script>
    const vm = new Vue({
        el: '#app',
        methods: {
            handleClick() {
                const el = this.$refs.hello
                console.log(el.innerHtml) // hello world
            }
        }
    })
</script>

父组件上使用 ref 获取到的是 DOM 元素,子组件上使用 ref 获取到的是子组件的引用

<div id="app">
    <counter ref="one" @change="handleChange"></counter>
    <counter ref="two" @change="handleChange"></counter>
    <div>{{ total }}</div>
</div>

<script>
    Vue.component('counter', {
        template: `<div @click="handleClick">{{ number }}</div>`,
        data() {
            return {
                number: 0
            }
        },
        methods: {
            handleClick() {
                this.number ++
                this.$emit('change')
            }
        }
    })
    const vm = new Vue({
        el: '#app',
        data: {
            total: 0
        },
        methods: {
            handleChange() {
                const one = this.$refs.one.number
                const two = this.$refs.two.number
                this.total = one + two
            }
        }
    })
</script>

父子组件之间的传值

  • 父组件通过属性的方式向子组件传值
    父组件可以向子组件传递参数,但是子组件只能使用此参数,不能修改,这是 Vue 单项数据流的概念
  • 子组件通过向外触发事件,通过事件参数的方式传值
<!-- 父组件向子组件传值 -->
<div id="app">
    <counter :count="0"></counter>
    <counter :count="1"></counter>
</div>

<script>
    const counter = {
        props: ['count'],
        data() {
            return {
                number: this.count
            }
        },
        template: `<div @click="handleClick">{{ number }}</div>`,
        methods: {
            handleClick() {
                this.number ++
            }
        }
    }
    const vm = new Vue({
        el: '#app',
        components: {
            counter
        }
    })
</script>

<!-- 子组件向父组件传值 -->
<div id="app">
    <counter :count="0"  @change="handleChange"></counter>
    <counter :count="1"  @change="handleChange"></counter>
    <div>{{ total }}</div>
</div>

<script>
    const counter = {
        props: ['count'],
        data() {
            return {
                number: this.count
            }
        },
        template: `<div @click="handleClick">{{ number }}</div>`,
        methods: {
            handleClick() {
                this.number  = this.number + 2
                this.$emit('change', 2)
            }
        }
    }
    const vm = new Vue({
        el: '#app',
        data: {
            total: 1
        },
        components: {
            counter
        },
        methods: {
            handleChange(step) {
                this.total += step
            }
        }
    })
</script>

参数校验

<div id="app">
    <child :content="'hell'"></child>
</div>

<script>
    Vue.component('child', {
        props: { 
            content: String, // 子组件对父组件传递的参数进行校验(约束),这里要求父组件传过来的 content 必须是一个 string 
            test1: [String, Number], // 传的参数可以是 string 也可以是 Number,
            test2: {
                type: String,
                required: false, // 为 true 时,参数必传
                default: 'default value', // 没传参数时,显示此值
                validator(value) {
                    return (value.length > 5) // 传递的 test2 这个参数长度必须大于5
                },
            }
        },
        template: `<div>{{ content }}</div>`
    })
    const vm = new Vue({
        el: '#app',
        
    })
</script>

给组件添加一个原生的事件

使用 v-on:click.native 给组件添加原生事件

<div id="app">
    <child @click.native="handleClick"></child>
</div>

<script>
    Vue.component('child', {
        template: `<div>Child</div>`
    })
    const vm = new Vue({
        el: '#app',
        methods: {
            handleClick() {
                alert('click')
            }
        }
    })
</script>

或者是使用向外触发事件

<div id="app">
    <child @click="handleClick"></child>
</div>

<script>
    Vue.component('child', {
        template: `<div @click="handleChildClick">Child</div>`,
        methods: {
            handleChildClick() {
                alert('child click')
                this.$emit('click')
            }
        }
    })
    const vm = new Vue({
        el: '#app',
        methods: {
            handleClick() {
                alert('click')
            }
        }
    })
</script>

运用总线模式(Bus/总线/发布订阅模式/观察者模式)在非父子组件之间传值

<div id="app">
    <child content = "Xianggang"></child>
    <child content = "Diao"></child>
</div>
<script>
    Vue.prototype.bus = new Vue()
    Vue.component('child', {
        data: function(){
            return {
                selfContent: this.content
            }
        },
        props: {
            content: String
        },
        template: `<div @click = "handleClick">{{ selfContent }}</div>`,
        methods: {
            handleClick: function() {
                this.bus.$emit('change', this.selfContent)
            }
        },
        mounted: function() {
            var _this = this
            this.bus.$on('change', function (msg) {
                _this.selfContent = msg
            })
        }
    })
    const vm = new Vue({
        el: '#app',
        methods: {

        }
    })
</script>

作用域插槽

固定写法:<template solt-scope=""></template>

<div id="app">
    <child>
        <template slot-scope="props"> <!-- slot-scope后面的随便取名 -->
            <h1>{{ props.item }}</h1>
        </template>
    </child>
</div>
<script>
    Vue.component('child', {
        data: function(){
            return {
                list: [1, 2, 3, 4]
            }
        },
        template: `<div>
                     <ul>
                        <slot
                            v-for="item of list"
                            :item = item
                        >
                            
                        </slot>
                     </ul> 
                   </div>`,
        
    })
    const vm = new Vue({
        el: '#app'
    })
</script>

动态组件

点击按钮切换组件的 v-if 实现方式

<div id="app">
    <child-one
        v-if="type === 'child-one'"
    ></child-one>
    <child-two
        v-if="type === 'child-two'"    
    ></child-two>
    <button @click="hadleBtnClick">change</button>
</div>
<script>
    Vue.component('child-one', {
        template: `<div>child one</div>`,
        
    })
    Vue.component('child-two', {
        template: `<div>child two</div>`,
        
    })
    const vm = new Vue({
        el: '#app',
        data: {
            type: 'child-one'
        },
        methods: {
            hadleBtnClick() {
                this.type = this.type === 'child-one' ? 'child-two' : 'child-one'
            }
        }
    })
</script>

动态组件的实现方式
会根据:is里面的类型动态加载组件,通过在组件中加入 v-once 指令,可以使组件在第二次被加载时直接从内存中读取,从而大大提高效率

<div id="app">
    <!-- vue中 <component></component> 就是动态组件-->
    <component :is="type"></component>
    <!-- <child-one
        v-if="type === 'child-one'"
    ></child-one>
    <child-two
        v-if="type === 'child-two'"    
    ></child-two> -->
    <button @click="hadleBtnClick">change</button>
</div>

<script>
    Vue.component('child-one', {
        template: `<div v-once>child one</div>`,
        
    })
    Vue.component('child-two', {
        template: `<div v-once>child two</div>`,
        
    })
    const vm = new Vue({
        el: '#app',
        data: {
            type: 'child-one'
        },
        methods: {
            hadleBtnClick() {
                this.type = this.type === 'child-one' ? 'child-two' : 'child-one'
            }
        }
    })
</script>

CSS过渡效果

Vue中的过渡动画使用<transition></transition>包裹,不管是里面的动态组件还是 v-if 或是 v-show 都可以实现,在 transition 标签中没加 name 属性时,默认是 v-enter 或是 v-leave······,加了 name 属性后,就是 属性-enter 或是 属性-leave······,如下面例子就是 fade-enter

<head>
    <style>
        .fade-enter, .fade-leave-to {
            opacity: 0;
        }
        .fade-enter-active, .fade-leave-active {
            transition: all 3s;
        }
    </style>
</head>
<body>
<div id="app">
    <transition name="fade">
            <div v-if="show">hello world</div>
    </transition>
    <button @click="hadleBtnClick">change</button>
</div>

<script>
    const vm = new Vue({
        el: '#app',
        data: {
            show: true
        },
        methods: {
            hadleBtnClick() {
                this.show = !this.show
            }
        }
    })
</script>

过渡动画的自定义class

<head>
    <style>
        @keyframes bounce-in {
            0% {
                transform: scale(0);
            }
            50% {
                transform: scale(1.5);
            }
            100% {
                transform: scale(1);
            }
        }
        .active {
            transform-origin: left center;
            animation: bounce-in 1s;
        }
        .leave {
            transform-origin: left center;
            animation: bounce-in 1s reverse;
        }
    </style>
</head>
<body>
<div id="app">
    <transition name="fade"
                enter-active-class="active"
                leave-active-class="leave"
    >
            <div v-if="show">hello world</div>
    </transition>
    <button @click="hadleBtnClick">change</button>
</div>

<script>
    const vm = new Vue({
        el: '#app',
        data: {
            show: true
        },
        methods: {
            hadleBtnClick() {
                this.show = !this.show
            }
        }
    })
</script>

JS 动画

运用 transition 标签的钩子函数实现 JS 动画

<head>
    <style>
        @keyframes bounce-in {
            0% {
                transform: scale(0);
            }
            50% {
                transform: scale(1.5);
            }
            100% {
                transform: scale(1);
            }
        }
        .active {
            transform-origin: left center;
            animation: bounce-in 1s;
        }
        .leave {
            transform-origin: left center;
            animation: bounce-in 1s reverse;
        }
    </style>
</head>
<body>
<div id="app">
    <transition @before-enter="handleBeforeEnter"
                @enter="handleEnter"
                @after-enter="handleAfterEnter"
    >
            <div v-if="show">hello world</div>
    </transition>
    <button @click="hadleBtnClick">change</button>
</div>
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            show: true
        },
        methods: {
            hadleBtnClick() {
                this.show = !this.show
            },
            handleBeforeEnter(el) {
                console.log('handleBeforeEnter')
                el.style.color = 'red'
            },
            handleEnter(el, done){
                console.log('handleEnter')
                setTimeout( () => {
                    el.style.color = 'green'
                    setTimeout(done, 4000)
                }, 2000)
            },
            handleAfterEnter(el) {
                console.log('handleAfterEnter')
                el.style.color = 'black'
            }

        }
    })
</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值