欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

荐 vue基础及高级用法(一)

程序员文章站 2022-09-14 11:43:07
1. 插值表达式{{xxx}}的形式,可以是值,也可以是表达式(不能是 js 语句,比如if、for)

{{msg}}

{{ok? '1':'2'}}

var app = new Vue({ el: '#app', data: { msg: 'Hello Vue!', ok: true }})展示效果2. 指...

1. 插值表达式

{{xxx}}的形式,可以是值,也可以是表达式(不能是 js 语句,比如if、for)

<div id="app">
    <p>{{msg}}</p>
    <p>{{ok? '1':'2'}}</p>
</div>
var app = new Vue({
  el: '#app',
  data: {
    msg: 'Hello Vue!',
    ok: true
  }
})

展示效果
荐
                                                        vue基础及高级用法(一)

2. 指令

v-cloak 指令 :直到编译结束显示

<div v-cloak>
  {{ message }}
</div>
[v-cloak] {
  display: none;
}

v-text 指令 :用于更新 html 标签里的内容

<div id="app">
    <p v-text="msg"></p>
    <!-- 和下面的一样 -->
    <p>{{msg}}</p>
</div>
var app = new Vue({
  el: '#app',
  data: {
    msg: 'message'
  }
})

效果展示

荐
                                                        vue基础及高级用法(一)

v-html 指令 :用于更新并解析 html 标签(不安全)

在网站上动态渲染任意 HTML 是非常危险的,因为容易导致 XSS 攻击。只在可信内容上使用 v-html

效果展示

<div id="app">
    <p v-html="msg"></p>
</div>
var app = new Vue({
    el: '#app',
    data: {
        msg: '<span style="color:red">红色字体</span>'
    }
})

荐
                                                        vue基础及高级用法(一)

v-bind 指令 :动态属性绑定

<div id="app">
    <p v-bind:id="pid">动态属性 id</p>
    <p :id="aid">简写形式</p>
</div>
var app = new Vue({
    el: '#app',
    data: {
        pId: 'pid',
        aId: 'aid'
    }
})
class与style
<div id="app">
    <p :class="{ black: isBlack, yellow: isYellow }">使用 class</p>
    <p :class="[black, yellow]">使用 class (数组)</p>
    <p :style="styleData">使用 style</p>
</div>
var app = new Vue({
    el: '#app',
    data() {
        return {
            isBlack: true,
            isYellow: true,

            black: 'black',
            yellow: 'yellow',

            styleData: {
                fontSize: '40px', // 转换为驼峰式
                color: 'red',
                backgroundColor: '#ccc' // 转换为驼峰式
            }
        }
    }
})

v-if、v-else-if、v-else 指令 :有条件地渲染元素

<div id="app">
    <p v-if="type === 'a'">A</p>
    <p v-else-if="type === 'b'">B</p>
    <p v-else-if="type === 'c'">C</p>
    <p v-else>other</p>
</div>
var app = new Vue({
    el: '#app',
    data() {
        return {
            type: 'a'
        }
    }
})

v-show 指令 :有条件地控制css display显示或隐藏元素

<div id="app">
    <p v-show="type === 'a'">A by v-show</p>
    <p v-show="type === 'b'">B by v-show</p>
</div>
var app = new Vue({
    el: '#app',
    data() {
        return {
            type: 'a'
        }
    }
})
v-if 与 v-show 的使用场景

频繁切换,使用 v-show 较好;
运行时条件很少改变,则使用 v-if 较好。

v-for 指令 :循环渲染元素

  • 不要把 v-if 和 v-for 同时用在同一个元素上。
<div id="app">
    <p>遍历数组</p>
    <ul>
        <li v-for="(item, index) in listArr" :key="item.id">
            {{index}} - {{item.id}} - {{item.title}}
        </li>
    </ul>

    <p>遍历对象</p>
    <ul >
        <li v-for="(val, key, index) in listObj" :key="key">
            {{index}} - {{key}} -  {{val.title}}
        </li>
    </ul>
