vue复习(一)
一、认识Vue
定义:一个构建数据驱动的Web界面的渐进式框架
优点:
1、可以完全通过客户端浏览器渲染页面,服务器端只提供数据
2、方面构建单页面应用程序(SPA)
二、引入Vue
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <title>vue导入</title> </head> <body> <div id="app"> <p title="普通p">p标签</p> <!-- v-bind vue的指令,可以被vue解析并处理 --> <!-- 第一个title:html标签的属性名(系统预定义的) --> <!-- 第二个titile:vue的变量 --> <p v-bind:title='title'>p标签</p> </div> </body> <!-- 引入外部vue js --> <script type="text/javascript" src="./js/vue.js"></script> <!-- 自身 js --> <script type="text/javascript"> // 创建vue实例,需要一个对象参数 new Vue({ el: '#app', data: { title: 'vue p' } }) </script> </html>
三、Vue实例
实例:el
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>vue实例之el</title> </head> <body> <div id="root"></div> <!-- <p v-bind:class="title" v-on:dblclick='action' v-model='abc' v-for="it in its"></p> --> <p v-bind:title='title'>p标签</p> </body> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript"> // el: vue实例的挂载目标 // 表示vue创建的该实例只对挂载点内部的模块进行处理 new Vue({ el: '#root', data: { title: 'vue p' } }) </script> </html>
数据:data
Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>vue data</title> </head> <body> <div id="app"> <p>{{ msg }}</p> <!-- 出现在模块中的变量,一般都需要默认初始值 --> <p v-text='txt'></p> </div> </body> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript"> var app = new Vue({ el: '#app', // data为模块中的变量提供数据 data: { msg: 'vue 控制的 文本1', txt: 'vue 控制的 文本2', } }); console.log(app) // el | data 为 vue变量 => 以$开头,区别普通变量 console.log(app.$data) console.log(app.$data.msg) // 所有在模块中产生的变量,也可以通过vue的实例直接访问 console.log(app.msg) </script> </html>
方法:methods
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>vue data</title> <style type="text/css"> .p1 { width: 300px; height: 100px; border: 1px solid #333; } </style> </head> <body> <div id="app"> <!-- v-on指令用于绑定事件 --> <!-- 事件对应逻辑由vue实例的methods处理 --> <!-- 绑定的事件(函数)需不需要携带参数列表: 无=>无需传参 有=>需要传参 --> <!-- 需要操作事件(需要事件对象)无需传参,传参后会都是事件 --> <p class="p1" v-on:click='func'>{{ msg }}</p> <p class="p1" v-on:click='fn("zero", 88888)'>{{ msg }}</p> </div> </body> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript"> var app = new Vue({ el: '#app', data: { msg: 'vue context' }, methods: { func: function (obj) { // alert('呵呵') // this: vue实例 => app // alert(this.msg) console.log(obj) }, fn: function (name, salary) { console.log(name) console.log(salary) } } }); </script> </html>
计算属性:computed
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>computed</title> </head> <body> <div id="app"> <div> 姓:<input type="text" v-model='first_name' /> </div> <div> 名:<input type="text" v-model='last_name' /> </div> <!-- <p>姓名:{{ full_name() }}</p> --> <!-- 采用计算方式的变量可以不在data中赋初值 --> <p>姓名:{{ full_name }}</p> </div> </body> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript"> var app = new Vue({ el: '#app', data: { first_name: '', last_name: '' }, // methods: { // full_name: function () { // return this.first_name + " " + this.last_name; // } // }, // 一个变量依赖于多个变量,一般对该变量采用计算处理 computed: { full_name: function () { return this.first_name + " " + this.last_name; } } }) </script> </html>
监听器:watch
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>computed</title> </head> <body> <div id="app"> <div> 姓名:<input type="text" v-model='full_name' placeholder="姓与名以空格隔开" /> </div> <p>姓:{{ first_name }}</p> <p>名:{{ last_name }}</p> </div> </body> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript"> var app = new Vue({ el: '#app', data: { full_name: '', first_name: '', last_name: '' }, watch: { full_name: function () { // 监听full_name,然后拆分为姓与名 var fname = this.full_name; var arr = fname.split(' '); this.first_name = arr[0]; this.last_name = arr[1]; } } }) </script> </html>
分隔符:delimiters
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>delimiters</title> </head> <body> <div id="app"> {{ msg }} [[ msg ]] ${ msg } </div> </body> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript"> var app = new Vue({ el: '#app', data: { msg: '数据' }, // delimiters配置自定义绑定符号 // 值为拥有两个元素的数组,元素为字符串形式 delimiters: ['${', '}'] }) </script> </html>
实例对象使用成员属性和方法
<script> var app = new Vue({ el: '#app', data: { msg: 'message' } }) console.log(app) console.log(app.$el) console.log(app.$data.msg) console.log(app.msg) </script>
四、实例生命周期钩子
定义:
每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。
钩子方法:
beforeCreate:在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
created:在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。
beforeMount:在挂载开始之前被调用:相关的 render 函数首次被调用。
mounted:el被新创建的vm.$el替换,并挂载到实例上去之后调用该钩子。
beforeUpdate:数据更新时调用,发生在虚拟 DOM 打补丁之前。
updated:数据更新时调用,发生在虚拟 DOM 打补丁之前。
activated:keep-alive 组件激活时调用。
deactivated:keep-alive 组件停用时调用。
beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。
destroyed:Vue实例销毁后调用。调用后,Vue实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
errorCaptured:2.5.0+ 新增,当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播。
重点钩子:
created:实例完全创建完毕(属性与方法都准备就绪)。可以进行数据操作(请求后台数据,重新渲染最新数据)
mounted:虚拟DOM构建完毕,并完成实例的el挂载。可以重新操作页面DOM
钩子函数实例:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>生命周期钩子</title> </head> <body> <div id="app"> {{ msg }} </div> </body> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript"> var app = new Vue({ el: '#app', data: { msg: '数据' }, // 该钩子方法触发:vue实例刚被创建(只拥有内存位置),其他任何操作都未执行 // 就满足的beforeCreate钩子的触发条件,系统就会回调该方法的实现 // 用户在该触发条件情况下想去完成某些逻辑,那么就去实现该钩子 beforeCreate: function () { }, /* // 系统内部调用 if (beforeCreate) { beforeCreate() } // ... // ... if (created) { created() } if (beforeMount) { beforeMount() } // ... */ // 数据与事件加载完毕,el并没有进行挂载 created: function () { // 获取想要的数据(请求后台) // 事件的解绑或换绑或重新绑定 // 对虚拟DOM进行修改 }, // DOM树加载完毕,el渲染完毕 mounted:function () { // 可能需要对DOM进行操作(交给模块处理) } }) </script> </html>
五、视图常规操作
v-text:文本变量
<p v-text='msg'></p> <p>{{ msg }}</p>
v-once:一次性文本赋值
<p v-once>{{ msg }}</p>
v-html:html文本变量
<p v-html='msg'></p> <script> new Vue({ el: '#app', data: { msg: '<b>文本</b>' } }) </script>
v-bind:属性绑定
<div id="app"> <img v-bind:src='imgSrc' /> <!-- 简写 --> <img :src='imgSrc' /> </div> <script> new Vue({ el: '#app', data: { imgSrc: 'https://www.baidu.com/favicon.ico' } })

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>主要指令v-bind</title> <script type="text/javascript" src="js/vue.js"></script> <style type="text/css"> .a { background-color: red; } .b { color: green; } </style> </head> <body> <div id="app"> <!-- v-bind:绑定系统预定义属性 --> <!-- 字符串abc --> <p title="abc">p段落</p> <!-- 1、变量abc,需要初始化 --> <p v-bind:title="abc">p段落</p> <!-- 2、如何直接将abc作为字符串绑定到属性 --> <p v-bind:title="'abc'">p段落</p> <!-- 3、v-bind简写为: --> <p :title="'ABC'">p段落</p> <!-- 4、绑定多个变量 --> <!-- i:以数组形式进行赋值 --> <!-- a, b为两个变量 --> <!-- 变量值可以有data提供 --> <!-- <div :class="[a, b]">12345</div> --> <!-- ii:以对象形式进行赋值 --> <!-- a,b为两个class值 --> <!-- class值只取true | false --> <!-- 非空均视为true,否则视为false --> <!-- <div :class="{a: 'A', b: 'B'}">67890</div> --> <!-- <div :class="{a: true, b: true}">67890</div> --> <!-- iii --> <div :class="[{a: true}, {b: true}]">呵呵嘻嘻哈哈</div> <!-- 总结 --> <!-- [], 中出现的值,作为变量,变量值来源于data,且最终将来源于data的数据作为属性值赋值给v-bind绑定的属性 --> <!-- {}, 中出现的键(key),直接作为v-bind绑定的属性的值,而键(key)对应的值(value)是决定键是否起效,值(value)的取值只为true|false --> <a :style="color" href="">百度</a> <a :style="{color: 'red', backgroundColor: 'black'}" href="">京东</a> </div> </body> <script type="text/javascript"> new Vue({ el: '#app', data: { abc: 'ABC', a: 'a', b: 'b', // color: 'color: red' color: { color: 'red', // 支持驼峰命名法 backgroundColor: 'orange' } } }) </script> </html>
v-model:双向数据绑定
<div id="app"> <input type="text" v-model='msg'> <p>{{ msg }}</p> </div> <script> new Vue({ el: '#app', data: { msg: '' } }) </script>

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>主要指令v-model</title> <script type="text/javascript" src="js/vue.js"></script> <style type="text/css"> </style> </head> <body> <div id="app"> <!-- v-model针对于表单元素 --> <form action="" method="get"> <!-- 1、双向绑定:服务于文本输入框 --> <!-- v-model存储的值为输入框的value值 --> <div> <input type="text" name="usr" v-model="in_val"> <input type="password" name="ps" v-model="in_val" > <textarea name="info" v-model="in_val"></textarea> </div> <!-- 2、单选框 --> <div> <!-- 单选框是以name进行分组,同组中只能发生单选 --> <!-- v-model存储的值为单选框的value值 --> 男:<input type="radio" name="sex" value="男" v-model="ra_val"> 女:<input type="radio" name="sex" value="女" v-model="ra_val"> {{ ra_val }} </div> <!-- 3、单一复选框 --> <!-- v-model存储的值为true|false --> <!-- 或者为自定义替换的值 --> <div> <input type="checkbox" v-model='sin_val' true-value="选中" false-value="未选中" /> {{ sin_val }} </div> <!-- 4、多复选框 --> <!-- v-model存储的值为存储值多复选框value的数组 --> <div> <input type="checkbox" value="喜好男的" name="cless" v-model='more_val' /> <input type="checkbox" value="喜好女的" name="cless" v-model='more_val' /> <input type="checkbox" value="不挑" name="cless" v-model='more_val' /> {{ more_val }} </div> <input type="submit"> </form> </div> </body> <script type="text/javascript"> new Vue({ el: '#app', data: { in_val: '', // 默认值可以决定单选框默认选项 ra_val: '男', // 默认值为true,单一复选框为选中,反之false为不选中 sin_val: '', // 数组中存在的值对应的复选框默认为选中状态 more_val: ['喜好女的','不挑'] } }) </script> </html>
v-on:事件绑定

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>主要指令v-on</title> <script type="text/javascript" src="js/vue.js"></script> <style type="text/css"> </style> </head> <body> <div id="app"> <!-- 1、绑定系统预定义事件,事件值为函数 --> <div v-on:click="fn1">{{ msg }}</div> <!-- 2、v-on简写 --> <div @click="fn2">{{ msg }}</div> <!-- 3、传值 -- 默认传值 -- 事件 event --> <div @click='fn3'>{{ msg }}</div> <!-- 4、传值 -- 自定义值 --> <div @click="fn4(msg, 88888)">{{ msg }}</div> <!-- 5、传参 -- 自定义值 + 事件 --> <div @click="fn5($event, msg)">{{ msg }}</div> </div> </body> <script type="text/javascript"> new Vue({ el: '#app', data: { msg: '默认值' }, methods: { fn1: function () { alert('呵呵') }, fn2 () { alert('嘻嘻') }, fn3 (obj) { console.log(obj) }, fn4 (obj, num) { console.log(obj, num) console.log(this.msg) }, fn5 (ev, msg) { console.log(ev, msg) } } }) </script> </html>
v-cloak:避免页面加载闪烁
<style> [v-cloak] { display: none; } </style> <div id="app" v-cloak> </div>
视图自身运算
<div id="app" v-cloak> <p>{{ 1 + 1 }}</p> <p>{{ [1, 2, 3].join('@') }}</p> </div>
视图相关操作实例:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>视图</title> <style type="text/css"> p { border: 1px solid #ff6700; height: 30px; line-height: 30px; } .abc { border-color: yellowgreen; } [class] { border-width: 5px; } [v-cloak] { display: none; } </style> <script type="text/javascript" src="js/vue.js"></script> </head> <body> <!-- <div id="app" v-cloak> --> <div id="app"> <!-- v-model实现数据的双向绑定 --> <input type="text" v-model='msg'> <input type="text" v-model='msg'> <p>{{ msg }}</p> <p v-text='msg'></p> <!-- 只赋值一次 --> <p v-once>{{ msg }}</p> <!-- 可以解析html语法的标签 --> <p v-html='msg'></p> <!-- 属性的绑定:属性值有变量控制 v-bind:属性名 :属性名 --> <!-- <p class="active"></p> --> <!-- <p v-bind:class='active'></p> --> <p :class='active'></p> <!-- 事件的绑定:事件值为函数名(带或不带参数列表) v-on:事件名 @事件名 --> <p @dblclick='func'></p> </div> </body> <script type="text/javascript"> var app = new Vue({ el: '#app', data: { msg: '初值', active: 'abc' }, methods: { func: function () { alert('呵呵') } } }) </script> </html>
六、条件渲染
v-if:值true会被渲染,值false不会被渲染
<div id="app"> <div v-if='isShow'>div div div</div> <button @click='isShow = !isShow'>改变</button> </div> <script> new Vue({ el: '#app', data: { isShow: true } }) </script>
v-else:与v-if结合使用形成对立面
<div id="app"> <div v-if='isShow'>div div div</div> <div v-else='isShow'>DIV DIV DIV</div> <button @click='isShow = !isShow'>改变</button> </div> <script> new Vue({ el: '#app', data: { isShow: true } }) </script>
v-else-if:变量的多情况值判断
<div id="app"> <div v-if='tag == 0'>if if if</div> <div v-else-if='tag == 1'>else if else</div> <div v-else='tag == 2'>else else else</div> <input type='number' min='0' max='2' v-model='tag' /> </div> <script> new Vue({ el: '#app', data: { tag: 0 } }) </script>
template:不被渲染的vue结构标签
<template v-if="isShow"> <p>用template嵌套</p> <p>可以为多行文本</p> <p>同时显隐</p> <p>且template标签不会被vue渲染到页面</p> </template>
-
v-show:一定会被渲染到页面,以display属性控制显隐
-
<div id="app"> <div v-if='tag == 0' key='0'>if if if</div> <div v-else-if='tag == 1' key='1'>else if else</div> <div v-else='tag == 2' key='2'>else else else</div> <input type='number' min='0' max='2' v-model='tag' /> </div> <script> new Vue({ el: '#app', data: { tag: 0 } }) </script>

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>条件渲染</title> <script type="text/javascript" src="js/vue.js"></script> <style type="text/css"> .box { width: 200px; height: 200px; background-color: red; border-radius: 50%; } .bb { width: 50px; height: 50px; border: 1px solid black; border-radius: 50%; font: 400 20px/50px 'STSong'; text-align: center; user-select: none; float: left; margin-left: 20px; } .wrap:after { content: ''; display: block; clear: both; } .a { width: 300px; height: 200px; } .r {background: red} .g {background: green} .b {background: blue} </style> </head> <body> <div id="app"> <button @click="btnClick">切换</button> <!-- 1、v-if取值为true|false --> <!-- true将会被渲染|false不会被渲染(页面中不存在该标签) --> <!-- <div class="box" v-if="isShow"></div> --> <!-- 2、v-show取值为true|false --> <!-- true为渲染并显示,false虽然渲染到DOM上,但display以none形式存在 --> <div class="box" v-show='false'></div> <!-- 3、v-if、v-else-if、v-else --> <!-- 多分支条件 --> <div class="wrap"> <!-- .bb.b$*3 --> <div class="bb b1" @click='changeColor(0)'>红</div> <div class="bb b2" @click='changeColor(1)'>绿</div> <div class="bb b3" @click='changeColor(2)'>蓝</div> </div> <div> <!-- 多分支一定存在判断,判断便会产生比较变量 --> <div class="r a" v-if='tag == 0'></div> <div class="g a" v-else-if='tag == 1'></div> <div class="b a" v-else></div> </div> </div> </body> <script type="text/javascript"> new Vue({ el: '#app', data: { isShow: false, tag: 0 }, methods: { // 通过方法控制绑定给v-if的值 btnClick: function () { this.isShow = !this.isShow; }, changeColor (num) { this.tag = num; } } }) </script> </html>
七、列表渲染
v-for:循环渲染列表
<div id="app"> <ul> <li v-for='item in items'>{{ item }}</li> </ul> <button @click='click'>改变</button> </div> <script> new Vue({ el: '#app', data: { items: ['张三', '李四', '王五'] }, methods: { click: function () { this.items.splice(1, 1, '李大大'); this.items.pop(); this.items.push('赵六') } } }) </script>
遍历数组
// items: ['张三', '李四', '王五'] // 值 <ul> <li v-for='item in items'>{{ item }}</li> </ul> // 值, 索引 <ul> <li v-for='(item, index) in items'>{{ index }} - {{ item }}</li> </ul>
遍历对象
// {'name': '张三', 'age': 18, 'sex': '男'} // 值 <div v-for="value in object"> {{ value }} </div> // 值, 键 <div v-for="(value, key) in object"> {{ key }}: {{ value }} </div> // 值, 键, 索引 <div v-for="(value, key, index) in object"> {{ index }}. {{ key }}: {{ value }} </div>

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>列表渲染</title> <script type="text/javascript" src="js/vue.js"></script> </head> <body> <div id="app"> <ul> <li>{{list[0]}}</li> <li>{{list[1]}}</li> <li>{{list[2]}}</li> <li>{{list[3]}}</li> <li>{{list[4]}}</li> <li>{{list[5]}}</li> <li>{{list[6]}}</li> </ul> <!-- 迭代数组 --> <ul> <!-- 变量it为集合list中被迭代出的元素 --> <!-- 由v-for指令控制的标签会随元素的个数动态渲染 --> <li v-for='it in list'>{{ it }}</li> </ul> <!-- 迭代对象 --> <div v-for='value in dic'>{{ value }}</div> <!-- 迭代除取值外的其他可迭代到的值 --> <ul> <li v-for="(v, i) in list">索引:{{i}} 名字:{{v}}</li> </ul> <ul> <li v-for="(v, k, i) in dic">{{i}} {{k}} {{v}}</li> </ul> </div> </body> <script type="text/javascript"> new Vue({ el: '#app', data: { list: ["张三", "李四", "王五", "赵六", "钱七", "egon", "monkey"], dic: {'name': 'zero', 'age': 8, 'salary': 88888} } }) </script> </html>
复杂数据渲染
// items: [{'name': '张三'}, {'age': 18}, {'sex': '男'}] <div> <div>{{ items[0].name }}</div> <div>{{ items[1].age }}</div> <div>{{ items[2].sex }}</div> </div>

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>列表渲染</title> <script type="text/javascript" src="js/vue.js"></script> </head> <body> <!-- key属性:可以提高效率(通过不同的唯一key值建立缓存) --> <div id="app"> <div v-for='(item,index) in list' :key='index' style="height: 30px"> <div v-for='(value, key, index) in item' :key='index + 10' style="float: left;"> {{key}} : {{value}} </div> </div> </div> </body> <script type="text/javascript"> new Vue({ el: '#app', data: { list: [ {'name': 'egon', 'age': 108}, {'name': 'monkey', 'age': 77}, {'name': 'zero', 'age': 8} ] } }) // items: [{'name': '张三'}, {'age': 18}, {'sex': '男'}] // 通过[索引]取出数组中对应的值 // 通过.key取出对象中对应的值 </script> </html>

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>todoList</title> <script type="text/javascript" src="js/vue.js"></script> </head> <body> <!-- 录入用户输入的数据,更新到指定的list中,通过vue的数据驱动特效,实时渲染到页面 --> <div id="app"> <div> <input type="text" v-model='value'> <!-- 提交:将数据添加到list中 --> <button @click='pushAction'>提交</button> </div> <ul> <!-- 点击指定的li,将自身数据从list中移除,完成自身删除 --> <li @click='deleteAction(index)' v-for='(item,index) in list' :key="index">{{ item }}</li> </ul> </div> </body> <script type="text/javascript"> new Vue({ el: '#app', // vue目前不支持索引直接操作数据,但可以通过数据类型对应的操作方法 data: { value: '', list: [] }, methods: { pushAction () { this.list.push(this.value); this.value = '' }, deleteAction (index) { // alert(index) this.list.splice(index, 1) } } }) </script> </html>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?