vue开发环境与基础语法、计算属性、侦听属性

一、开发环境

1.通过CDN引入(暴露了全局的vue类对象)
  • 全局构建版本:

这个类对象提供了一个createApp()方法,用来创建一个vue应用

xml 复制代码
<head>
    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
</head>

<body>
    <div id="app"></div>
    <script>
        const { createApp } = Vue  // 对象解构
    </script>
</body>
  • ES模块构建版本:
xml 复制代码
<script type="module">
import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'
</script>
2.工程构建

在命令行中运行 npm create vue@latest

二、创建应用示例

通过createApp()方法创建一个vue应用,通过mount()方法挂载到指定div节点下显示

data选项(函数方法) - 定义数据,返回的属性将会成为响应式的状态

methods选项 - 定义方法,是一些用来更改状态与触发更新的函数

template选项 - 定义模板

为方便vue各选项的理解,这里用template选项定义模板(去vcsode应用商店安装es6-string-html扩展,在template选项上方加/html/注释),也可直接写入到div标签中

xml 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
</head>

<body>
    <div id="app"></div>
    <script>
        //方法一
        // const app = Vue.createApp({// 创建vue应用
        //     data() {
        //         return {
        //             message: 'helloworld'  //定义数据模型
        //         }
        //     },
        //     template: `<p>{{message}}</p>`  // 定义模板  模板文本插值语法 {{ }}
        // })
        // app.mount('#app')// 挂载到指定div节点下显示

        //方法二
        const { createApp } = Vue  // 对象解构
        // 根组件(组件本质是有指定选项属性的javascript对象)
        const root = {
            data() {
                return {
                    message: 'helloworld',  //定义数据模型
                }
            },

            /*html*/
            template: `<p>{{message}}</p>`  // 定义模板  模板文本插值语法 {{ }}
        }

        createApp(root).mount('#app')// 创建vue应用并挂载到指定div节点下显示
    </script>
</body>
</html>

三、基础语法

1. 文本插值

{{ 变量/表达式 }}

2. 指令(带有v-前缀的特殊属性)
2.1 操作内容文本

v-html 解析标签元素(innerHTML)

v-text 不解析标签元素(innerText)

v-pre vue不解析{{ }}

2.2 操作属性

v-bind:属性名=属性值(setAttribute(属性名,属性值),getAttribute(属性名))

:属性名=属性值(简写形式)

2.3 操作样式

:class="字符 / 对象{样式:控制样式变量} / 数组,"(class="")

2.4 操作事件

v-on:事件类型=事件处理函数(onclick="")

@事件类型=事件处理函数(简写形式)

2.5 v-if和v-show

v-if和v-show区别:

v-if 动态添加移除dom节点(满足条件渲染dom节点,不满足不渲染)

v-show 通过css样式display控制dom节点隐藏显示(本质是css样式的 display: none/block)

2.6 列表渲染v-for

(v-for要绑定key,以便虚拟dom diff算法能够快速找到列表项,对列表项进行高效操作)

不建议v-for与v-if合用:

v-for会比v-if优先执行,如果一起用会造成性能浪费,可以v-for外嵌套v-if

如果v-for内嵌套v-if,可以先用计算属性computed过滤遍历数组,再用v-for,优化性能

2.7 表单数据双向绑定v-model

:value="" @input=""/v-model(通过event.target.value获取输入框的值)

2.8 v-cloak 性能优化,用于隐藏未完成编译的DOM模板

网速比较慢或者加载东西比较多时,可能会出现未编译模板闪现情况,用户可能看到还没编译完成的双大括号标签。

v-cloak 会保留在所绑定的元素上,直到相关组件实例被挂载后才移除。配合像v-cloak{display:none}这样的CSS规则,它可以在组件编译完毕前隐藏原始模板。

xml 复制代码
<style>
[v-cloak]{display:none}
</style>
<div v-cloak></div>
3. 指令修饰符模板语法
3.1表单修饰符

number将输入框内容转换为number类型

trim去除前后空格

lazy懒加载,input事件替换成change事件(不是输入时触发,而是输入完成时触发)

ini 复制代码
<input v-model.lazy="msg" >
3.2事件修饰符

prevent阻止默认行为(链接跳转、表单提交/event.preventDefault())

stop阻止事件传播(事件冒泡、事件捕获)

passive滚动事件的默认行为 (scrolling) 将立即发生,而非等待 onScroll 完成。( 不能同时使用.passive 和 .prevent,因为 .passive 已经向浏览器表明了你不想阻止事件的默认行为。如果同时使用 .prevent 会被忽略,并且会报错。)

self仅当 event.target 是元素本身时才会触发事件处理器

capture添加事件监听器时,指向内部元素的事件,在被内部元素处理前,先被外部处理(事件捕获)

once点击事件最多被触发一次

3.3按键修饰符

enter/tab/delete (捕获"Delete"和"Backspace"两个按键)/esc/space/up/down/left/right

@keyup.enter="bindLogin"