</div>
var app = new Vue({
    el: '#app',
    data() {
        return {
            flag: false,
            listArr: [
                { id: 'a', title: '标题1' }, // 数据结构中,最好有 id ,方便使用 key
                { id: 'b', title: '标题2' },
                { id: 'c', title: '标题3' }
            ],
            listObj: {
                a: { title: '标题1' },
                b: { title: '标题2' },
                c: { title: '标题3' },
            }
        }
    }
})

荐
                                                        vue基础及高级用法(一)

为什么要有key,且不用index(即数组的下标)来作为key。

虚拟dom中,diff算法会根据selkey来判断节点是否可以复用。

荐
                                                        vue基础及高级用法(一)

v-on 指令 :绑定监听事件

  • event 是原生的。
  • 事件被挂载到当前元素,和 DOM 事件一样。
用 vue 绑定的事件,组建销毁时会自动解绑。
自己绑定的事件,需要自己销毁!!!
<div id="app">
    <p>{{num}}</p>
    <button v-on:click="increment1">+1</button>
    <button @click="increment1">简写形式</button>
    <button @click="increment2(2, $event)">+2</button>
</div>
var app = new Vue({
    el: '#app',
    data() {
        return {
            num: 0
        }
    },
    methods: {
        increment1(event) {
            console.log(event) // 是原生的 event 对象
            console.log(event.target) // 注意,事件是被注册到当前元素的,和 React 不一样
            this.num++
        },
        increment2(val, event) {
            this.num = this.num + val
        },
        loadHandler() {
            // do some thing
        }
    },
    mounted() {
        window.addEventListener('load', this.loadHandler)
    },
    beforeDestroy() {
        //【注意】用 vue 绑定的事件,组建销毁时会自动被解绑
        // 自己绑定的事件,需要自己销毁!!!
        window.removeEventListener('load', this.loadHandler)
    }
})

v-model 指令 :表单数据的双向绑定

修饰符
  • .lazy - 取代 input 监听 change 事件
  • .number - 输入字符串转为有效的数字
  • .trim - 输入首尾空格过滤
表单用法
<div id="app">
    <p>输入框: {{name}}</p>
    <input type="text" v-model.trim="name"/>
    <input type="text" v-model.lazy="name"/>
    <input type="text" v-model.number="age"/>

    <p>多行文本: {{desc}}</p>
    <textarea v-model="desc"></textarea>
    <!-- 注意,<textarea>{{desc}}</textarea> 是不允许的!!! -->

    <p>复选框 {{checked}}</p>
    <input type="checkbox" v-model="checked"/>

    <p>多个复选框 {{checkedNames}}</p>
    <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>

    <p>单选 {{gender}}</p>
    <input type="radio" id="male" value="male" v-model="gender"/>
    <label for="male"></label>
    <input type="radio" id="female" value="female" v-model="gender"/>
    <label for="female"></label>

    <p>下拉列表选择 {{selected}}</p>
    <select v-model="selected">
        <option disabled value="">请选择</option>
        <option>A</option>
        <option>B</option>
        <option>C</option>
    </select>

    <p>下拉列表选择(多选) {{selectedList}}</p>
    <select v-model="selectedList" multiple>
        <option disabled value="">请选择</option>
        <option>A</option>
        <option>B</option>
        <option>C</option>
    </select>
</div>
var app = new Vue({
    el: '#app',
    data() {
        return {
            name: '双越',
            age: 18,
            desc: '自我介绍',

            checked: true,
            checkedNames: [],

            gender: 'male',

            selected: '',
            selectedList: []
        }
    }
})
拓展:v-model实现原理
  • v-model的本质是一个语法糖。
  • v-model在组件中不建议使用,自行设计即可。
<input v-model="sth" />
第一行的代码其实只是第二行的语法糖
<input v-bind:value="sth" v-on:input="sth = $event.target.value" />
然后第二行代码还能简写成这样:
<input :value="sth" @input="sth = $event.target.value" />
如果是复选框
<input type="checkbox" :checked="status" @change="status = $event.target.checked" />

原理:每当输入框内容发生变化时,就会触发oninput,把最新的value传递给 绑定的值。

v-slot 指令 :插槽,通过父组件决定子组件模板显示

普通插槽

