[{"data":1,"prerenderedAt":3368},["ShallowReactive",2],{"note:code\u002Fvue\u002F05-forms-lists-styles":3},{"id":4,"title":5,"body":6,"description":16,"extension":3362,"meta":3363,"navigation":500,"path":3364,"seo":3365,"stem":3366,"__hash__":3367},"notes\u002Fsource\u002Fcode\u002Fvue\u002F05-forms-lists-styles.md","05 列表、表单、样式和用户输入",{"type":7,"value":8,"toc":3344},"minimark",[9,13,17,20,25,28,114,117,184,190,193,240,243,247,250,321,324,327,382,433,436,452,460,465,586,589,605,611,656,661,667,670,693,696,726,729,777,780,812,815,876,895,898,902,905,934,937,974,977,1005,1008,1040,1043,1047,1050,1071,1078,1182,1185,1210,1213,1313,1316,1373,1377,1380,1409,1412,1415,1484,1487,1491,1493,1516,1519,1635,1637,1764,1770,1774,1777,1824,1827,1907,1910,1955,1958,1962,1965,2013,2020,2024,2027,2153,2156,2170,2173,2177,2180,2182,2203,2205,2263,2266,2277,2280,2315,2321,2325,3305,3308,3341],[10,11,5],"h1",{"id":12},"_05-列表表单样式和用户输入",[14,15,16],"p",{},"真实应用不是只展示数据，还要让用户输入、修改、筛选、提交。表单和列表是 Vue 项目最常见的业务界面。",[14,18,19],{},"本章目标：你能处理用户输入，能写基本校验，能稳定渲染列表，能根据状态切换样式，并能考虑空状态、错误状态和可访问性。",[21,22,24],"h2",{"id":23},"_1-列表数据应该有稳定-id","1. 列表数据应该有稳定 id",[14,26,27],{},"假设任务列表：",[29,30,35],"pre",{"className":31,"code":32,"language":33,"meta":34,"style":34},"language-js shiki shiki-themes github-light github-dark","const tasks = ref([\n  { id: 'task-1', title: '学习 v-for', done: false },\n  { id: 'task-2', title: '学习表单', done: true }\n])\n","js","",[36,37,38,62,87,108],"code",{"__ignoreMap":34},[39,40,43,47,51,54,58],"span",{"class":41,"line":42},"line",1,[39,44,46],{"class":45},"szBVR","const",[39,48,50],{"class":49},"sj4cs"," tasks",[39,52,53],{"class":45}," =",[39,55,57],{"class":56},"sScJk"," ref",[39,59,61],{"class":60},"sVt8B","([\n",[39,63,65,68,72,75,78,81,84],{"class":41,"line":64},2,[39,66,67],{"class":60},"  { id: ",[39,69,71],{"class":70},"sZZnC","'task-1'",[39,73,74],{"class":60},", title: ",[39,76,77],{"class":70},"'学习 v-for'",[39,79,80],{"class":60},", done: ",[39,82,83],{"class":49},"false",[39,85,86],{"class":60}," },\n",[39,88,90,92,95,97,100,102,105],{"class":41,"line":89},3,[39,91,67],{"class":60},[39,93,94],{"class":70},"'task-2'",[39,96,74],{"class":60},[39,98,99],{"class":70},"'学习表单'",[39,101,80],{"class":60},[39,103,104],{"class":49},"true",[39,106,107],{"class":60}," }\n",[39,109,111],{"class":41,"line":110},4,[39,112,113],{"class":60},"])\n",[14,115,116],{},"渲染：",[29,118,122],{"className":119,"code":120,"language":121,"meta":34,"style":34},"language-vue shiki shiki-themes github-light github-dark","\u003Cli v-for=\"task in tasks\" :key=\"task.id\">\n  {{ task.title }}\n\u003C\u002Fli>\n","vue",[36,123,124,170,175],{"__ignoreMap":34},[39,125,126,129,133,136,139,142,145,148,150,152,155,158,160,162,165,167],{"class":41,"line":42},[39,127,128],{"class":60},"\u003C",[39,130,132],{"class":131},"s9eBZ","li",[39,134,135],{"class":45}," v-for",[39,137,138],{"class":60},"=",[39,140,141],{"class":70},"\"",[39,143,144],{"class":60},"task ",[39,146,147],{"class":45},"in",[39,149,50],{"class":60},[39,151,141],{"class":70},[39,153,154],{"class":60}," :",[39,156,157],{"class":56},"key",[39,159,138],{"class":60},[39,161,141],{"class":70},[39,163,164],{"class":60},"task.id",[39,166,141],{"class":70},[39,168,169],{"class":60},">\n",[39,171,172],{"class":41,"line":64},[39,173,174],{"class":60},"  {{ task.title }}\n",[39,176,177,180,182],{"class":41,"line":89},[39,178,179],{"class":60},"\u003C\u002F",[39,181,132],{"class":131},[39,183,169],{"class":60},[14,185,186,189],{},[36,187,188],{},"id"," 是每一项的身份。不要把标题当 id，因为标题可能重复或修改。",[14,191,192],{},"前端新增时可以生成 id：",[29,194,196],{"className":31,"code":195,"language":33,"meta":34,"style":34},"const task = {\n  id: crypto.randomUUID(),\n  title: newTitle,\n  done: false\n}\n",[36,197,198,210,221,226,234],{"__ignoreMap":34},[39,199,200,202,205,207],{"class":41,"line":42},[39,201,46],{"class":45},[39,203,204],{"class":49}," task",[39,206,53],{"class":45},[39,208,209],{"class":60}," {\n",[39,211,212,215,218],{"class":41,"line":64},[39,213,214],{"class":60},"  id: crypto.",[39,216,217],{"class":56},"randomUUID",[39,219,220],{"class":60},"(),\n",[39,222,223],{"class":41,"line":89},[39,224,225],{"class":60},"  title: newTitle,\n",[39,227,228,231],{"class":41,"line":110},[39,229,230],{"class":60},"  done: ",[39,232,233],{"class":49},"false\n",[39,235,237],{"class":41,"line":236},5,[39,238,239],{"class":60},"}\n",[14,241,242],{},"如果后端返回数据，通常使用后端的 id。",[21,244,246],{"id":245},"_2-不要在模板里写复杂过滤","2. 不要在模板里写复杂过滤",[14,248,249],{},"不推荐：",[29,251,253],{"className":119,"code":252,"language":121,"meta":34,"style":34},"\u003Cli v-for=\"task in tasks.filter(task => !task.done)\" :key=\"task.id\">\n  {{ task.title }}\n\u003C\u002Fli>\n",[36,254,255,309,313],{"__ignoreMap":34},[39,256,257,259,261,263,265,267,269,271,274,277,280,284,287,290,293,295,297,299,301,303,305,307],{"class":41,"line":42},[39,258,128],{"class":60},[39,260,132],{"class":131},[39,262,135],{"class":45},[39,264,138],{"class":60},[39,266,141],{"class":70},[39,268,144],{"class":60},[39,270,147],{"class":45},[39,272,273],{"class":60}," tasks.",[39,275,276],{"class":56},"filter",[39,278,279],{"class":60},"(",[39,281,283],{"class":282},"s4XuR","task",[39,285,286],{"class":45}," =>",[39,288,289],{"class":45}," !",[39,291,292],{"class":60},"task.done)",[39,294,141],{"class":70},[39,296,154],{"class":60},[39,298,157],{"class":56},[39,300,138],{"class":60},[39,302,141],{"class":70},[39,304,164],{"class":60},[39,306,141],{"class":70},[39,308,169],{"class":60},[39,310,311],{"class":41,"line":64},[39,312,174],{"class":60},[39,314,315,317,319],{"class":41,"line":89},[39,316,179],{"class":60},[39,318,132],{"class":131},[39,320,169],{"class":60},[14,322,323],{},"这能运行，但不好读。模板应该尽量描述结构，不要塞复杂逻辑。",[14,325,326],{},"推荐：",[29,328,330],{"className":31,"code":329,"language":33,"meta":34,"style":34},"const activeTasks = computed(() => {\n  return tasks.value.filter((task) => !task.done)\n})\n",[36,331,332,352,377],{"__ignoreMap":34},[39,333,334,336,339,341,344,347,350],{"class":41,"line":42},[39,335,46],{"class":45},[39,337,338],{"class":49}," activeTasks",[39,340,53],{"class":45},[39,342,343],{"class":56}," computed",[39,345,346],{"class":60},"(() ",[39,348,349],{"class":45},"=>",[39,351,209],{"class":60},[39,353,354,357,360,362,365,367,370,372,374],{"class":41,"line":64},[39,355,356],{"class":45},"  return",[39,358,359],{"class":60}," tasks.value.",[39,361,276],{"class":56},[39,363,364],{"class":60},"((",[39,366,283],{"class":282},[39,368,369],{"class":60},") ",[39,371,349],{"class":45},[39,373,289],{"class":45},[39,375,376],{"class":60},"task.done)\n",[39,378,379],{"class":41,"line":89},[39,380,381],{"class":60},"})\n",[29,383,385],{"className":119,"code":384,"language":121,"meta":34,"style":34},"\u003Cli v-for=\"task in activeTasks\" :key=\"task.id\">\n  {{ task.title }}\n\u003C\u002Fli>\n",[36,386,387,421,425],{"__ignoreMap":34},[39,388,389,391,393,395,397,399,401,403,405,407,409,411,413,415,417,419],{"class":41,"line":42},[39,390,128],{"class":60},[39,392,132],{"class":131},[39,394,135],{"class":45},[39,396,138],{"class":60},[39,398,141],{"class":70},[39,400,144],{"class":60},[39,402,147],{"class":45},[39,404,338],{"class":60},[39,406,141],{"class":70},[39,408,154],{"class":60},[39,410,157],{"class":56},[39,412,138],{"class":60},[39,414,141],{"class":70},[39,416,164],{"class":60},[39,418,141],{"class":70},[39,420,169],{"class":60},[39,422,423],{"class":41,"line":64},[39,424,174],{"class":60},[39,426,427,429,431],{"class":41,"line":89},[39,428,179],{"class":60},[39,430,132],{"class":131},[39,432,169],{"class":60},[14,434,435],{},"优点：",[437,438,439,442,445],"ul",{},[132,440,441],{},"模板更干净。",[132,443,444],{},"过滤逻辑有名字。",[132,446,447,448,451],{},"调试时可以单独看 ",[36,449,450],{},"activeTasks","。",[21,453,455,456,459],{"id":454},"_3-v-model-是什么","3. ",[36,457,458],{},"v-model"," 是什么",[14,461,462,463,451],{},"输入框的值和响应式状态同步，最常用 ",[36,464,458],{},[29,466,468],{"className":119,"code":467,"language":121,"meta":34,"style":34},"\u003Cscript setup>\nimport { ref } from 'vue'\n\nconst title = ref('')\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cinput v-model=\"title\">\n  \u003Cp>你输入的是：{{ title }}\u003C\u002Fp>\n\u003C\u002Ftemplate>\n",[36,469,470,482,496,502,521,529,534,544,563,577],{"__ignoreMap":34},[39,471,472,474,477,480],{"class":41,"line":42},[39,473,128],{"class":60},[39,475,476],{"class":131},"script",[39,478,479],{"class":56}," setup",[39,481,169],{"class":60},[39,483,484,487,490,493],{"class":41,"line":64},[39,485,486],{"class":45},"import",[39,488,489],{"class":60}," { ref } ",[39,491,492],{"class":45},"from",[39,494,495],{"class":70}," 'vue'\n",[39,497,498],{"class":41,"line":89},[39,499,501],{"emptyLinePlaceholder":500},true,"\n",[39,503,504,506,509,511,513,515,518],{"class":41,"line":110},[39,505,46],{"class":45},[39,507,508],{"class":49}," title",[39,510,53],{"class":45},[39,512,57],{"class":56},[39,514,279],{"class":60},[39,516,517],{"class":70},"''",[39,519,520],{"class":60},")\n",[39,522,523,525,527],{"class":41,"line":236},[39,524,179],{"class":60},[39,526,476],{"class":131},[39,528,169],{"class":60},[39,530,532],{"class":41,"line":531},6,[39,533,501],{"emptyLinePlaceholder":500},[39,535,537,539,542],{"class":41,"line":536},7,[39,538,128],{"class":60},[39,540,541],{"class":131},"template",[39,543,169],{"class":60},[39,545,547,550,553,556,558,561],{"class":41,"line":546},8,[39,548,549],{"class":60},"  \u003C",[39,551,552],{"class":131},"input",[39,554,555],{"class":56}," v-model",[39,557,138],{"class":60},[39,559,560],{"class":70},"\"title\"",[39,562,169],{"class":60},[39,564,566,568,570,573,575],{"class":41,"line":565},9,[39,567,549],{"class":60},[39,569,14],{"class":131},[39,571,572],{"class":60},">你输入的是：{{ title }}\u003C\u002F",[39,574,14],{"class":131},[39,576,169],{"class":60},[39,578,580,582,584],{"class":41,"line":579},10,[39,581,179],{"class":60},[39,583,541],{"class":131},[39,585,169],{"class":60},[14,587,588],{},"用户输入时：",[437,590,591,594,600],{},[132,592,593],{},"输入框内容变化。",[132,595,596,599],{},[36,597,598],{},"title"," 自动更新。",[132,601,602,599],{},[36,603,604],{},"{{ title }}",[14,606,607,608,610],{},"如果不用 ",[36,609,458],{},"，你要手动写：",[29,612,614],{"className":119,"code":613,"language":121,"meta":34,"style":34},"\u003Cinput :value=\"title\" @input=\"title = $event.target.value\">\n",[36,615,616],{"__ignoreMap":34},[39,617,618,620,622,624,627,629,631,633,635,638,640,642,644,647,649,652,654],{"class":41,"line":42},[39,619,128],{"class":60},[39,621,552],{"class":131},[39,623,154],{"class":60},[39,625,626],{"class":56},"value",[39,628,138],{"class":60},[39,630,141],{"class":70},[39,632,598],{"class":60},[39,634,141],{"class":70},[39,636,637],{"class":60}," @",[39,639,552],{"class":56},[39,641,138],{"class":60},[39,643,141],{"class":70},[39,645,646],{"class":60},"title ",[39,648,138],{"class":45},[39,650,651],{"class":60}," $event.target.value",[39,653,141],{"class":70},[39,655,169],{"class":60},[14,657,658,660],{},[36,659,458],{}," 就是把这种常见模式封装起来。",[21,662,664,665],{"id":663},"_4-不同表单控件的-v-model","4. 不同表单控件的 ",[36,666,458],{},[14,668,669],{},"文本输入：",[29,671,673],{"className":119,"code":672,"language":121,"meta":34,"style":34},"\u003Cinput v-model=\"title\">\n",[36,674,675],{"__ignoreMap":34},[39,676,677,679,681,683,685,687,689,691],{"class":41,"line":42},[39,678,128],{"class":60},[39,680,552],{"class":131},[39,682,555],{"class":56},[39,684,138],{"class":60},[39,686,141],{"class":70},[39,688,598],{"class":60},[39,690,141],{"class":70},[39,692,169],{"class":60},[14,694,695],{},"多行文本：",[29,697,699],{"className":119,"code":698,"language":121,"meta":34,"style":34},"\u003Ctextarea v-model=\"description\">\u003C\u002Ftextarea>\n",[36,700,701],{"__ignoreMap":34},[39,702,703,705,708,710,712,714,717,719,722,724],{"class":41,"line":42},[39,704,128],{"class":60},[39,706,707],{"class":131},"textarea",[39,709,555],{"class":56},[39,711,138],{"class":60},[39,713,141],{"class":70},[39,715,716],{"class":60},"description",[39,718,141],{"class":70},[39,720,721],{"class":60},">\u003C\u002F",[39,723,707],{"class":131},[39,725,169],{"class":60},[14,727,728],{},"选择框：",[29,730,732],{"className":119,"code":731,"language":121,"meta":34,"style":34},"\u003Cselect v-model=\"priority\">\n  \u003Coption value=\"low\">低\u003C\u002Foption>\n  \u003Coption value=\"normal\">普通\u003C\u002Foption>\n  \u003Coption value=\"high\">高\u003C\u002Foption>\n\u003C\u002Fselect>\n",[36,733,734,754,759,764,769],{"__ignoreMap":34},[39,735,736,738,741,743,745,747,750,752],{"class":41,"line":42},[39,737,128],{"class":60},[39,739,740],{"class":131},"select",[39,742,555],{"class":56},[39,744,138],{"class":60},[39,746,141],{"class":70},[39,748,749],{"class":60},"priority",[39,751,141],{"class":70},[39,753,169],{"class":60},[39,755,756],{"class":41,"line":64},[39,757,758],{"class":60},"  \u003Coption value=\"low\">低\u003C\u002Foption>\n",[39,760,761],{"class":41,"line":89},[39,762,763],{"class":60},"  \u003Coption value=\"normal\">普通\u003C\u002Foption>\n",[39,765,766],{"class":41,"line":110},[39,767,768],{"class":60},"  \u003Coption value=\"high\">高\u003C\u002Foption>\n",[39,770,771,773,775],{"class":41,"line":236},[39,772,179],{"class":60},[39,774,740],{"class":131},[39,776,169],{"class":60},[14,778,779],{},"单个复选框：",[29,781,783],{"className":119,"code":782,"language":121,"meta":34,"style":34},"\u003Clabel>\n  \u003Cinput v-model=\"accepted\" type=\"checkbox\">\n  我已阅读规则\n\u003C\u002Flabel>\n",[36,784,785,794,799,804],{"__ignoreMap":34},[39,786,787,789,792],{"class":41,"line":42},[39,788,128],{"class":60},[39,790,791],{"class":131},"label",[39,793,169],{"class":60},[39,795,796],{"class":41,"line":64},[39,797,798],{"class":60},"  \u003Cinput v-model=\"accepted\" type=\"checkbox\">\n",[39,800,801],{"class":41,"line":89},[39,802,803],{"class":60},"  我已阅读规则\n",[39,805,806,808,810],{"class":41,"line":110},[39,807,179],{"class":60},[39,809,791],{"class":131},[39,811,169],{"class":60},[14,813,814],{},"多个复选框绑定数组：",[29,816,818],{"className":119,"code":817,"language":121,"meta":34,"style":34},"\u003Clabel>\n  \u003Cinput v-model=\"selectedTags\" type=\"checkbox\" value=\"vue\">\n  Vue\n\u003C\u002Flabel>\n\n\u003Clabel>\n  \u003Cinput v-model=\"selectedTags\" type=\"checkbox\" value=\"router\">\n  Router\n\u003C\u002Flabel>\n",[36,819,820,828,833,838,846,850,858,863,868],{"__ignoreMap":34},[39,821,822,824,826],{"class":41,"line":42},[39,823,128],{"class":60},[39,825,791],{"class":131},[39,827,169],{"class":60},[39,829,830],{"class":41,"line":64},[39,831,832],{"class":60},"  \u003Cinput v-model=\"selectedTags\" type=\"checkbox\" value=\"vue\">\n",[39,834,835],{"class":41,"line":89},[39,836,837],{"class":60},"  Vue\n",[39,839,840,842,844],{"class":41,"line":110},[39,841,179],{"class":60},[39,843,791],{"class":131},[39,845,169],{"class":60},[39,847,848],{"class":41,"line":236},[39,849,501],{"emptyLinePlaceholder":500},[39,851,852,854,856],{"class":41,"line":531},[39,853,128],{"class":60},[39,855,791],{"class":131},[39,857,169],{"class":60},[39,859,860],{"class":41,"line":536},[39,861,862],{"class":60},"  \u003Cinput v-model=\"selectedTags\" type=\"checkbox\" value=\"router\">\n",[39,864,865],{"class":41,"line":546},[39,866,867],{"class":60},"  Router\n",[39,869,870,872,874],{"class":41,"line":565},[39,871,179],{"class":60},[39,873,791],{"class":131},[39,875,169],{"class":60},[29,877,879],{"className":31,"code":878,"language":33,"meta":34,"style":34},"const selectedTags = ref([])\n",[36,880,881],{"__ignoreMap":34},[39,882,883,885,888,890,892],{"class":41,"line":42},[39,884,46],{"class":45},[39,886,887],{"class":49}," selectedTags",[39,889,53],{"class":45},[39,891,57],{"class":56},[39,893,894],{"class":60},"([])\n",[14,896,897],{},"选中后，数组里会有对应 value。",[21,899,901],{"id":900},"_5-表单修饰符","5. 表单修饰符",[14,903,904],{},"去掉前后空格：",[29,906,908],{"className":119,"code":907,"language":121,"meta":34,"style":34},"\u003Cinput v-model.trim=\"title\">\n",[36,909,910],{"__ignoreMap":34},[39,911,912,914,916,918,921,924,926,928,930,932],{"class":41,"line":42},[39,913,128],{"class":60},[39,915,552],{"class":131},[39,917,555],{"class":56},[39,919,920],{"class":60},".",[39,922,923],{"class":56},"trim",[39,925,138],{"class":60},[39,927,141],{"class":70},[39,929,598],{"class":60},[39,931,141],{"class":70},[39,933,169],{"class":60},[14,935,936],{},"转换数字：",[29,938,940],{"className":119,"code":939,"language":121,"meta":34,"style":34},"\u003Cinput v-model.number=\"minutes\" type=\"number\">\n",[36,941,942],{"__ignoreMap":34},[39,943,944,946,948,950,952,955,957,959,962,964,967,969,972],{"class":41,"line":42},[39,945,128],{"class":60},[39,947,552],{"class":131},[39,949,555],{"class":56},[39,951,920],{"class":60},[39,953,954],{"class":56},"number",[39,956,138],{"class":60},[39,958,141],{"class":70},[39,960,961],{"class":60},"minutes",[39,963,141],{"class":70},[39,965,966],{"class":56}," type",[39,968,138],{"class":60},[39,970,971],{"class":70},"\"number\"",[39,973,169],{"class":60},[14,975,976],{},"输入框失焦后才同步：",[29,978,980],{"className":119,"code":979,"language":121,"meta":34,"style":34},"\u003Cinput v-model.lazy=\"title\">\n",[36,981,982],{"__ignoreMap":34},[39,983,984,986,988,990,992,995,997,999,1001,1003],{"class":41,"line":42},[39,985,128],{"class":60},[39,987,552],{"class":131},[39,989,555],{"class":56},[39,991,920],{"class":60},[39,993,994],{"class":56},"lazy",[39,996,138],{"class":60},[39,998,141],{"class":70},[39,1000,598],{"class":60},[39,1002,141],{"class":70},[39,1004,169],{"class":60},[14,1006,1007],{},"表单提交阻止刷新：",[29,1009,1011],{"className":119,"code":1010,"language":121,"meta":34,"style":34},"\u003Cform @submit.prevent=\"submit\">\n",[36,1012,1013],{"__ignoreMap":34},[39,1014,1015,1017,1020,1022,1025,1027,1030,1032,1034,1036,1038],{"class":41,"line":42},[39,1016,128],{"class":60},[39,1018,1019],{"class":131},"form",[39,1021,637],{"class":60},[39,1023,1024],{"class":56},"submit",[39,1026,920],{"class":60},[39,1028,1029],{"class":56},"prevent",[39,1031,138],{"class":60},[39,1033,141],{"class":70},[39,1035,1024],{"class":60},[39,1037,141],{"class":70},[39,1039,169],{"class":60},[14,1041,1042],{},"这些修饰符不是必须用，但它们能减少重复代码。",[21,1044,1046],{"id":1045},"_6-基础表单校验","6. 基础表单校验",[14,1048,1049],{},"状态：",[29,1051,1053],{"className":31,"code":1052,"language":33,"meta":34,"style":34},"const title = ref('')\n",[36,1054,1055],{"__ignoreMap":34},[39,1056,1057,1059,1061,1063,1065,1067,1069],{"class":41,"line":42},[39,1058,46],{"class":45},[39,1060,508],{"class":49},[39,1062,53],{"class":45},[39,1064,57],{"class":56},[39,1066,279],{"class":60},[39,1068,517],{"class":70},[39,1070,520],{"class":60},[14,1072,1073,1074,1077],{},"错误信息用 ",[36,1075,1076],{},"computed","：",[29,1079,1081],{"className":31,"code":1080,"language":33,"meta":34,"style":34},"const titleError = computed(() => {\n  if (!title.value.trim()) {\n    return '标题不能为空'\n  }\n\n  if (title.value.length > 30) {\n    return '标题不能超过 30 个字符'\n  }\n\n  return ''\n})\n",[36,1082,1083,1100,1119,1127,1132,1136,1155,1162,1166,1170,1177],{"__ignoreMap":34},[39,1084,1085,1087,1090,1092,1094,1096,1098],{"class":41,"line":42},[39,1086,46],{"class":45},[39,1088,1089],{"class":49}," titleError",[39,1091,53],{"class":45},[39,1093,343],{"class":56},[39,1095,346],{"class":60},[39,1097,349],{"class":45},[39,1099,209],{"class":60},[39,1101,1102,1105,1108,1111,1114,1116],{"class":41,"line":64},[39,1103,1104],{"class":45},"  if",[39,1106,1107],{"class":60}," (",[39,1109,1110],{"class":45},"!",[39,1112,1113],{"class":60},"title.value.",[39,1115,923],{"class":56},[39,1117,1118],{"class":60},"()) {\n",[39,1120,1121,1124],{"class":41,"line":89},[39,1122,1123],{"class":45},"    return",[39,1125,1126],{"class":70}," '标题不能为空'\n",[39,1128,1129],{"class":41,"line":110},[39,1130,1131],{"class":60},"  }\n",[39,1133,1134],{"class":41,"line":236},[39,1135,501],{"emptyLinePlaceholder":500},[39,1137,1138,1140,1143,1146,1149,1152],{"class":41,"line":531},[39,1139,1104],{"class":45},[39,1141,1142],{"class":60}," (title.value.",[39,1144,1145],{"class":49},"length",[39,1147,1148],{"class":45}," >",[39,1150,1151],{"class":49}," 30",[39,1153,1154],{"class":60},") {\n",[39,1156,1157,1159],{"class":41,"line":536},[39,1158,1123],{"class":45},[39,1160,1161],{"class":70}," '标题不能超过 30 个字符'\n",[39,1163,1164],{"class":41,"line":546},[39,1165,1131],{"class":60},[39,1167,1168],{"class":41,"line":565},[39,1169,501],{"emptyLinePlaceholder":500},[39,1171,1172,1174],{"class":41,"line":579},[39,1173,356],{"class":45},[39,1175,1176],{"class":70}," ''\n",[39,1178,1180],{"class":41,"line":1179},11,[39,1181,381],{"class":60},[14,1183,1184],{},"提交按钮是否可用：",[29,1186,1188],{"className":31,"code":1187,"language":33,"meta":34,"style":34},"const canSubmit = computed(() => !titleError.value)\n",[36,1189,1190],{"__ignoreMap":34},[39,1191,1192,1194,1197,1199,1201,1203,1205,1207],{"class":41,"line":42},[39,1193,46],{"class":45},[39,1195,1196],{"class":49}," canSubmit",[39,1198,53],{"class":45},[39,1200,343],{"class":56},[39,1202,346],{"class":60},[39,1204,349],{"class":45},[39,1206,289],{"class":45},[39,1208,1209],{"class":60},"titleError.value)\n",[14,1211,1212],{},"提交：",[29,1214,1216],{"className":31,"code":1215,"language":33,"meta":34,"style":34},"function submit() {\n  if (!canSubmit.value) {\n    return\n  }\n\n  tasks.value.unshift({\n    id: crypto.randomUUID(),\n    title: title.value.trim(),\n    done: false\n  })\n\n  title.value = ''\n}\n",[36,1217,1218,1229,1240,1245,1249,1253,1264,1273,1282,1289,1294,1298,1308],{"__ignoreMap":34},[39,1219,1220,1223,1226],{"class":41,"line":42},[39,1221,1222],{"class":45},"function",[39,1224,1225],{"class":56}," submit",[39,1227,1228],{"class":60},"() {\n",[39,1230,1231,1233,1235,1237],{"class":41,"line":64},[39,1232,1104],{"class":45},[39,1234,1107],{"class":60},[39,1236,1110],{"class":45},[39,1238,1239],{"class":60},"canSubmit.value) {\n",[39,1241,1242],{"class":41,"line":89},[39,1243,1244],{"class":45},"    return\n",[39,1246,1247],{"class":41,"line":110},[39,1248,1131],{"class":60},[39,1250,1251],{"class":41,"line":236},[39,1252,501],{"emptyLinePlaceholder":500},[39,1254,1255,1258,1261],{"class":41,"line":531},[39,1256,1257],{"class":60},"  tasks.value.",[39,1259,1260],{"class":56},"unshift",[39,1262,1263],{"class":60},"({\n",[39,1265,1266,1269,1271],{"class":41,"line":536},[39,1267,1268],{"class":60},"    id: crypto.",[39,1270,217],{"class":56},[39,1272,220],{"class":60},[39,1274,1275,1278,1280],{"class":41,"line":546},[39,1276,1277],{"class":60},"    title: title.value.",[39,1279,923],{"class":56},[39,1281,220],{"class":60},[39,1283,1284,1287],{"class":41,"line":565},[39,1285,1286],{"class":60},"    done: ",[39,1288,233],{"class":49},[39,1290,1291],{"class":41,"line":579},[39,1292,1293],{"class":60},"  })\n",[39,1295,1296],{"class":41,"line":1179},[39,1297,501],{"emptyLinePlaceholder":500},[39,1299,1301,1304,1306],{"class":41,"line":1300},12,[39,1302,1303],{"class":60},"  title.value ",[39,1305,138],{"class":45},[39,1307,1176],{"class":70},[39,1309,1311],{"class":41,"line":1310},13,[39,1312,239],{"class":60},[14,1314,1315],{},"模板：",[29,1317,1319],{"className":119,"code":1318,"language":121,"meta":34,"style":34},"\u003Cform @submit.prevent=\"submit\">\n  \u003Clabel for=\"task-title\">任务标题\u003C\u002Flabel>\n  \u003Cinput id=\"task-title\" v-model.trim=\"title\">\n  \u003Cp v-if=\"titleError\" role=\"alert\">{{ titleError }}\u003C\u002Fp>\n  \u003Cbutton :disabled=\"!canSubmit\">新增\u003C\u002Fbutton>\n\u003C\u002Fform>\n",[36,1320,1321,1345,1350,1355,1360,1365],{"__ignoreMap":34},[39,1322,1323,1325,1327,1329,1331,1333,1335,1337,1339,1341,1343],{"class":41,"line":42},[39,1324,128],{"class":60},[39,1326,1019],{"class":131},[39,1328,637],{"class":60},[39,1330,1024],{"class":56},[39,1332,920],{"class":60},[39,1334,1029],{"class":56},[39,1336,138],{"class":60},[39,1338,141],{"class":70},[39,1340,1024],{"class":60},[39,1342,141],{"class":70},[39,1344,169],{"class":60},[39,1346,1347],{"class":41,"line":64},[39,1348,1349],{"class":60},"  \u003Clabel for=\"task-title\">任务标题\u003C\u002Flabel>\n",[39,1351,1352],{"class":41,"line":89},[39,1353,1354],{"class":60},"  \u003Cinput id=\"task-title\" v-model.trim=\"title\">\n",[39,1356,1357],{"class":41,"line":110},[39,1358,1359],{"class":60},"  \u003Cp v-if=\"titleError\" role=\"alert\">{{ titleError }}\u003C\u002Fp>\n",[39,1361,1362],{"class":41,"line":236},[39,1363,1364],{"class":60},"  \u003Cbutton :disabled=\"!canSubmit\">新增\u003C\u002Fbutton>\n",[39,1366,1367,1369,1371],{"class":41,"line":531},[39,1368,179],{"class":60},[39,1370,1019],{"class":131},[39,1372,169],{"class":60},[21,1374,1376],{"id":1375},"_7-为什么错误信息用字符串而不是布尔值","7. 为什么错误信息用字符串而不是布尔值",[14,1378,1379],{},"你可能想写：",[29,1381,1383],{"className":31,"code":1382,"language":33,"meta":34,"style":34},"const hasError = computed(() => !title.value.trim())\n",[36,1384,1385],{"__ignoreMap":34},[39,1386,1387,1389,1392,1394,1396,1398,1400,1402,1404,1406],{"class":41,"line":42},[39,1388,46],{"class":45},[39,1390,1391],{"class":49}," hasError",[39,1393,53],{"class":45},[39,1395,343],{"class":56},[39,1397,346],{"class":60},[39,1399,349],{"class":45},[39,1401,289],{"class":45},[39,1403,1113],{"class":60},[39,1405,923],{"class":56},[39,1407,1408],{"class":60},"())\n",[14,1410,1411],{},"这只能告诉你“有没有错”，不能告诉用户“错在哪里”。",[14,1413,1414],{},"更好的方式是返回错误文本：",[29,1416,1418],{"className":31,"code":1417,"language":33,"meta":34,"style":34},"const titleError = computed(() => {\n  if (!title.value.trim()) return '标题不能为空'\n  if (title.value.length > 30) return '标题不能超过 30 个字符'\n  return ''\n})\n",[36,1419,1420,1436,1456,1474,1480],{"__ignoreMap":34},[39,1421,1422,1424,1426,1428,1430,1432,1434],{"class":41,"line":42},[39,1423,46],{"class":45},[39,1425,1089],{"class":49},[39,1427,53],{"class":45},[39,1429,343],{"class":56},[39,1431,346],{"class":60},[39,1433,349],{"class":45},[39,1435,209],{"class":60},[39,1437,1438,1440,1442,1444,1446,1448,1451,1454],{"class":41,"line":64},[39,1439,1104],{"class":45},[39,1441,1107],{"class":60},[39,1443,1110],{"class":45},[39,1445,1113],{"class":60},[39,1447,923],{"class":56},[39,1449,1450],{"class":60},"()) ",[39,1452,1453],{"class":45},"return",[39,1455,1126],{"class":70},[39,1457,1458,1460,1462,1464,1466,1468,1470,1472],{"class":41,"line":89},[39,1459,1104],{"class":45},[39,1461,1142],{"class":60},[39,1463,1145],{"class":49},[39,1465,1148],{"class":45},[39,1467,1151],{"class":49},[39,1469,369],{"class":60},[39,1471,1453],{"class":45},[39,1473,1161],{"class":70},[39,1475,1476,1478],{"class":41,"line":110},[39,1477,356],{"class":45},[39,1479,1176],{"class":70},[39,1481,1482],{"class":41,"line":236},[39,1483,381],{"class":60},[14,1485,1486],{},"这样同一个值既能判断是否有错，也能显示错误。",[21,1488,1490],{"id":1489},"_8-列表筛选","8. 列表筛选",[14,1492,1049],{},[29,1494,1496],{"className":31,"code":1495,"language":33,"meta":34,"style":34},"const filter = ref('all')\n",[36,1497,1498],{"__ignoreMap":34},[39,1499,1500,1502,1505,1507,1509,1511,1514],{"class":41,"line":42},[39,1501,46],{"class":45},[39,1503,1504],{"class":49}," filter",[39,1506,53],{"class":45},[39,1508,57],{"class":56},[39,1510,279],{"class":60},[39,1512,1513],{"class":70},"'all'",[39,1515,520],{"class":60},[14,1517,1518],{},"筛选结果：",[29,1520,1522],{"className":31,"code":1521,"language":33,"meta":34,"style":34},"const filteredTasks = computed(() => {\n  if (filter.value === 'active') {\n    return tasks.value.filter((task) => !task.done)\n  }\n\n  if (filter.value === 'completed') {\n    return tasks.value.filter((task) => task.done)\n  }\n\n  return tasks.value\n})\n",[36,1523,1524,1541,1556,1576,1580,1584,1597,1616,1620,1624,1631],{"__ignoreMap":34},[39,1525,1526,1528,1531,1533,1535,1537,1539],{"class":41,"line":42},[39,1527,46],{"class":45},[39,1529,1530],{"class":49}," filteredTasks",[39,1532,53],{"class":45},[39,1534,343],{"class":56},[39,1536,346],{"class":60},[39,1538,349],{"class":45},[39,1540,209],{"class":60},[39,1542,1543,1545,1548,1551,1554],{"class":41,"line":64},[39,1544,1104],{"class":45},[39,1546,1547],{"class":60}," (filter.value ",[39,1549,1550],{"class":45},"===",[39,1552,1553],{"class":70}," 'active'",[39,1555,1154],{"class":60},[39,1557,1558,1560,1562,1564,1566,1568,1570,1572,1574],{"class":41,"line":89},[39,1559,1123],{"class":45},[39,1561,359],{"class":60},[39,1563,276],{"class":56},[39,1565,364],{"class":60},[39,1567,283],{"class":282},[39,1569,369],{"class":60},[39,1571,349],{"class":45},[39,1573,289],{"class":45},[39,1575,376],{"class":60},[39,1577,1578],{"class":41,"line":110},[39,1579,1131],{"class":60},[39,1581,1582],{"class":41,"line":236},[39,1583,501],{"emptyLinePlaceholder":500},[39,1585,1586,1588,1590,1592,1595],{"class":41,"line":531},[39,1587,1104],{"class":45},[39,1589,1547],{"class":60},[39,1591,1550],{"class":45},[39,1593,1594],{"class":70}," 'completed'",[39,1596,1154],{"class":60},[39,1598,1599,1601,1603,1605,1607,1609,1611,1613],{"class":41,"line":536},[39,1600,1123],{"class":45},[39,1602,359],{"class":60},[39,1604,276],{"class":56},[39,1606,364],{"class":60},[39,1608,283],{"class":282},[39,1610,369],{"class":60},[39,1612,349],{"class":45},[39,1614,1615],{"class":60}," task.done)\n",[39,1617,1618],{"class":41,"line":546},[39,1619,1131],{"class":60},[39,1621,1622],{"class":41,"line":565},[39,1623,501],{"emptyLinePlaceholder":500},[39,1625,1626,1628],{"class":41,"line":579},[39,1627,356],{"class":45},[39,1629,1630],{"class":60}," tasks.value\n",[39,1632,1633],{"class":41,"line":1179},[39,1634,381],{"class":60},[14,1636,1315],{},[29,1638,1640],{"className":119,"code":1639,"language":121,"meta":34,"style":34},"\u003Cbutton @click=\"filter = 'all'\">全部\u003C\u002Fbutton>\n\u003Cbutton @click=\"filter = 'active'\">未完成\u003C\u002Fbutton>\n\u003Cbutton @click=\"filter = 'completed'\">已完成\u003C\u002Fbutton>\n\n\u003Cul>\n  \u003Cli v-for=\"task in filteredTasks\" :key=\"task.id\">\n    {{ task.title }}\n  \u003C\u002Fli>\n\u003C\u002Ful>\n",[36,1641,1642,1673,1701,1729,1733,1741,1746,1751,1756],{"__ignoreMap":34},[39,1643,1644,1646,1649,1651,1654,1656,1658,1661,1663,1666,1669,1671],{"class":41,"line":42},[39,1645,128],{"class":60},[39,1647,1648],{"class":131},"button",[39,1650,637],{"class":60},[39,1652,1653],{"class":56},"click",[39,1655,138],{"class":60},[39,1657,141],{"class":70},[39,1659,1660],{"class":60},"filter ",[39,1662,138],{"class":45},[39,1664,1665],{"class":70}," 'all'\"",[39,1667,1668],{"class":60},">全部\u003C\u002F",[39,1670,1648],{"class":131},[39,1672,169],{"class":60},[39,1674,1675,1677,1679,1681,1683,1685,1687,1689,1691,1694,1697,1699],{"class":41,"line":64},[39,1676,128],{"class":60},[39,1678,1648],{"class":131},[39,1680,637],{"class":60},[39,1682,1653],{"class":56},[39,1684,138],{"class":60},[39,1686,141],{"class":70},[39,1688,1660],{"class":60},[39,1690,138],{"class":45},[39,1692,1693],{"class":70}," 'active'\"",[39,1695,1696],{"class":60},">未完成\u003C\u002F",[39,1698,1648],{"class":131},[39,1700,169],{"class":60},[39,1702,1703,1705,1707,1709,1711,1713,1715,1717,1719,1722,1725,1727],{"class":41,"line":89},[39,1704,128],{"class":60},[39,1706,1648],{"class":131},[39,1708,637],{"class":60},[39,1710,1653],{"class":56},[39,1712,138],{"class":60},[39,1714,141],{"class":70},[39,1716,1660],{"class":60},[39,1718,138],{"class":45},[39,1720,1721],{"class":70}," 'completed'\"",[39,1723,1724],{"class":60},">已完成\u003C\u002F",[39,1726,1648],{"class":131},[39,1728,169],{"class":60},[39,1730,1731],{"class":41,"line":110},[39,1732,501],{"emptyLinePlaceholder":500},[39,1734,1735,1737,1739],{"class":41,"line":236},[39,1736,128],{"class":60},[39,1738,437],{"class":131},[39,1740,169],{"class":60},[39,1742,1743],{"class":41,"line":531},[39,1744,1745],{"class":60},"  \u003Cli v-for=\"task in filteredTasks\" :key=\"task.id\">\n",[39,1747,1748],{"class":41,"line":536},[39,1749,1750],{"class":60},"    {{ task.title }}\n",[39,1752,1753],{"class":41,"line":546},[39,1754,1755],{"class":60},"  \u003C\u002Fli>\n",[39,1757,1758,1760,1762],{"class":41,"line":565},[39,1759,179],{"class":60},[39,1761,437],{"class":131},[39,1763,169],{"class":60},[14,1765,1766,1767,1769],{},"这里的 ",[36,1768,276],{}," 是页面局部状态。如果只是当前组件使用，不需要放 Pinia。",[21,1771,1773],{"id":1772},"_9-动态-class","9. 动态 class",[14,1775,1776],{},"根据状态切换样式：",[29,1778,1780],{"className":119,"code":1779,"language":121,"meta":34,"style":34},"\u003Cli :class=\"{ done: task.done, urgent: task.priority === 'high' }\">\n  {{ task.title }}\n\u003C\u002Fli>\n",[36,1781,1782,1812,1816],{"__ignoreMap":34},[39,1783,1784,1786,1788,1790,1793,1795,1797,1800,1802,1805,1808,1810],{"class":41,"line":42},[39,1785,128],{"class":60},[39,1787,132],{"class":131},[39,1789,154],{"class":60},[39,1791,1792],{"class":56},"class",[39,1794,138],{"class":60},[39,1796,141],{"class":70},[39,1798,1799],{"class":60},"{ done: task.done, urgent: task.priority ",[39,1801,1550],{"class":45},[39,1803,1804],{"class":70}," 'high'",[39,1806,1807],{"class":60}," }",[39,1809,141],{"class":70},[39,1811,169],{"class":60},[39,1813,1814],{"class":41,"line":64},[39,1815,174],{"class":60},[39,1817,1818,1820,1822],{"class":41,"line":89},[39,1819,179],{"class":60},[39,1821,132],{"class":131},[39,1823,169],{"class":60},[14,1825,1826],{},"CSS：",[29,1828,1832],{"className":1829,"code":1830,"language":1831,"meta":34,"style":34},"language-css shiki shiki-themes github-light github-dark",".done {\n  color: #64748b;\n  text-decoration: line-through;\n}\n\n.urgent {\n  border-left: 4px solid #dc2626;\n}\n","css",[36,1833,1834,1841,1855,1867,1871,1875,1882,1903],{"__ignoreMap":34},[39,1835,1836,1839],{"class":41,"line":42},[39,1837,1838],{"class":56},".done",[39,1840,209],{"class":60},[39,1842,1843,1846,1849,1852],{"class":41,"line":64},[39,1844,1845],{"class":49},"  color",[39,1847,1848],{"class":60},": ",[39,1850,1851],{"class":49},"#64748b",[39,1853,1854],{"class":60},";\n",[39,1856,1857,1860,1862,1865],{"class":41,"line":89},[39,1858,1859],{"class":49},"  text-decoration",[39,1861,1848],{"class":60},[39,1863,1864],{"class":49},"line-through",[39,1866,1854],{"class":60},[39,1868,1869],{"class":41,"line":110},[39,1870,239],{"class":60},[39,1872,1873],{"class":41,"line":236},[39,1874,501],{"emptyLinePlaceholder":500},[39,1876,1877,1880],{"class":41,"line":531},[39,1878,1879],{"class":56},".urgent",[39,1881,209],{"class":60},[39,1883,1884,1887,1889,1892,1895,1898,1901],{"class":41,"line":536},[39,1885,1886],{"class":49},"  border-left",[39,1888,1848],{"class":60},[39,1890,1891],{"class":49},"4",[39,1893,1894],{"class":45},"px",[39,1896,1897],{"class":49}," solid",[39,1899,1900],{"class":49}," #dc2626",[39,1902,1854],{"class":60},[39,1904,1905],{"class":41,"line":546},[39,1906,239],{"class":60},[14,1908,1909],{},"数组写法：",[29,1911,1913],{"className":119,"code":1912,"language":121,"meta":34,"style":34},"\u003Cbutton :class=\"['button', variant, { loading }]\">\n  保存\n\u003C\u002Fbutton>\n",[36,1914,1915,1942,1947],{"__ignoreMap":34},[39,1916,1917,1919,1921,1923,1925,1927,1929,1932,1935,1938,1940],{"class":41,"line":42},[39,1918,128],{"class":60},[39,1920,1648],{"class":131},[39,1922,154],{"class":60},[39,1924,1792],{"class":56},[39,1926,138],{"class":60},[39,1928,141],{"class":70},[39,1930,1931],{"class":60},"[",[39,1933,1934],{"class":70},"'button'",[39,1936,1937],{"class":60},", variant, { loading }]",[39,1939,141],{"class":70},[39,1941,169],{"class":60},[39,1943,1944],{"class":41,"line":64},[39,1945,1946],{"class":60},"  保存\n",[39,1948,1949,1951,1953],{"class":41,"line":89},[39,1950,179],{"class":60},[39,1952,1648],{"class":131},[39,1954,169],{"class":60},[14,1956,1957],{},"对象适合开关类名，数组适合组合多个类名。",[21,1959,1961],{"id":1960},"_10-动态-style","10. 动态 style",[14,1963,1964],{},"动态 style 适合少量数值样式：",[29,1966,1968],{"className":119,"code":1967,"language":121,"meta":34,"style":34},"\u003Cdiv class=\"progress-fill\" :style=\"{ width: progress + '%' }\">\u003C\u002Fdiv>\n",[36,1969,1970],{"__ignoreMap":34},[39,1971,1972,1974,1977,1980,1982,1985,1987,1990,1992,1994,1997,2000,2003,2005,2007,2009,2011],{"class":41,"line":42},[39,1973,128],{"class":60},[39,1975,1976],{"class":131},"div",[39,1978,1979],{"class":56}," class",[39,1981,138],{"class":60},[39,1983,1984],{"class":70},"\"progress-fill\"",[39,1986,154],{"class":60},[39,1988,1989],{"class":56},"style",[39,1991,138],{"class":60},[39,1993,141],{"class":70},[39,1995,1996],{"class":60},"{ width: progress ",[39,1998,1999],{"class":45},"+",[39,2001,2002],{"class":70}," '%'",[39,2004,1807],{"class":60},[39,2006,141],{"class":70},[39,2008,721],{"class":60},[39,2010,1976],{"class":131},[39,2012,169],{"class":60},[14,2014,2015,2016,2019],{},"不建议把大量样式都写到 ",[36,2017,2018],{},":style"," 里。复杂样式优先用 class。",[21,2021,2023],{"id":2022},"_11-空状态加载和错误","11. 空状态、加载和错误",[14,2025,2026],{},"任何真实列表都不应该只写成功状态。",[29,2028,2030],{"className":119,"code":2029,"language":121,"meta":34,"style":34},"\u003Cp v-if=\"loading\">加载中...\u003C\u002Fp>\n\u003Cp v-else-if=\"error\" role=\"alert\">{{ error }}\u003C\u002Fp>\n\u003Cp v-else-if=\"filteredTasks.length === 0\">暂无任务\u003C\u002Fp>\n\u003Cul v-else>\n  \u003Cli v-for=\"task in filteredTasks\" :key=\"task.id\">\n    {{ task.title }}\n  \u003C\u002Fli>\n\u003C\u002Ful>\n",[36,2031,2032,2057,2090,2122,2133,2137,2141,2145],{"__ignoreMap":34},[39,2033,2034,2036,2038,2041,2043,2045,2048,2050,2053,2055],{"class":41,"line":42},[39,2035,128],{"class":60},[39,2037,14],{"class":131},[39,2039,2040],{"class":45}," v-if",[39,2042,138],{"class":60},[39,2044,141],{"class":70},[39,2046,2047],{"class":60},"loading",[39,2049,141],{"class":70},[39,2051,2052],{"class":60},">加载中...\u003C\u002F",[39,2054,14],{"class":131},[39,2056,169],{"class":60},[39,2058,2059,2061,2063,2066,2068,2070,2073,2075,2078,2080,2083,2086,2088],{"class":41,"line":64},[39,2060,128],{"class":60},[39,2062,14],{"class":131},[39,2064,2065],{"class":45}," v-else-if",[39,2067,138],{"class":60},[39,2069,141],{"class":70},[39,2071,2072],{"class":60},"error",[39,2074,141],{"class":70},[39,2076,2077],{"class":56}," role",[39,2079,138],{"class":60},[39,2081,2082],{"class":70},"\"alert\"",[39,2084,2085],{"class":60},">{{ error }}\u003C\u002F",[39,2087,14],{"class":131},[39,2089,169],{"class":60},[39,2091,2092,2094,2096,2098,2100,2102,2105,2107,2110,2113,2115,2118,2120],{"class":41,"line":89},[39,2093,128],{"class":60},[39,2095,14],{"class":131},[39,2097,2065],{"class":45},[39,2099,138],{"class":60},[39,2101,141],{"class":70},[39,2103,2104],{"class":60},"filteredTasks.",[39,2106,1145],{"class":49},[39,2108,2109],{"class":45}," ===",[39,2111,2112],{"class":49}," 0",[39,2114,141],{"class":70},[39,2116,2117],{"class":60},">暂无任务\u003C\u002F",[39,2119,14],{"class":131},[39,2121,169],{"class":60},[39,2123,2124,2126,2128,2131],{"class":41,"line":110},[39,2125,128],{"class":60},[39,2127,437],{"class":131},[39,2129,2130],{"class":45}," v-else",[39,2132,169],{"class":60},[39,2134,2135],{"class":41,"line":236},[39,2136,1745],{"class":60},[39,2138,2139],{"class":41,"line":531},[39,2140,1750],{"class":60},[39,2142,2143],{"class":41,"line":536},[39,2144,1755],{"class":60},[39,2146,2147,2149,2151],{"class":41,"line":546},[39,2148,179],{"class":60},[39,2150,437],{"class":131},[39,2152,169],{"class":60},[14,2154,2155],{},"四种状态：",[437,2157,2158,2161,2164,2167],{},[132,2159,2160],{},"loading：正在加载。",[132,2162,2163],{},"error：加载失败。",[132,2165,2166],{},"empty：加载成功但没有数据。",[132,2168,2169],{},"success：有数据。",[14,2171,2172],{},"初学者经常只写 success，真实项目必须补全其他状态。",[21,2174,2176],{"id":2175},"_12-表单可访问性","12. 表单可访问性",[14,2178,2179],{},"不要只用 placeholder 当标签。",[14,2181,249],{},[29,2183,2185],{"className":119,"code":2184,"language":121,"meta":34,"style":34},"\u003Cinput placeholder=\"任务标题\">\n",[36,2186,2187],{"__ignoreMap":34},[39,2188,2189,2191,2193,2196,2198,2201],{"class":41,"line":42},[39,2190,128],{"class":60},[39,2192,552],{"class":131},[39,2194,2195],{"class":56}," placeholder",[39,2197,138],{"class":60},[39,2199,2200],{"class":70},"\"任务标题\"",[39,2202,169],{"class":60},[14,2204,326],{},[29,2206,2208],{"className":119,"code":2207,"language":121,"meta":34,"style":34},"\u003Clabel for=\"task-title\">任务标题\u003C\u002Flabel>\n\u003Cinput id=\"task-title\" v-model=\"title\" placeholder=\"例如：学习组件通信\">\n",[36,2209,2210,2231],{"__ignoreMap":34},[39,2211,2212,2214,2216,2219,2221,2224,2227,2229],{"class":41,"line":42},[39,2213,128],{"class":60},[39,2215,791],{"class":131},[39,2217,2218],{"class":56}," for",[39,2220,138],{"class":60},[39,2222,2223],{"class":70},"\"task-title\"",[39,2225,2226],{"class":60},">任务标题\u003C\u002F",[39,2228,791],{"class":131},[39,2230,169],{"class":60},[39,2232,2233,2235,2237,2240,2242,2244,2246,2248,2250,2252,2254,2256,2258,2261],{"class":41,"line":64},[39,2234,128],{"class":60},[39,2236,552],{"class":131},[39,2238,2239],{"class":56}," id",[39,2241,138],{"class":60},[39,2243,2223],{"class":70},[39,2245,555],{"class":56},[39,2247,138],{"class":60},[39,2249,141],{"class":70},[39,2251,598],{"class":60},[39,2253,141],{"class":70},[39,2255,2195],{"class":56},[39,2257,138],{"class":60},[39,2259,2260],{"class":70},"\"例如：学习组件通信\"",[39,2262,169],{"class":60},[14,2264,2265],{},"原因：",[437,2267,2268,2271,2274],{},[132,2269,2270],{},"placeholder 输入后会消失。",[132,2272,2273],{},"屏幕阅读器更需要 label。",[132,2275,2276],{},"点击 label 可以聚焦对应输入框。",[14,2278,2279],{},"错误提示：",[29,2281,2283],{"className":119,"code":2282,"language":121,"meta":34,"style":34},"\u003Cp v-if=\"titleError\" role=\"alert\">{{ titleError }}\u003C\u002Fp>\n",[36,2284,2285],{"__ignoreMap":34},[39,2286,2287,2289,2291,2293,2295,2297,2300,2302,2304,2306,2308,2311,2313],{"class":41,"line":42},[39,2288,128],{"class":60},[39,2290,14],{"class":131},[39,2292,2040],{"class":45},[39,2294,138],{"class":60},[39,2296,141],{"class":70},[39,2298,2299],{"class":60},"titleError",[39,2301,141],{"class":70},[39,2303,2077],{"class":56},[39,2305,138],{"class":60},[39,2307,2082],{"class":70},[39,2309,2310],{"class":60},">{{ titleError }}\u003C\u002F",[39,2312,14],{"class":131},[39,2314,169],{"class":60},[14,2316,2317,2320],{},[36,2318,2319],{},"role=\"alert\""," 能帮助辅助技术知道这里出现了重要反馈。",[21,2322,2324],{"id":2323},"_13-完整任务表单例子","13. 完整任务表单例子",[29,2326,2328],{"className":119,"code":2327,"language":121,"meta":34,"style":34},"\u003Cscript setup>\nimport { computed, ref } from 'vue'\n\nconst title = ref('')\nconst priority = ref('normal')\nconst filter = ref('all')\nconst tasks = ref([])\n\nconst titleError = computed(() => {\n  if (!title.value.trim()) return '标题不能为空'\n  if (title.value.length > 30) return '标题不能超过 30 个字符'\n  return ''\n})\n\nconst canSubmit = computed(() => !titleError.value)\n\nconst filteredTasks = computed(() => {\n  if (filter.value === 'active') return tasks.value.filter((task) => !task.done)\n  if (filter.value === 'completed') return tasks.value.filter((task) => task.done)\n  return tasks.value\n})\n\nfunction addTask() {\n  if (!canSubmit.value) return\n\n  tasks.value.unshift({\n    id: crypto.randomUUID(),\n    title: title.value.trim(),\n    priority: priority.value,\n    done: false\n  })\n\n  title.value = ''\n  priority.value = 'normal'\n}\n\nfunction toggleTask(id) {\n  const task = tasks.value.find((item) => item.id === id)\n\n  if (task) {\n    task.done = !task.done\n  }\n}\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cform @submit.prevent=\"addTask\">\n    \u003Clabel for=\"title\">任务标题\u003C\u002Flabel>\n    \u003Cinput id=\"title\" v-model.trim=\"title\">\n    \u003Cp v-if=\"titleError\" role=\"alert\">{{ titleError }}\u003C\u002Fp>\n\n    \u003Clabel for=\"priority\">优先级\u003C\u002Flabel>\n    \u003Cselect id=\"priority\" v-model=\"priority\">\n      \u003Coption value=\"low\">低\u003C\u002Foption>\n      \u003Coption value=\"normal\">普通\u003C\u002Foption>\n      \u003Coption value=\"high\">高\u003C\u002Foption>\n    \u003C\u002Fselect>\n\n    \u003Cbutton :disabled=\"!canSubmit\">新增任务\u003C\u002Fbutton>\n  \u003C\u002Fform>\n\n  \u003Cbutton @click=\"filter = 'all'\">全部\u003C\u002Fbutton>\n  \u003Cbutton @click=\"filter = 'active'\">未完成\u003C\u002Fbutton>\n  \u003Cbutton @click=\"filter = 'completed'\">已完成\u003C\u002Fbutton>\n\n  \u003Cp v-if=\"filteredTasks.length === 0\">暂无任务\u003C\u002Fp>\n\n  \u003Cul v-else>\n    \u003Cli\n      v-for=\"task in filteredTasks\"\n      :key=\"task.id\"\n      :class=\"{ done: task.done, urgent: task.priority === 'high' }\"\n    >\n      \u003Clabel>\n        \u003Cinput type=\"checkbox\" :checked=\"task.done\" @change=\"toggleTask(task.id)\">\n        {{ task.title }}\n      \u003C\u002Flabel>\n    \u003C\u002Fli>\n  \u003C\u002Ful>\n\u003C\u002Ftemplate>\n",[36,2329,2330,2340,2351,2355,2371,2389,2405,2417,2421,2437,2455,2473,2479,2483,2488,2507,2512,2529,2560,2589,2596,2601,2606,2616,2631,2636,2645,2654,2663,2669,2676,2681,2686,2695,2706,2711,2716,2730,2762,2767,2775,2788,2793,2798,2807,2812,2821,2838,2858,2880,2906,2911,2932,2953,2977,2998,3019,3029,3034,3056,3066,3071,3092,3112,3132,3137,3157,3162,3173,3181,3192,3203,3214,3220,3229,3262,3268,3278,3287,3296],{"__ignoreMap":34},[39,2331,2332,2334,2336,2338],{"class":41,"line":42},[39,2333,128],{"class":60},[39,2335,476],{"class":131},[39,2337,479],{"class":56},[39,2339,169],{"class":60},[39,2341,2342,2344,2347,2349],{"class":41,"line":64},[39,2343,486],{"class":45},[39,2345,2346],{"class":60}," { computed, ref } ",[39,2348,492],{"class":45},[39,2350,495],{"class":70},[39,2352,2353],{"class":41,"line":89},[39,2354,501],{"emptyLinePlaceholder":500},[39,2356,2357,2359,2361,2363,2365,2367,2369],{"class":41,"line":110},[39,2358,46],{"class":45},[39,2360,508],{"class":49},[39,2362,53],{"class":45},[39,2364,57],{"class":56},[39,2366,279],{"class":60},[39,2368,517],{"class":70},[39,2370,520],{"class":60},[39,2372,2373,2375,2378,2380,2382,2384,2387],{"class":41,"line":236},[39,2374,46],{"class":45},[39,2376,2377],{"class":49}," priority",[39,2379,53],{"class":45},[39,2381,57],{"class":56},[39,2383,279],{"class":60},[39,2385,2386],{"class":70},"'normal'",[39,2388,520],{"class":60},[39,2390,2391,2393,2395,2397,2399,2401,2403],{"class":41,"line":531},[39,2392,46],{"class":45},[39,2394,1504],{"class":49},[39,2396,53],{"class":45},[39,2398,57],{"class":56},[39,2400,279],{"class":60},[39,2402,1513],{"class":70},[39,2404,520],{"class":60},[39,2406,2407,2409,2411,2413,2415],{"class":41,"line":536},[39,2408,46],{"class":45},[39,2410,50],{"class":49},[39,2412,53],{"class":45},[39,2414,57],{"class":56},[39,2416,894],{"class":60},[39,2418,2419],{"class":41,"line":546},[39,2420,501],{"emptyLinePlaceholder":500},[39,2422,2423,2425,2427,2429,2431,2433,2435],{"class":41,"line":565},[39,2424,46],{"class":45},[39,2426,1089],{"class":49},[39,2428,53],{"class":45},[39,2430,343],{"class":56},[39,2432,346],{"class":60},[39,2434,349],{"class":45},[39,2436,209],{"class":60},[39,2438,2439,2441,2443,2445,2447,2449,2451,2453],{"class":41,"line":579},[39,2440,1104],{"class":45},[39,2442,1107],{"class":60},[39,2444,1110],{"class":45},[39,2446,1113],{"class":60},[39,2448,923],{"class":56},[39,2450,1450],{"class":60},[39,2452,1453],{"class":45},[39,2454,1126],{"class":70},[39,2456,2457,2459,2461,2463,2465,2467,2469,2471],{"class":41,"line":1179},[39,2458,1104],{"class":45},[39,2460,1142],{"class":60},[39,2462,1145],{"class":49},[39,2464,1148],{"class":45},[39,2466,1151],{"class":49},[39,2468,369],{"class":60},[39,2470,1453],{"class":45},[39,2472,1161],{"class":70},[39,2474,2475,2477],{"class":41,"line":1300},[39,2476,356],{"class":45},[39,2478,1176],{"class":70},[39,2480,2481],{"class":41,"line":1310},[39,2482,381],{"class":60},[39,2484,2486],{"class":41,"line":2485},14,[39,2487,501],{"emptyLinePlaceholder":500},[39,2489,2491,2493,2495,2497,2499,2501,2503,2505],{"class":41,"line":2490},15,[39,2492,46],{"class":45},[39,2494,1196],{"class":49},[39,2496,53],{"class":45},[39,2498,343],{"class":56},[39,2500,346],{"class":60},[39,2502,349],{"class":45},[39,2504,289],{"class":45},[39,2506,1209],{"class":60},[39,2508,2510],{"class":41,"line":2509},16,[39,2511,501],{"emptyLinePlaceholder":500},[39,2513,2515,2517,2519,2521,2523,2525,2527],{"class":41,"line":2514},17,[39,2516,46],{"class":45},[39,2518,1530],{"class":49},[39,2520,53],{"class":45},[39,2522,343],{"class":56},[39,2524,346],{"class":60},[39,2526,349],{"class":45},[39,2528,209],{"class":60},[39,2530,2532,2534,2536,2538,2540,2542,2544,2546,2548,2550,2552,2554,2556,2558],{"class":41,"line":2531},18,[39,2533,1104],{"class":45},[39,2535,1547],{"class":60},[39,2537,1550],{"class":45},[39,2539,1553],{"class":70},[39,2541,369],{"class":60},[39,2543,1453],{"class":45},[39,2545,359],{"class":60},[39,2547,276],{"class":56},[39,2549,364],{"class":60},[39,2551,283],{"class":282},[39,2553,369],{"class":60},[39,2555,349],{"class":45},[39,2557,289],{"class":45},[39,2559,376],{"class":60},[39,2561,2563,2565,2567,2569,2571,2573,2575,2577,2579,2581,2583,2585,2587],{"class":41,"line":2562},19,[39,2564,1104],{"class":45},[39,2566,1547],{"class":60},[39,2568,1550],{"class":45},[39,2570,1594],{"class":70},[39,2572,369],{"class":60},[39,2574,1453],{"class":45},[39,2576,359],{"class":60},[39,2578,276],{"class":56},[39,2580,364],{"class":60},[39,2582,283],{"class":282},[39,2584,369],{"class":60},[39,2586,349],{"class":45},[39,2588,1615],{"class":60},[39,2590,2592,2594],{"class":41,"line":2591},20,[39,2593,356],{"class":45},[39,2595,1630],{"class":60},[39,2597,2599],{"class":41,"line":2598},21,[39,2600,381],{"class":60},[39,2602,2604],{"class":41,"line":2603},22,[39,2605,501],{"emptyLinePlaceholder":500},[39,2607,2609,2611,2614],{"class":41,"line":2608},23,[39,2610,1222],{"class":45},[39,2612,2613],{"class":56}," addTask",[39,2615,1228],{"class":60},[39,2617,2619,2621,2623,2625,2628],{"class":41,"line":2618},24,[39,2620,1104],{"class":45},[39,2622,1107],{"class":60},[39,2624,1110],{"class":45},[39,2626,2627],{"class":60},"canSubmit.value) ",[39,2629,2630],{"class":45},"return\n",[39,2632,2634],{"class":41,"line":2633},25,[39,2635,501],{"emptyLinePlaceholder":500},[39,2637,2639,2641,2643],{"class":41,"line":2638},26,[39,2640,1257],{"class":60},[39,2642,1260],{"class":56},[39,2644,1263],{"class":60},[39,2646,2648,2650,2652],{"class":41,"line":2647},27,[39,2649,1268],{"class":60},[39,2651,217],{"class":56},[39,2653,220],{"class":60},[39,2655,2657,2659,2661],{"class":41,"line":2656},28,[39,2658,1277],{"class":60},[39,2660,923],{"class":56},[39,2662,220],{"class":60},[39,2664,2666],{"class":41,"line":2665},29,[39,2667,2668],{"class":60},"    priority: priority.value,\n",[39,2670,2672,2674],{"class":41,"line":2671},30,[39,2673,1286],{"class":60},[39,2675,233],{"class":49},[39,2677,2679],{"class":41,"line":2678},31,[39,2680,1293],{"class":60},[39,2682,2684],{"class":41,"line":2683},32,[39,2685,501],{"emptyLinePlaceholder":500},[39,2687,2689,2691,2693],{"class":41,"line":2688},33,[39,2690,1303],{"class":60},[39,2692,138],{"class":45},[39,2694,1176],{"class":70},[39,2696,2698,2701,2703],{"class":41,"line":2697},34,[39,2699,2700],{"class":60},"  priority.value ",[39,2702,138],{"class":45},[39,2704,2705],{"class":70}," 'normal'\n",[39,2707,2709],{"class":41,"line":2708},35,[39,2710,239],{"class":60},[39,2712,2714],{"class":41,"line":2713},36,[39,2715,501],{"emptyLinePlaceholder":500},[39,2717,2719,2721,2724,2726,2728],{"class":41,"line":2718},37,[39,2720,1222],{"class":45},[39,2722,2723],{"class":56}," toggleTask",[39,2725,279],{"class":60},[39,2727,188],{"class":282},[39,2729,1154],{"class":60},[39,2731,2733,2736,2738,2740,2742,2745,2747,2750,2752,2754,2757,2759],{"class":41,"line":2732},38,[39,2734,2735],{"class":45},"  const",[39,2737,204],{"class":49},[39,2739,53],{"class":45},[39,2741,359],{"class":60},[39,2743,2744],{"class":56},"find",[39,2746,364],{"class":60},[39,2748,2749],{"class":282},"item",[39,2751,369],{"class":60},[39,2753,349],{"class":45},[39,2755,2756],{"class":60}," item.id ",[39,2758,1550],{"class":45},[39,2760,2761],{"class":60}," id)\n",[39,2763,2765],{"class":41,"line":2764},39,[39,2766,501],{"emptyLinePlaceholder":500},[39,2768,2770,2772],{"class":41,"line":2769},40,[39,2771,1104],{"class":45},[39,2773,2774],{"class":60}," (task) {\n",[39,2776,2778,2781,2783,2785],{"class":41,"line":2777},41,[39,2779,2780],{"class":60},"    task.done ",[39,2782,138],{"class":45},[39,2784,289],{"class":45},[39,2786,2787],{"class":60},"task.done\n",[39,2789,2791],{"class":41,"line":2790},42,[39,2792,1131],{"class":60},[39,2794,2796],{"class":41,"line":2795},43,[39,2797,239],{"class":60},[39,2799,2801,2803,2805],{"class":41,"line":2800},44,[39,2802,179],{"class":60},[39,2804,476],{"class":131},[39,2806,169],{"class":60},[39,2808,2810],{"class":41,"line":2809},45,[39,2811,501],{"emptyLinePlaceholder":500},[39,2813,2815,2817,2819],{"class":41,"line":2814},46,[39,2816,128],{"class":60},[39,2818,541],{"class":131},[39,2820,169],{"class":60},[39,2822,2824,2826,2828,2831,2833,2836],{"class":41,"line":2823},47,[39,2825,549],{"class":60},[39,2827,1019],{"class":131},[39,2829,2830],{"class":56}," @submit.prevent",[39,2832,138],{"class":60},[39,2834,2835],{"class":70},"\"addTask\"",[39,2837,169],{"class":60},[39,2839,2841,2844,2846,2848,2850,2852,2854,2856],{"class":41,"line":2840},48,[39,2842,2843],{"class":60},"    \u003C",[39,2845,791],{"class":131},[39,2847,2218],{"class":56},[39,2849,138],{"class":60},[39,2851,560],{"class":70},[39,2853,2226],{"class":60},[39,2855,791],{"class":131},[39,2857,169],{"class":60},[39,2859,2861,2863,2865,2867,2869,2871,2874,2876,2878],{"class":41,"line":2860},49,[39,2862,2843],{"class":60},[39,2864,552],{"class":131},[39,2866,2239],{"class":56},[39,2868,138],{"class":60},[39,2870,560],{"class":70},[39,2872,2873],{"class":56}," v-model.trim",[39,2875,138],{"class":60},[39,2877,560],{"class":70},[39,2879,169],{"class":60},[39,2881,2883,2885,2887,2889,2891,2894,2896,2898,2900,2902,2904],{"class":41,"line":2882},50,[39,2884,2843],{"class":60},[39,2886,14],{"class":131},[39,2888,2040],{"class":56},[39,2890,138],{"class":60},[39,2892,2893],{"class":70},"\"titleError\"",[39,2895,2077],{"class":56},[39,2897,138],{"class":60},[39,2899,2082],{"class":70},[39,2901,2310],{"class":60},[39,2903,14],{"class":131},[39,2905,169],{"class":60},[39,2907,2909],{"class":41,"line":2908},51,[39,2910,501],{"emptyLinePlaceholder":500},[39,2912,2914,2916,2918,2920,2922,2925,2928,2930],{"class":41,"line":2913},52,[39,2915,2843],{"class":60},[39,2917,791],{"class":131},[39,2919,2218],{"class":56},[39,2921,138],{"class":60},[39,2923,2924],{"class":70},"\"priority\"",[39,2926,2927],{"class":60},">优先级\u003C\u002F",[39,2929,791],{"class":131},[39,2931,169],{"class":60},[39,2933,2935,2937,2939,2941,2943,2945,2947,2949,2951],{"class":41,"line":2934},53,[39,2936,2843],{"class":60},[39,2938,740],{"class":131},[39,2940,2239],{"class":56},[39,2942,138],{"class":60},[39,2944,2924],{"class":70},[39,2946,555],{"class":56},[39,2948,138],{"class":60},[39,2950,2924],{"class":70},[39,2952,169],{"class":60},[39,2954,2956,2959,2962,2965,2967,2970,2973,2975],{"class":41,"line":2955},54,[39,2957,2958],{"class":60},"      \u003C",[39,2960,2961],{"class":131},"option",[39,2963,2964],{"class":56}," value",[39,2966,138],{"class":60},[39,2968,2969],{"class":70},"\"low\"",[39,2971,2972],{"class":60},">低\u003C\u002F",[39,2974,2961],{"class":131},[39,2976,169],{"class":60},[39,2978,2980,2982,2984,2986,2988,2991,2994,2996],{"class":41,"line":2979},55,[39,2981,2958],{"class":60},[39,2983,2961],{"class":131},[39,2985,2964],{"class":56},[39,2987,138],{"class":60},[39,2989,2990],{"class":70},"\"normal\"",[39,2992,2993],{"class":60},">普通\u003C\u002F",[39,2995,2961],{"class":131},[39,2997,169],{"class":60},[39,2999,3001,3003,3005,3007,3009,3012,3015,3017],{"class":41,"line":3000},56,[39,3002,2958],{"class":60},[39,3004,2961],{"class":131},[39,3006,2964],{"class":56},[39,3008,138],{"class":60},[39,3010,3011],{"class":70},"\"high\"",[39,3013,3014],{"class":60},">高\u003C\u002F",[39,3016,2961],{"class":131},[39,3018,169],{"class":60},[39,3020,3022,3025,3027],{"class":41,"line":3021},57,[39,3023,3024],{"class":60},"    \u003C\u002F",[39,3026,740],{"class":131},[39,3028,169],{"class":60},[39,3030,3032],{"class":41,"line":3031},58,[39,3033,501],{"emptyLinePlaceholder":500},[39,3035,3037,3039,3041,3044,3046,3049,3052,3054],{"class":41,"line":3036},59,[39,3038,2843],{"class":60},[39,3040,1648],{"class":131},[39,3042,3043],{"class":56}," :disabled",[39,3045,138],{"class":60},[39,3047,3048],{"class":70},"\"!canSubmit\"",[39,3050,3051],{"class":60},">新增任务\u003C\u002F",[39,3053,1648],{"class":131},[39,3055,169],{"class":60},[39,3057,3059,3062,3064],{"class":41,"line":3058},60,[39,3060,3061],{"class":60},"  \u003C\u002F",[39,3063,1019],{"class":131},[39,3065,169],{"class":60},[39,3067,3069],{"class":41,"line":3068},61,[39,3070,501],{"emptyLinePlaceholder":500},[39,3072,3074,3076,3078,3081,3083,3086,3088,3090],{"class":41,"line":3073},62,[39,3075,549],{"class":60},[39,3077,1648],{"class":131},[39,3079,3080],{"class":56}," @click",[39,3082,138],{"class":60},[39,3084,3085],{"class":70},"\"filter = 'all'\"",[39,3087,1668],{"class":60},[39,3089,1648],{"class":131},[39,3091,169],{"class":60},[39,3093,3095,3097,3099,3101,3103,3106,3108,3110],{"class":41,"line":3094},63,[39,3096,549],{"class":60},[39,3098,1648],{"class":131},[39,3100,3080],{"class":56},[39,3102,138],{"class":60},[39,3104,3105],{"class":70},"\"filter = 'active'\"",[39,3107,1696],{"class":60},[39,3109,1648],{"class":131},[39,3111,169],{"class":60},[39,3113,3115,3117,3119,3121,3123,3126,3128,3130],{"class":41,"line":3114},64,[39,3116,549],{"class":60},[39,3118,1648],{"class":131},[39,3120,3080],{"class":56},[39,3122,138],{"class":60},[39,3124,3125],{"class":70},"\"filter = 'completed'\"",[39,3127,1724],{"class":60},[39,3129,1648],{"class":131},[39,3131,169],{"class":60},[39,3133,3135],{"class":41,"line":3134},65,[39,3136,501],{"emptyLinePlaceholder":500},[39,3138,3140,3142,3144,3146,3148,3151,3153,3155],{"class":41,"line":3139},66,[39,3141,549],{"class":60},[39,3143,14],{"class":131},[39,3145,2040],{"class":56},[39,3147,138],{"class":60},[39,3149,3150],{"class":70},"\"filteredTasks.length === 0\"",[39,3152,2117],{"class":60},[39,3154,14],{"class":131},[39,3156,169],{"class":60},[39,3158,3160],{"class":41,"line":3159},67,[39,3161,501],{"emptyLinePlaceholder":500},[39,3163,3165,3167,3169,3171],{"class":41,"line":3164},68,[39,3166,549],{"class":60},[39,3168,437],{"class":131},[39,3170,2130],{"class":56},[39,3172,169],{"class":60},[39,3174,3176,3178],{"class":41,"line":3175},69,[39,3177,2843],{"class":60},[39,3179,3180],{"class":131},"li\n",[39,3182,3184,3187,3189],{"class":41,"line":3183},70,[39,3185,3186],{"class":56},"      v-for",[39,3188,138],{"class":60},[39,3190,3191],{"class":70},"\"task in filteredTasks\"\n",[39,3193,3195,3198,3200],{"class":41,"line":3194},71,[39,3196,3197],{"class":56},"      :key",[39,3199,138],{"class":60},[39,3201,3202],{"class":70},"\"task.id\"\n",[39,3204,3206,3209,3211],{"class":41,"line":3205},72,[39,3207,3208],{"class":56},"      :class",[39,3210,138],{"class":60},[39,3212,3213],{"class":70},"\"{ done: task.done, urgent: task.priority === 'high' }\"\n",[39,3215,3217],{"class":41,"line":3216},73,[39,3218,3219],{"class":60},"    >\n",[39,3221,3223,3225,3227],{"class":41,"line":3222},74,[39,3224,2958],{"class":60},[39,3226,791],{"class":131},[39,3228,169],{"class":60},[39,3230,3232,3235,3237,3239,3241,3244,3247,3249,3252,3255,3257,3260],{"class":41,"line":3231},75,[39,3233,3234],{"class":60},"        \u003C",[39,3236,552],{"class":131},[39,3238,966],{"class":56},[39,3240,138],{"class":60},[39,3242,3243],{"class":70},"\"checkbox\"",[39,3245,3246],{"class":56}," :checked",[39,3248,138],{"class":60},[39,3250,3251],{"class":70},"\"task.done\"",[39,3253,3254],{"class":56}," @change",[39,3256,138],{"class":60},[39,3258,3259],{"class":70},"\"toggleTask(task.id)\"",[39,3261,169],{"class":60},[39,3263,3265],{"class":41,"line":3264},76,[39,3266,3267],{"class":60},"        {{ task.title }}\n",[39,3269,3271,3274,3276],{"class":41,"line":3270},77,[39,3272,3273],{"class":60},"      \u003C\u002F",[39,3275,791],{"class":131},[39,3277,169],{"class":60},[39,3279,3281,3283,3285],{"class":41,"line":3280},78,[39,3282,3024],{"class":60},[39,3284,132],{"class":131},[39,3286,169],{"class":60},[39,3288,3290,3292,3294],{"class":41,"line":3289},79,[39,3291,3061],{"class":60},[39,3293,437],{"class":131},[39,3295,169],{"class":60},[39,3297,3299,3301,3303],{"class":41,"line":3298},80,[39,3300,179],{"class":60},[39,3302,541],{"class":131},[39,3304,169],{"class":60},[21,3306,3307],{"id":3307},"本章练习",[3309,3310,3311,3314,3317,3320,3326,3329,3332,3338],"ol",{},[132,3312,3313],{},"写一个任务创建表单。",[132,3315,3316],{},"标题不能为空，不能超过 30 字。",[132,3318,3319],{},"增加优先级选择。",[132,3321,3322,3323,3325],{},"用 ",[36,3324,1076],{}," 渲染“全部 \u002F 未完成 \u002F 已完成”三种列表。",[132,3327,3328],{},"给已完成任务加删除线样式。",[132,3330,3331],{},"给高优先级任务加醒目边框。",[132,3333,3334,3335,3337],{},"给输入框补全 ",[36,3336,791],{}," 和错误提示。",[132,3339,3340],{},"回答：哪些状态应该留在当前组件内？为什么？",[1989,3342,3343],{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":34,"searchDepth":64,"depth":64,"links":3345},[3346,3347,3348,3350,3352,3353,3354,3355,3356,3357,3358,3359,3360,3361],{"id":23,"depth":64,"text":24},{"id":245,"depth":64,"text":246},{"id":454,"depth":64,"text":3349},"3. v-model 是什么",{"id":663,"depth":64,"text":3351},"4. 不同表单控件的 v-model",{"id":900,"depth":64,"text":901},{"id":1045,"depth":64,"text":1046},{"id":1375,"depth":64,"text":1376},{"id":1489,"depth":64,"text":1490},{"id":1772,"depth":64,"text":1773},{"id":1960,"depth":64,"text":1961},{"id":2022,"depth":64,"text":2023},{"id":2175,"depth":64,"text":2176},{"id":2323,"depth":64,"text":2324},{"id":3307,"depth":64,"text":3307},"md",{"order":236},"\u002Fsource\u002Fcode\u002Fvue\u002F05-forms-lists-styles",{"title":5,"description":16},"source\u002Fcode\u002Fvue\u002F05-forms-lists-styles","yPwjzmLkorpp8I12OtFtCz7t7uHCERHTPDWnrApPk58",1784032889391]