xml 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>模板语法</title>
    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
    <style>
        .p1 {
            width: 100px;
            height: 100px;
            background-color: skyblue;
        }
        .d1 {
            color: pink;
        }
        .d2 {
            background-color: rgb(43, 67, 226);
        }
        .d3{
            width: 400px;
            height: 400px;
            background-color: skyblue;
        }
        .d4{
            width: 200px;
            height: 200px;
            background-color: pink;
        }
        [v-cloak] {
            display: none;
        }
    </style>
</head>

<body>
    <div id="app"></div>
    <script>
        const { createApp } = Vue
        const root = {
            // 定义数据
            data() {
                return {
                    title: '文本插值',
                    num: 10,
                    isOk: true,
                    message: 'helloworld',

                    contenthtml: '<h1>v-html操作内容</h1>',
                    contenttext: '<h1>v-text操作内容</h1>',

                    url: 'http://www.baidu.com',
                    pic: 'https://img0.baidu.com/it/u=1705694933,4002952892&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1672160400&t=7153143fa69e03b8233f4d808da5c4b9',

                    onLine: 2, // 0 在线,1 隐身,2 离线
                    show: true,

                    list: [
                        { id: 1001, name: 'javascript高级编程', price: 88.98 },
                        { id: 1002, name: 'vue高级编程', price: 108.89 },
                        { id: 1003, name: 'css高级编程', price: 68.89 },
                    ],

                    modelmsg: '双向绑定',
                    state: false,

                    numberValue: '',
                    trimValue: '',
                    lazyValue: '',
                }
            },

            // methods选项定义方法
            methods: {
                onAlert() {
                    alert('执行onAlert方法 >>>>');
                },

                // methods选项方法不能用箭头函数
                bindInput() {
                    //this: vue实例对象
                    this.modelmsg = event.target.value
                },

                bindNumberConfirm() {
                    alert(typeof (this.numberValue))
                    console.log('this.numberValue ', this.numberValue, typeof (this.numberValue))
                },

                bindTrimConfirm() {
                    alert(this.trimValue)
                    console.log('this.trimValue ', this.trimValue)
                },

                bindBaidu() {
                    // event.preventDefault()
                    alert('bindBaidu>>>>')
                    console.log('bindBaidu>>>>')
                },

                bindSubmit() {
                    alert('bindSubmit >>>> ')
                    console.log('bindSubmit >>>> ')
                },

                bindStopOne(){
                    alert('bindStopOne >>>')
                    console.log('bindStopOne >>>')
                },

                bindStopTwo(){
                    alert('bindStopTwo >>>')
                    console.log('bindStopTwo >>>')
                },

                bindLogin(){
                    alert('bindLogin >>>')
                    console.log('bindLogin >>>')
                },
            },

            // 定义模板
            template: `<div v-cloak>

                        <p>----文本插值-----</p>
                        <h2>{{title}}</h2>
                        <p>{{ num+1 }}</p>
                        <p>{{ isOk?'YES':'NO' }}</p>
                        <p>{{ message.split('').reverse().join('') }}</p>

                        <p>----操作内容-----</p>
                        <p v-html="contenthtml"></p>
                        <p v-text="contenttext"></p>
                        <h2 v-pre>{{title}}</h2>

                        <p>----操作属性-----</p>
                        <a v-bind:href="url">百度</a>
                        <div><img :src="pic" alt="图片"/></div>

                        <p>----操作样式-----</p>
                        <p class="p1">操作样式字符</p>
                        <p v-bind:class="{'p1':isOk}">操作样式对象</p>
                        <p :class="['d1','d2']">操作样式数组</p>

                        <p>----操作事件-----</p>
                        <button v-on:click="onAlert">确定1</button>
                        <button @click="onAlert">确定2</button>

                        <p>----v-if和v-show-----</p>
                        <p v-if="onLine === 0">在线</p>
                        <p v-else-if="onLine === 1">隐身</p>
                        <p v-else>离线</p>
                        <p v-show="show">显示</p>

                        <p>----列表渲染v-for-----</p>
                        <table>
                            <tr>
                               <th>索引号</th>
                               <th>ID</th>
                               <th>名称</th>
                               <th>价格</th>
                            </tr>

                            <tr v-for="(item,index) in list ">
                               <td>{{ index}}</td>   
                               <td>{{ item.id }}</td>   
                               <td>{{ item.name }}</td>   
                               <td>{{ item.price }}</td>   
                            </tr>  
                        </table>

                        <ul>
                           <li v-for="(item,index) in list" >{{index}} - {{item.id}} - {{item.name}} - {{item.price}}</li>
                        </ul>

                        <p>----表单数据双向绑定v-model-----</p>
                        <p>{{modelmsg}}</p>
                        <input type="text" :value="modelmsg" @input="bindInput"/>
                        <input type="text" v-model="modelmsg"/>

                        {{state?'yes':'no'}}
                        <input type="checkbox" v-model="state"/>

                        <p>----表单修饰符-----</p>
                        <p>{{ numberValue }}</p>
                        <input type="text" v-model.number="numberValue"> <button @click="bindNumberConfirm">确定</button>

                        <p>{{ trimValue }}</p>
                        <input type="text" v-model.trim="trimValue"> <button @click="bindTrimConfirm">确定</button>

                        <p>{{lazyValue}}</p>
                        <input type="text" v-model.lazy="lazyValue">

                        <p>----事件修饰符-----</p>
                        <a :href="url" @click.prevent="bindBaidu">百度</a>
                        <form :action="url" @submit.prevent="bindSubmit">
                            <input type="submit" value="提交">
                        </form>

                        <div class="d3" @click="bindStopOne">
                            <div class="d4" @click.stop="bindStopTwo">按钮1</div>
                        </div>

                        <p>----按键修饰符-----</p>
                        <input type="text" @keyup.enter="bindLogin"/>
                      </div>`
        }

        createApp(root).mount('#app')
    </script>