father 模板:

<child>
  <p>yy</p>
</child>

child 模板:

<div>
  <P>Hello</P>
  <slot>父组件没有提供内容的默认值</slot>
</div>

最终的效果相当于

<div>
  <P>Hello</P>
  <p>yy</p>
</div>
具名插槽

父组件在 <template> 元素上使用 v-slot

<body-content>
  <template v-slot:header>
  <!-- v-slot 缩写 -->
  <!-- <template #header> -->
    <div class="header">header</div>
  </template>
  <template v-slot:footer>
    <div class="footer">footer</div>
  </template>
</body-content>

子组件通过 name 属性,定义 的名字

<div>
  <slot name="header"></slot>
  <div class='content'>content</div>
  <slot name="footer"></slot>
</div>
v-slot 只能添加在 <template> 上,以下情况例外
当只有默认插槽时,可以把 v-slot 直接用在组件上
<current-user v-slot:default="slotProps">
  {{ slotProps.user.firstName }}
</current-user>
作用域插槽

父组件用子组件的数据填充插槽

<div id="app">
    <current-user>
        <template v-slot:default="slotProps">
            子组件传递的姓名{{ slotProps.user }} 年龄{{ slotProps.age}}
        </template>
    </current-user>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    Vue.component('current-user', {
        template: `
        <span>
        <slot v-bind:user="user" age="250">
            {{ user }}
        </slot>
        </span>
        `,
        data: function() {
            return {
                user: '姓名'
            };
        }
    })
    const app = new Vue({
        el: '#app',
    });
</script>

3. 数据

computed 计算属性

计算属性的结果会被缓存,依赖的data变化才会重新计算。

<div id="app">
    <p>num {{num}}</p>
    <p>num {{num}}</p>
    <p>double1 {{double1}}</p>
    <p>double1 {{double1}}</p>
    <input v-model="double2"/>
</div>
var app = new Vue({
    el: '#app',
    data:{
        num: 20
    },
    computed: {
        double1() {
            console.log('double1')
            return this.num * 2
        },
        double2: {
            get() {
                console.log('double2get')
                return this.num * 2
            },
            set(val) {
                console.log('double2set')
                this.num = val/2
            }
        }
    }
})

watch 监听属性

监听数据的变化。

<div id="app">
    <input v-model="name"/>
    <input v-model="info.city"/>
</div>
    var app = new Vue({
        el: '#app',
        data() {
            return {
                name: '双越',
                info: {
                    city: '北京'
                }
            }
        },
        watch: {
            name(oldVal, val) {
                // eslint-disable-next-line
                console.log('watch name', oldVal, val) // 值类型,可正常拿到 oldVal 和 val
            },
            info: {
                handler(oldVal, val) {
                    // eslint-disable-next-line
                    console.log('watch info', oldVal, val) // 引用类型,拿不到 oldVal 。因为指针相同,此时已经指向了新的 val
                },
                deep: true // 深度监听
            }
        }
    })

4. 生命周期

荐
                                                        vue基础及高级用法(一)
常用

  • beforeCreate::在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。(服务器端渲染期间被调用)
  • created:可以访问到data,(服务器端渲染期间被调用)
  • beforeMount : 在挂载开始之前被调用:相关的渲染函数首次被调用
  • mounted : el 被新创建的 vm.$el 替换, 挂载成功
一般在此时调用ajax,js是单线程的,dom加载完才会进行异步操作
// mounted 不保证子组件都被挂载。如果等到视图渲染完毕,可以在 mounted 内部使用 vm.$nextTick:
mounted: function () {
    this.$nextTick(function () {
        // Code that will run only after the
        // entire view has been rendered
    })
}
  • beforeUpdate : 数据更新时调用
  • updated :组件 DOM 已经更新完毕
// updated 不保证子组件都被重绘。如果等到视图重绘完毕,可以在 updated 里使用 vm.$nextTick:
updated: function () {
    this.$nextTick(function () {
        // Code that will run only after the
        // entire view has been re-rendered
    })
}
  • beforeDestory():组件销毁前。
一般在此时解绑自定义事件和清除定时器。
  • destoryed():组件销毁之后

