显示todo列表

2019-01-0710812 阅读5 评论

在我们的当前模板中,todo 列表的值都是我们直接写在 HTML 文档里的。合理的情况应该是根据用户添加和删除 todo 时动态地显示全部内容,这就要交给 Vue 了。当然,第一步是要先构建 Vue 的实例,注意这个实例目前是没有绑定任何数据的,其 data 是一个空函数,不返回任何有用的数据:

<body>
<div id="todo-app">
    ...
</div>
<script src="https://cdn.bootcss.com/vue/2.5.16/vue.js"></script>
<script>
    var app = new Vue({
        el: '#todo-app',
        data: function () {
        },
    })
</script>
</body>

我们现在还没有实现用户添加 todo 的功能,我们先做个弊,假设用户已经输入了一些 todo,存在一个 todos 列表里,现在需要将 Vue 实例和这个 todos 绑定:

var app = new Vue({
    el: '#todo-app',
    data: function () {
        return {
            todos: [
                {id: 0, title: '学习 Vue'},
                {id: 1, title: '整个牛项目'},
                {id: 2, title: '迎娶白富美走上人生巅峰'},
            ]
        }
    },
})

现在每一个 todo 都是一个对象,它有 id 和 title 两个属性,id 用来唯一标识这个 todo。然后我们就在模板中循环显示这个 todos 列表,Vue 中循环指令用 v-for:

<div id="todo-app">
  ...
  <!--todo list-->
  <ul>
    <li v-for='todo in todos' :key='todo.id'>
      <span>{{ todo.title }}</span>
      <input type="button" value="标为完成">
      <input type="button" value="删除">
      <input type="text" value="编辑 todo..."/>
    </li>
  </ul>
  <!-- end todo list -->
  ...
</div>

注意到 v-for='todo in todos' 这种写法,其含义就是循环 todos 列表,将列表的每一项保存到 todo 变量,循环渲染 li 元素的内容。特别注意我们还给 li 元素绑定了一个 key 属性,这将告诉 Vue 每个渲染的 li 元素都是不同的,因为 id 不同。

你可以删除或者添加 todos 列表中的元素,然后刷新浏览器,可以看到页面渲染的内容会跟着变化。你也可以在按 F12 进入浏览器的调试窗口,在命令行(console)输入命令:

app.todos = [
                {id: 1, title: '整个牛项目'},
                {id: 2, title: '迎娶白富美(或走上人生巅峰)'},
            ]

这个 app 是我们创建的 Vue 实例的名字,然后引用它绑定的数据 todos,我们给它赋了一个新的值,然后你会实时地看到浏览器渲染的结果变化了。Vue 就是这么神奇!

显然,人工为 todos 列表添加数据是一点也不好玩的,我们希望在上方的输入框输入想要添加的 todo,然后按回车就自动给我们添加 todo,接下来我们就来实现它。

-- EOF --

5 评论
登录后回复
Qin Yuan
2020-07-12 09:42:39

想请教楼主或者是其他各位达人一个问题,困扰了我很久很久.
我试图架构一个django+vue的东西.从后台返回数据,用vue来做渲染.目前已经能启动,http://localhost:8000/index.html 到我指定的index文件
然后我把楼主的这个todo内容拷进去.诡异的是好像所有的vue的变量经过了server那边过来都不起作用了,但是如果我是在local直接打开这个文件是起作用的.
简单一点说这样:

然后在上面把v-for什么的都删掉,就写死一个

  • {{ testID }}
  • 然后如果我在本地直接打开这个index.html 这个"1"是渲染成功的.但是如果我用http://localhost:8000/index.html 这个"1"就不见了.
    我的理解是django应该直接把我的静态文件给返回了,然后这个再在本地给render,怎么会变成变量不起作用了呢
    我django那边是这样返回的

    urlpatterns = [
    #re_path('^\(', views.index), re_path('^\)', TemplateView.as_view(template_name='index.html')),
    ]

    感谢楼主和各位达人.提问如果信息不全说得不清楚请告知我尽力改进.

    回复
    Qin Yuan Qin Yuan
    2020-07-12 10:15:43

    我已经...自己找到错误了.果然把问题讲述出来就是一个查错的过程.
    问题在于,django也试图去渲染那个{{testID}}返回给browser的时候就已经把它给替换成空的了
    我有个笨的解决方法就是在django那边按照raw的方式返回:
    result = finders.find('index.html')
    with open(result, encoding='utf-8') as f:
    return HttpResponse(f.read())

    但是这样,index.html里面定义的{% load static %} 这些又不能用了
    真是头大...

    回复
    追梦人物 Qin Yuan
    2020-07-19 20:30:10

    django 的模板语法和 vue 的冲突,一般我们不这样使用。推荐的做法是为 todo 开发 api(参考最新在更新的 drf 教程),vue 通过调用接口拿数据。

    回复
    搁浅亚细亚
    2019-02-19 09:45:50

    app.todos = todos: [ {id: 1, title: '整个牛项目'}, {id: 2, title: '迎娶白富美(或走上人生巅峰)'}, ] 这句在console中报错“Uncaught SyntaxError: Unexpected token :”

    回复
    追梦人物 搁浅亚细亚
    2019-02-27 18:49:28

    感谢,已经修复,改为:

    app.todos = [ {id: 1, title: '整个牛项目'}, {id: 2, title: '迎娶白富美(或走上人生巅峰)'}, ]
    回复