vue3新特性

新增功能

Fragment

不受根节点限制,渲染函数可以接收Array

Teleport

类似Portal,随用随取,e.g.弹窗

Suspense

嵌套的异步依赖,e.g.async setup()

带来的变化

  • 性能提升1.3x~2x
  • TS支持,新增:Fragment、Teleport、Suspense
  • 按需加载(配合Vite) & 组合式API

组合式API(composition)

https://v3.vuejs.org/api/composition-api.html#setup
https://v3.cn.vuejs.org/api/composition-api.html 

新建项目

vue create todo-list

eslint + prettier

https://www.cnblogs.com/jiaoshou/p/11271719.html

初始化

添加bootstrap样式

<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.3/css/bootstrap.min.css" rel="stylesheet">

挂载到public/index.html

引入reactive创建响应式对象

const state = reactive({
  valueAdd: "", // 添加事项
  valueEdit: "", // 编辑事项
});
return toRefs(state);

具体实现

渲染item

<div class="form-group form-check mb-0">
  <input
         type="checkbox"
         class="form-check-input"
         :id="'item-' + index"
         v-model="item.checked"
         @click="() => (item.checked = !item.checked)"
         />
  <label
         class="form-check-label"
         v-if="!item.isEdit"
         @dblclick="showEdit(item, index)"
         >{{ item.name }}</label
    >
  <label class="form-check-label" :for="'item-' + index" v-else>
    <input type="text" v-model="valueEdit" @blur="inputBlur" />
  </label>
</div>
<button
        type="button"
        class="close"
        aria-label="Close"
        @click="remove(index)"
        >
  <span aria-hidden="true">&times;</span>
</button>

点击checkbox完成任务

@click="() => (item.checked = !item.checked)"
	<ul class="list-group">
      <li
        class="list-group-item"
        v-for="(item, index) of finished"
        :key="'finished-' + index"
      >
        <div class="form-group form-check">
          <input
            type="checkbox"
            class="form-check-input"
            :id="'finished-' + index"
            v-model="item.checked"
            disabled
          />
          <label class="form-check-label" :for="'finished-' + index">{{
            item.name
          }}</label>
        </div>
      </li>
    </ul>
      // 已结束事项
      finished: computed(() =>
        state.lists.filter((item) => item.checked == true)
      ),

点击按钮添加新的任务

// 添加任务
const add = () => {
  state.lists.push({
    name: state.valueAdd,
    checked: false,
    isEdit: false,
  });
  state.valueAdd = "";
};

双击文字编辑任务

<label
       class="form-check-label"
       v-if="!item.isEdit"
       @dblclick="showEdit(item, index)"
       >{{ item.name }}</label
  >
<label class="form-check-label" :for="'item-' + index" v-else>
  <input type="text" v-model="valueEdit" @blur="inputBlur" />
</label>

双击切换至编辑模式

const showEdit = (item, index) => {
  editIndex = index;
  item.isEdit = true;
  state.valueEdit = item.name;
};

单击关闭编辑模式

const inputBlur = () => {
  state.lists[editIndex] = {
    name: state.valueEdit,
    checked: false,
    isEdit: false,
  };
};

点击按钮删除任务

const remove = (index) => {
  state.lists.splice(index, 1);
};

多页面数据存储

store/index.js下

export default createStore({
  state: {
    list : []// 数据
  },
  mutations: {},
  actions: {},
  modules: {},
});

使用时,在reactive中通过computed来时时更新list

list: computed(() => store.state.list)