Vue 2.0 入门系列(12) 用面向对象的概念去实现任务列表 (1)

<p><code></p> <h1 id="articleHeader0">12. 面向对象的任务列表实现 (1)</h1> <h2 id="articleHeader1">后台</h2> <h3 id="articleHeader2">初始化</h3> <p>创建一个新应用:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="$ laravel new vue-to-do $ cd vue-to-do" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs ruby"><code class="sh">$ laravel new vue-to-<span class="hljs-keyword">do</span> $ cd vue-to-<span class="hljs-keyword">do</span></code></pre> <p>创建 Task 相关:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="$ php artisan make:model Task -mc Model created successfully. Created Migration: 2017_05_01_050911_create_tasks_table Controller created successfully." title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs properties"><code class="sh"><span class="hljs-meta">$</span> <span class="hljs-string">php artisan make:model Task -mc</span> <span class="hljs-attr">Model</span> <span class="hljs-string">created successfully.</span> <span class="hljs-attr">Created</span> <span class="hljs-string">Migration: 2017_05_01_050911_create_tasks_table</span> <span class="hljs-attr">Controller</span> <span class="hljs-string">created successfully.</span></code></pre> <p>配置数据库:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="// /.env DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=vue_todo DB_USERNAME=root DB_PASSWORD=" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs makefile"><code class="sh">// /.env DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=vue_todo DB_USERNAME=root DB_PASSWORD=</code></pre> <p>编辑迁移文件:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="/database/migrations/2017_05_01_050911_create_tasks_table.php Schema::create('tasks', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->text('description'); $table->timestamps(); });" title="" data-original-title="复制"></span> </div> </p></div> <pre class="php hljs"><code class="php">/database/migrations/<span class="hljs-number">2017</span>_05_01_050911_create_tasks_table.php Schema::create(<span class="hljs-string">'tasks'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">(Blueprint $table)</span> </span>{ $table-&gt;increments(<span class="hljs-string">'id'</span>); $table-&gt;string(<span class="hljs-string">'name'</span>); $table-&gt;text(<span class="hljs-string">'description'</span>); $table-&gt;timestamps(); });</code></pre> <p>执行迁移:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="$ php artisan migrate" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs shell"><code class="sh" style="word-break: break-word; white-space: initial;"><span class="hljs-meta">$</span><span class="bash"> php artisan migrate</span></code></pre> <h3 id="articleHeader3">业务逻辑</h3> <p>路由:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="/routes/web.php Route::get('/tasks','TaskController@index'); Route::post('/tasks','TaskController@store');" title="" data-original-title="复制"></span> </div> </p></div> <pre class="php hljs"><code class="php">/routes/web.php Route::get(<span class="hljs-string">'/tasks'</span>,<span class="hljs-string">'TaskController@index'</span>); Route::post(<span class="hljs-string">'/tasks'</span>,<span class="hljs-string">'TaskController@store'</span>);</code></pre> <p>控制器:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="/app/Http/Controllers/TaskController.php <?php namespace AppHttpControllers; use AppTask; use IlluminateHttpRequest; class TaskController extends Controller { /** * 显示与创建任务列表 * @return [Response] [view] */ public function index() { $tasks = Task::all(); return view('tasks.index', compact('tasks')); } /** * 保存任务列表 * @return [Response] [message] */ public function store() { $this->validate(request(), [ 'name' => 'required', 'description' => 'required' ]); Task::forceCreate(request('name', 'description')); return ['message' => '任务创建成功']; } }" title="" data-original-title="复制"></span> </div> </p></div> <pre class="php hljs"><code class="php">/app/Http/Controllers/TaskController.php <span class="hljs-meta">&lt;?php</span> <span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span><span class="hljs-title">Http</span><span class="hljs-title">Controllers</span>; <span class="hljs-keyword">use</span> <span class="hljs-title">App</span><span class="hljs-title">Task</span>; <span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span><span class="hljs-title">Http</span><span class="hljs-title">Request</span>; <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TaskController</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Controller</span> </span>{ <span class="hljs-comment">/** * 显示与创建任务列表 * <span class="hljs-doctag">@return</span> [Response] [view] */</span> <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">index</span><span class="hljs-params">()</span> </span>{ $tasks = Task::all(); <span class="hljs-keyword">return</span> view(<span class="hljs-string">'tasks.index'</span>, compact(<span class="hljs-string">'tasks'</span>)); } <span class="hljs-comment">/** * 保存任务列表 * <span class="hljs-doctag">@return</span> [Response] [message] */</span> <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">store</span><span class="hljs-params">()</span> </span>{ <span class="hljs-keyword">$this</span>-&gt;validate(request(), [ <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'required'</span>, <span class="hljs-string">'description'</span> =&gt; <span class="hljs-string">'required'</span> ]); Task::forceCreate(request(<span class="hljs-string">'name'</span>, <span class="hljs-string">'description'</span>)); <span class="hljs-keyword">return</span> [<span class="hljs-string">'message'</span> =&gt; <span class="hljs-string">'任务创建成功'</span>]; } }</code></pre> <h2 id="articleHeader4">前端</h2> <h3 id="articleHeader5">基本功能实现</h3> <p>首先定义视图:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="/resources/views/tasks/index.blade.php <!DOCTYPE html> <html lang=&quot;en&quot;> <head> <meta charset=&quot;UTF-8&quot;> <title>Vue-To-Do-List</title> </head> <body> </p> <div id=&quot;app&quot; class=&quot;container&quot;> @if (count($tasks)) </p> <table class=&quot;table&quot;> <thead> <tr> <th>#</th> <th>任务名</th> <th>描述</th> </tr> </thead> <tbody> @foreach ($tasks as $task) </p> <tr> <th>{{ $task['id']}}</th> <td>{{ $task['name'] }}</td> <td>{{ $task['description'] }}</td> </tr> <p> @endforeach </tbody> </table> <p> @endif </p> <form method=&quot;POST&quot; action=&quot;/tasks&quot; @submit.prevent=&quot;onSubmit&quot;> <fieldset class=&quot;form-group&quot;> <label for=&quot;name&quot;>任务名</label> <input type=&quot;text&quot; class=&quot;form-control&quot; id=&quot;name&quot; name=&quot;name&quot; v-model=&quot;name&quot;> </fieldset> <fieldset class=&quot;form-group&quot;> <label for=&quot;description&quot;>任务描述</label> <input type=&quot;text&quot; class=&quot;form-control&quot; id=&quot;description&quot; name=&quot;description&quot; v-model=&quot;description&quot;> </fieldset> <p> <button type=&quot;submit&quot; class=&quot;btn btn-primary&quot;>创建</button> </form> </p></div> <link href=&quot;https://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css&quot; rel=&quot;stylesheet&quot;> <script src=&quot;https://cdn.bootcss.com/vue/2.2.6/vue.js&quot;></script> <script src=&quot;https://cdn.bootcss.com/axios/0.16.1/axios.js&quot;></script> <script type=&quot;text/javascript&quot; src=&quot;/js/app.js&quot;></script> </body> </html>" title="" data-original-title="复制"></span> </div> </p></div> <pre class="xml hljs"><code class="html">/resources/views/tasks/index.blade.php <span class="hljs-meta">&lt;!DOCTYPE html&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Vue-To-Do-List<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"app"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span> @if (count($tasks)) <span class="hljs-tag">&lt;<span class="hljs-name">table</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"table"</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">thead</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>#<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>任务名<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>描述<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">thead</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">tbody</span>&gt;</span> @foreach ($tasks as $task) <span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>{{ $task['id']}}<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{ $task['name'] }}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{ $task['description'] }}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span> @endforeach <span class="hljs-tag">&lt;/<span class="hljs-name">tbody</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">table</span>&gt;</span> @endif <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">method</span>=<span class="hljs-string">"POST"</span> <span class="hljs-attr">action</span>=<span class="hljs-string">"/tasks"</span> @<span class="hljs-attr">submit.prevent</span>=<span class="hljs-string">"onSubmit"</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">fieldset</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-group"</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"name"</span>&gt;</span>任务名<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"name"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"name"</span> <span class="hljs-attr">v-model</span>=<span class="hljs-string">"name"</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">fieldset</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">fieldset</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-group"</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"description"</span>&gt;</span>任务描述<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"description"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"description"</span> <span class="hljs-attr">v-model</span>=<span class="hljs-string">"description"</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">fieldset</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-primary"</span>&gt;</span>创建<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css"</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.bootcss.com/vue/2.2.6/vue.js"</span>&gt;</span><span class="undefined"></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.bootcss.com/axios/0.16.1/axios.js"</span>&gt;</span><span class="undefined"></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/javascript"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"/js/app.js"</span>&gt;</span><span class="undefined"></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></code></pre> <p>为了阻止表单的提交,可以使用 <code>prevent</code> 修饰符,相当于调用 <code>Event.preventDefault() </code> 方法。</p> <p>前端业务逻辑:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="/public/js/app.js Vue.prototype.$http = axios; var vm = new Vue({ el: '#app', data: { name:'', description:'' }, methods: { onSubmit(){ this.$http.post('/tasks',this.$data) } } })" title="" data-original-title="复制"></span> </div> </p></div> <pre class="javascript hljs"><code class="js">/public/js/app.js Vue.prototype.$http = axios; <span class="hljs-keyword">var</span> vm = <span class="hljs-keyword">new</span> Vue({ <span class="hljs-attr">el</span>: <span class="hljs-string">'#app'</span>, <span class="hljs-attr">data</span>: { <span class="hljs-attr">name</span>:<span class="hljs-string">''</span>, <span class="hljs-attr">description</span>:<span class="hljs-string">''</span> }, <span class="hljs-attr">methods</span>: { onSubmit(){ <span class="hljs-keyword">this</span>.$http.post(<span class="hljs-string">'/tasks'</span>,<span class="hljs-keyword">this</span>.$data) } } })</code></pre> <p>这里使用了之前介绍的 <code>axios</code> 包,其中,<code>$data</code> 为实例的 data 对象。在这里相当于:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="this.$http.post('/tasks',{ name: this.name, description: this.description })" title="" data-original-title="复制"></span> </div> </p></div> <pre class="javascript hljs"><code class="js"><span class="hljs-keyword">this</span>.$http.post(<span class="hljs-string">'/tasks'</span>,{ <span class="hljs-attr">name</span>: <span class="hljs-keyword">this</span>.name, <span class="hljs-attr">description</span>: <span class="hljs-keyword">this</span>.description })</code></pre> <p>基本的效果如下:</p> <p><span class="img-wrap"><img data-src="/img/bVMZrR?w=600&amp;h=400" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="clipboard.png" title="clipboard.png" style="cursor: pointer;"></span></p> <h3 id="articleHeader6">Errors 类</h3> <p>之前只实现了正确提交的功能。接下来实现错误提交的情况。</p> <p><code>axios</code> 的 <code>post</code> 请求的基本方法如下:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="axios.post('/user', { firstName: 'Fred', lastName: 'Flintstone' }) // 成功 .then(function (response) { console.log(response); }) // 失败 .catch(function (error) { console.log(error); });" title="" data-original-title="复制"></span> </div> </p></div> <pre class="javascript hljs"><code class="js">axios.post(<span class="hljs-string">'/user'</span>, { <span class="hljs-attr">firstName</span>: <span class="hljs-string">'Fred'</span>, <span class="hljs-attr">lastName</span>: <span class="hljs-string">'Flintstone'</span> }) <span class="hljs-comment">// 成功</span> .then(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">response</span>) </span>{ <span class="hljs-built_in">console</span>.log(response); }) <span class="hljs-comment">// 失败</span> .catch(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">error</span>) </span>{ <span class="hljs-built_in">console</span>.log(error); });</code></pre> <p>假如提交了一个空的表单,后台会返回错误消息,我们可以通过 <code>error.response.data</code> 来访问。比如</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="data: { name:'', description:'', errors:{} }, methods: { onSubmit(){ this.$http.post('/tasks',this.$data) .catch(error => this.errors = error.response.data); } }" title="" data-original-title="复制"></span> </div> </p></div> <pre class="javascript hljs"><code class="js">data: { <span class="hljs-attr">name</span>:<span class="hljs-string">''</span>, <span class="hljs-attr">description</span>:<span class="hljs-string">''</span>, <span class="hljs-attr">errors</span>:{} }, <span class="hljs-attr">methods</span>: { onSubmit(){ <span class="hljs-keyword">this</span>.$http.post(<span class="hljs-string">'/tasks'</span>,<span class="hljs-keyword">this</span>.$data) .catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> <span class="hljs-keyword">this</span>.errors = error.response.data); } }</code></pre> <p>为了方便操作,可以将其封装成类:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="Vue.prototype.$http = axios; class Errors { /** * 初始化 */ constructor(){ this.errors = {} } /** * 保存错误信息 */ record(errors){ this.errors = errors; } } var vm = new Vue({ el: '#app', data: { name:'', description:'', errors:new Errors() }, methods: { onSubmit(){ this.$http.post('/tasks',this.$data) .catch(error => this.errors.record = error.response.data); } } })" title="" data-original-title="复制"></span> </div> </p></div> <pre class="javascript hljs"><code class="js">Vue.prototype.$http = axios; <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Errors</span> </span>{ <span class="hljs-comment">/** * 初始化 */</span> <span class="hljs-keyword">constructor</span>(){ <span class="hljs-keyword">this</span>.errors = {} } <span class="hljs-comment">/** * 保存错误信息 */</span> record(errors){ <span class="hljs-keyword">this</span>.errors = errors; } } <span class="hljs-keyword">var</span> vm = <span class="hljs-keyword">new</span> Vue({ <span class="hljs-attr">el</span>: <span class="hljs-string">'#app'</span>, <span class="hljs-attr">data</span>: { <span class="hljs-attr">name</span>:<span class="hljs-string">''</span>, <span class="hljs-attr">description</span>:<span class="hljs-string">''</span>, <span class="hljs-attr">errors</span>:<span class="hljs-keyword">new</span> Errors() }, <span class="hljs-attr">methods</span>: { onSubmit(){ <span class="hljs-keyword">this</span>.$http.post(<span class="hljs-string">'/tasks'</span>,<span class="hljs-keyword">this</span>.$data) .catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> <span class="hljs-keyword">this</span>.errors.record = error.response.data); } } })</code></pre> <p>在控制台中查看对应的 <code>errors</code> 实例:</p> <p><span class="img-wrap"><img data-src="/img/bVMZrS?w=722&amp;h=520" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="clipboard.png" title="clipboard.png" style="cursor: pointer;"></span></p> <p>也就是说,可以通过 <code>errors[name][0]</code> 的方式来访问错误信息,将其写成方法:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="get(field) { if (this.errors[field]) { return this.errors[field][0]; } }" title="" data-original-title="复制"></span> </div> </p></div> <pre class="javascript hljs"><code class="js">get(field) { <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.errors[field]) { <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.errors[field][<span class="hljs-number">0</span>]; } }</code></pre> <p>页面中就可以显示错误消息了:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text=" <fieldset class=&quot;form-group&quot;> <label for=&quot;name&quot;>任务名</label> <input type=&quot;text&quot; class=&quot;form-control&quot; id=&quot;name&quot; v-model=&quot;name&quot;> <small class=&quot;text-danger&quot; v-text=&quot;errors.get('name')&quot;></small> </fieldset> <fieldset class=&quot;form-group&quot;> <label for=&quot;description&quot;>任务描述</label> <input type=&quot;text&quot; class=&quot;form-control&quot; id=&quot;description&quot; v-model=&quot;description&quot;> <small class=&quot;text-danger &quot; v-text=&quot;errors.get('description')&quot;></small> </fieldset> <p>" title="" data-original-title="复制"></span> </div> </p></div> <pre class="xml hljs"><code class="html"><span class="hljs-tag">&lt;<span class="hljs-name">fieldset</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-group"</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"name"</span>&gt;</span>任务名<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"name"</span> <span class="hljs-attr">v-model</span>=<span class="hljs-string">"name"</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">small</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-danger"</span> <span class="hljs-attr">v-text</span>=<span class="hljs-string">"errors.get('name')"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">small</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">fieldset</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">fieldset</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-group"</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"description"</span>&gt;</span>任务描述<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"description"</span> <span class="hljs-attr">v-model</span>=<span class="hljs-string">"description"</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">small</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-danger "</span> <span class="hljs-attr">v-text</span>=<span class="hljs-string">"errors.get('description')"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">small</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">fieldset</span>&gt;</span></code></pre> <p>效果如下:</p> <p><span class="img-wrap"><img data-src="/img/bVMZrU?w=419&amp;h=166" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="clipboard.png" title="clipboard.png" style="cursor: pointer;"></span></p> <p>接着,增加条件判断,以决定是否显示错误信息的页面:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="<small class=&quot;text-danger&quot; v-if=&quot;errors.has('name')&quot; v-text=&quot;errors.get('name')&quot;></small> <small class=&quot;text-danger&quot; v-if=&quot;errors.has('description')&quot; v-text=&quot;errors.get('description')&quot;></small>" title="" data-original-title="复制"></span> </div> </p></div> <pre class="xml hljs"><code class="html"><span class="hljs-tag">&lt;<span class="hljs-name">small</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-danger"</span> <span class="hljs-attr">v-if</span>=<span class="hljs-string">"errors.has('name')"</span> <span class="hljs-attr">v-text</span>=<span class="hljs-string">"errors.get('name')"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">small</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">small</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-danger"</span> <span class="hljs-attr">v-if</span>=<span class="hljs-string">"errors.has('description')"</span> <span class="hljs-attr">v-text</span>=<span class="hljs-string">"errors.get('description')"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">small</span>&gt;</span></code></pre> <p>对应的方法:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="/** * 判断属性是否存在 * @param {string} field */ has(field){ return this.errors.hasOwnProperty(field); }" title="" data-original-title="复制"></span> </div> </p></div> <pre class="javascript hljs"><code class="js"><span class="hljs-comment">/** * 判断属性是否存在 * @param {string} field */</span> has(field){ <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.errors.hasOwnProperty(field); }</code></pre> <p>当存在错误消息的时候,不允许用户再次提交:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="<button type=&quot;submit&quot; class=&quot;btn btn-primary&quot; :disabled=&quot;errors.any()&quot;>创建</button>" title="" data-original-title="复制"></span> </div> </p></div> <pre class="xml hljs"><code class="html" style="word-break: break-word; white-space: initial;"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-primary"</span> <span class="hljs-attr">:disabled</span>=<span class="hljs-string">"errors.any()"</span>&gt;</span>创建<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></code></pre> <p>对应的方法:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="any(){ return Object.keys(this.errors).length > 0; }" title="" data-original-title="复制"></span> </div> </p></div> <pre class="javascript hljs"><code class="js">any(){ <span class="hljs-keyword">return</span> <span class="hljs-built_in">Object</span>.keys(<span class="hljs-keyword">this</span>.errors).length &gt; <span class="hljs-number">0</span>; }</code></pre> <p>最后,用户重新输入时,应当清空错误消息:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text=" <form method=&quot;POST&quot; action=&quot;/tasks&quot; @submit.prevent=&quot;onSubmit&quot; @keydown=&quot;errors.clear($event.target.name)&quot;>" title="" data-original-title="复制"></span> </div> </p></div> <pre class="xml hljs"><code class="html" style="word-break: break-word; white-space: initial;"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">method</span>=<span class="hljs-string">"POST"</span> <span class="hljs-attr">action</span>=<span class="hljs-string">"/tasks"</span> @<span class="hljs-attr">submit.prevent</span>=<span class="hljs-string">"onSubmit"</span> @<span class="hljs-attr">keydown</span>=<span class="hljs-string">"errors.clear($event.target.name)"</span>&gt;</span></code></pre> <p>对应方法:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="clear(field){ if (field) { delete this.errors[field]; return; } this.errors = {}; }" title="" data-original-title="复制"></span> </div> </p></div> <pre class="javascript hljs"><code class="js">clear(field){ <span class="hljs-keyword">if</span> (field) { <span class="hljs-keyword">delete</span> <span class="hljs-keyword">this</span>.errors[field]; <span class="hljs-keyword">return</span>; } <span class="hljs-keyword">this</span>.errors = {}; }</code></pre> <hr> <p>附录:</p> <ul> <li> <p><a href="https://cn.vuejs.org/v2/api/#v-on" rel="nofollow noreferrer" target="_blank">v-on 修饰符</a></p> </li> <li> <p><a href="https://cn.vuejs.org/v2/api/#vm-data" rel="nofollow noreferrer" target="_blank">data</a></p> </li> </ul> <p></code></p>
脚本宝典为你提供优质服务
脚本宝典 » Vue 2.0 入门系列(12) 用面向对象的概念去实现任务列表 (1)

发表评论

提供最优质的资源集合

立即查看 了解详情