不常用

  • activated:当组件激活的时候调用
  • deactivated:当组件停用的时候调用
  • errorCaptured:当捕获一个来自子孙组件的错误时被调用。(服务器端渲染期间被调用)

拓展:父子组件的生命周期

  • 加载渲染过程

父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted

  • 子组件更新过程

父beforeUpdate->子beforeUpdate->子updated->父updated

  • 父组件更新过程

父beforeUpdate->父updated

  • 销毁过程

父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

5. 组件间的通讯

常见的有三种方式:父子间传值、非父子间自定义事件传值、vuex。

  • 父传子 用 props
<div id="app">
    <div>{{pmsg}}</div>
    <menu-item :title='ptitle' :content='ptitle'></menu-item>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
    //父组件向子组件传值-基本使用
    Vue.component('menu-item', {
        props: ['title', 'content'],
        data: function() {
            return {
                msg: '子组件本身的数据'
            }
        },
        template: `
            <div>
                <p>{{msg}}</p>
                <p>{{title}}</p>
                <p>{{content}}</p>
            </div>`
    });
    var vm = new Vue({
        el: '#app',
        data: {
            pmsg: '父组件中内容',
            ptitle: '动态绑定属性'
        }
    });
</script>

  • 子传父 用 $emit

子组件写法
this.$emit(‘fa’, this.num)

父组件写法
<button-add @fa=“getNum”>

<div id="app">
    <div>{{sonNum}}</div>
    <!--    vue定义好的组件,可以重复使用·-->
    <button-add @fa="getNum"></button-add>
</div>
<!--引入vue-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    // 注册全局对象,要写在vue实例的上面
    Vue.component('button-add', {
        data: function () {
            return {
                num: 0
            }
        },
        template: `<button @click="add">{{num}}</button>`,
        methods: {
            add: function () {
                this.num = this.num + 1
                this.$emit('fa', this.num)
            }
        }
    })
    // 创建vue实例
    var vm = new Vue({
        el: '#app',
        data: {
            sonNum: 0
        },
        methods: {
            getNum: function (son) {
                this.sonNum = son
            }
        }
    })
</script>
  • 非父子组件(兄弟组件),需要创建新的vue实例来自定义事件

用法

  1. 创建一个新的vue对象
var newvue = new Vue()
  1. 触发事件
newvue.$emit('自定义事件名', 参数)
  1. 监听事件
newvue.on('自定义事件名', 触发方法名)
  1. 销毁事件:需要自行销毁
newvue.off('自定义事件名')

示例

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <div>父组件</div>
    <div>
      <button @click='handle'>销毁事件</button>
    </div>
    <test-tom></test-tom>
    <test-jerry></test-jerry>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /*
      兄弟组件之间数据传递
    */
    // 提供事件中心
    var hub = new Vue();

    Vue.component('test-tom', {
      data: function(){
        return {
          num: 0
        }
      },
      template: `
        <div>
          <div>TOM:{{num}}</div>
          <div>
            <button @click='handle'>点击</button>
          </div>
        </div>
      `,
      methods: {
        handle: function(){
          hub.$emit('jerry-event', 2);
        }
      },
      mounted: function() {
        // 监听事件
        hub.$on('tom-event', (val) => {
          this.num += val;
        });
      }
    });
    Vue.component('test-jerry', {
      data: function(){
        return {
          num: 0
        }
      },
      template: `
        <div>
          <div>JERRY:{{num}}</div>
          <div>
            <button @click='handle'>点击</button>
          </div>
        </div>
      `,
      methods: {
        handle: function(){
          // 触发兄弟组件的事件
          hub.$emit('tom-event', 1);
        }
      },
      mounted: function() {
        // 监听事件
        hub.$on('jerry-event', (val) => {
          this.num += val;
        });
      }
    });
    var vm = new Vue({
      el: '#app',
      data: {
        
      },
      methods: {
        handle: function(){
          hub.$off('tom-event');
          hub.$off('jerry-event');
        }
      }
    });
  </script>
</body>
</html>

本文地址:https://blog.csdn.net/weixin_43745003/article/details/107279151