</body>
</html>

四、计算属性computed

缓存计算的结果,依赖项变化重新计算(计算属性的值可以修改,要定义成对象形式,语法上用get、set写法,但要避免直接修改计算属性的值,一般是通过依赖项自动修改)

computed:{}

例如计算总价

xml 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>计算总价</title>
    <script src="../lib/vue.global.js"></script>
</head>

<body>
    <div id="app"></div>
    <script>
        const { createApp } = Vue
        const root = {

            data() {
                return {
                    list: [
                        { id: 1, name: 'js高级编程', price: 88.89 },
                        { id: 2, name: 'vue高级编程', price: 118.88 },
                    ]
                }
            },

            methods: {
                bindAddBook(){
                    let product = {id:3,name:'react高级编程',price:200}
                    this.list.push(product)
                }
            },

            computed: {// computed声明时定义成方法,但本质上是一个属性,一定有一个返回值,在computed方法体中定义依赖,当依赖变化重新
                totalPrice(){
                    // let sum = 0
                    // for(let i = 0; i < this.list.length; i++){
                    //     let res = this.list[i]
                    //     sum += res.price
                    // }

                    //累加方法 .reduce((previous, current) => {return previous + current.price}, 0)
                    let sum = this.list.reduce((previous, current) => previous + current.price, 0)
                    return sum.toFixed(2)
                }

          //计算属性的值可以修改,要定义成对象形式,语法上用get、set写法,但要避免直接修改计算属性的值。一般是通过依赖项自动修改

          //fullName:{

              //get(){return xx},

              //set(newvalue){}

          //}

            /* html */
            template: `<div>
                         <table>
                             <tr>
                                 <th>序号</th>
                                 <th>名称</th>
                                 <th>价格</th>
                             </tr>

                             <tr v-for="item,index in list">
                                 <td>{{item.id}}</td>
                                 <td>{{item.name}}</td>
                                 <td>{{item.price}}</td>
                             </tr>
                         </table>

                         <h2>总价: <span>{{totalPrice}}</span></h2>

                         <button @click="bindAddBook">添加商品</button>
                    </div>`

        }
        createApp(root).mount('#app')
    </script>
</body>
</html>

五、侦听属性watch

侦听响应式数据的变化和一些非DOM元素改变,可以获取数据改变前后的值。

默认情况下,组件初次加载完毕不会调用watch侦听器。如果想让watch侦听器立即被调用,需要使用 immediate 选项。

javascript 复制代码
watch:{
  username(){},//函数形式
  username:{//对象形式,立即执行
    handler:(){},//固定写法,自动调用
    immediate:true,
    deep:true,//侦听的是个对象user:{name:'zc',age:20},改变属性侦听不到,需要深度侦听
  }
}
xml 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>watch侦听器</title>
    <script src="../lib/vue.global.js"></script>
</head>

<body>
    <div id="app"></div>
    <script>
        const {createApp} = Vue
        const App = {
            data() {
                return {
                    username:'jack',
                    keyword:'衣服',
                    user:{
                        name:'rose',
                        age:20
                    }
                }
            },

            //侦听器
            watch: {
                username(newValue,oldValue){
                    console.log('newValue ',newValue, '  oldValue',oldValue);
                },
                keyword:{
                    // handler是固定写法,侦听器触发执行的方法。表示当keyword值变化自动调用handler处理函数,
                    handler(newValue,oldValue){
                        console.log('keyword newValue ',newValue, '  oldValue',oldValue);
                    },
                    // 立即执行
                    immediate:true
                },
                user:{
                    handler(newValue,oldValue){
                        console.log('user newValue ',newValue, '  oldValue',oldValue);
                    },
                    // 深度侦听
                    deep:true
                }
            },

            /* html */

            template:`<div>
                        <h2>watch侦听器</h2>
                     </div>`
        }
        const app = createApp(App).mount('#app')
    </script>
</body>
</html>
相关推荐
mldong4 小时前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排5 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60615 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角6 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!7 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰7 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi8 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen9 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马10 小时前
AI源码分析:拆解模型底层实现逻辑
前端
IT_陈寒10 小时前
React子组件莫名其妙重渲染?你可能漏了这个Hook
前端·人工智能·后端