尚硅谷Vue入门视频 笔记

尚硅谷视频:https://www.bilibili.com/video/BV1Zy4y1K7SH/?spm_id_from=333.999.0.0&vd_source=cec13bbe100bddfff8baf29d18ed8994

模板语法

  • 插值语法
<h1>
    {{name}}
</h1>
  • 指令语法
单向数据绑定
<h1 v-bind:href = "js表达式"></h1>
<h1 :href = "js表达式"></h1>
双向数据绑定 一般用在表单类元素上 默认收集value值
<input  type = "text" v-model:value="name"/>
<input  type = "text" v-model="name"/>

data与el的2种写法

  • el有2种写法

    • (1).new Vue时候配置el属性。
    • (2).先创建Vue实例,随后再通过vm.$mount(‘#root’)指定el的值。
  • data有2种写法

    • (1).对象式

      data: {
      	name: 'shanghai'
      }
      
    • (2).函数式

      data (){
          console.log('@@@', this); //此时this是Vue
          return {
          	name: 'shanghai'
          }
      }
      

如何选择:目前哪种写法都可以,以后学习到组件时,data必须使用函数式,否则会报错。

  • 一个重要的原则:
    由Vue管理的函数(例如data),一定不要写箭头函数,一旦写了箭头函数,this就不再是Vue实例了。

MVVM模型

  • MVVM模型

    • M:模型(Model) :data中的数据
    • V:视图(View) :模板代码
    • VM:视图模型(ViewModel):Vue实例
  • 观察发现:

    • data中所有的属性,最后都出现在了vm身上。
    • vm身上所有的属性 及 Vue原型上所有属性,在Vue模板中都可以直接使用。

事件

<h1 @click="showInfo" >点我提示信息</h1>


事件修饰符

1.prevent:阻止默认事件(常用);
<a href="https://www.baidu.com" @click.prevent="showInfo" >点我提示信息</a>

2.stop:阻止事件冒泡(常用);
修饰符也可以连用,例如下面事例是即阻止冒泡同时也阻止默认行为
<div class="demo1" @click="showMsg(1)">
<button @click.stop="showMsg(2)">点我提示信息</button>
<!--修饰符也可以连用,例如下面事例是即阻止冒泡同时也阻止默认行为-->
<!--<a href="https://www.google.com.tw" @click.prevent.stop="showInfo">谷歌台湾</a>-->
</div>

3.once:事件只触发一次(常用);

4.capture:使用事件的捕获模式;
<!-- capture事件的捕获模式 让事件以捕获的方式来处理(先捕获再冒泡)-->
<div class="box1" @click.capture="showMsg(1)">
div1
<div class="box2" @click="showMsg(2)">div2</div>
</div>
       
5.self:只有event.target是当前操作的元素时才触发事件;
<!-- self 只有event.target是当前操作的元素时才触发事件(变相阻止冒泡)-->
<div class="demo1" @click.self="showInfo">
<button @click="showInfo">点我提示信息</button>
</div>

6.passive:事件的默认行为立即执行,无需等待事件回调执行完毕;
<!--passive:事件的默认行为立即执行,无需等待事件回调执行完毕;-->
<!--scroll滚动条一滚动就会触发的事件 wheel鼠标滚轮事件-->
<ul class="list" @scroll.passive="demo">
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
</ul>

正常输出2、1,@click.stop输出2, @click.capture输出1,2(先捕获再冒泡

请添加图片描述

事件的基本使用

  1. 使用v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名
  2. 事件的回调需要配置在methods对象中,最终会在vm上
  3. methods中配置的函数,不要用箭头函数!否则this就不是vm了
  4. methods中配置的函数,都是被Vue所管理的函数,this的指向是vm 或 组件实例对象
  5. @click=“demo” 和 @click=“demo($event)” 效果一致,但后者可以传参
<button v-on:click="showInfo1">点我提示信息1</button>
<!--简写形式 @click-->
<button @click="showInfo2($event,66)">点我提示信息2</button>

showInfo2(e,num){
    console.log(e.target);//
    console.log(`接收参数:${num}`);
}

计算属性

  1. 定义:要用的属性不存在,要通过已有属性计算得来。
  2. 原理:底层借助了Objcet.defineproperty方法提供的getter和setter。
  3. get函数什么时候执行?
    • 初次读取时会执行一次。
    • 当依赖的数据发生改变时会被再次调用。
  4. set函数什么时候执行?
    • 修改计算属性所依赖的普通属性(放在data里面的)
  5. 优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便。
  6. 备注:
    1. 计算属性最终会出现在vm上,直接读取使用即可。
    2. 如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变。
<div>
姓:<input type="text" v-model="firstName"/>
    <br/><br/>
    名:<input type="text" v-model="lastName"/>
    <br/><br/>
    测试:<input type="text" v-model="test"/>
    <br/><br/>
    全名: <input type="text" v-model="fullName"/>
    <br/><br/>
    全名: <span>{{ fullName }}</span>
</div>
<script type="text/javascript">
    const vm = new Vue({
        el: '#root',
        data: {
            //data里的都是属性
            firstName: '张',
            lastName: '三',
            test:'test'
        },
        //计算属性--> 旧属性加工
        computed: {
            fullName: {
                //get的作用,当读取fullName时get就会被调用,且返回值就做为fullName的值
                //defineProperty
                //注意vm._data是不存在计算属性的
                //计算属性算完之后直接丢到了viewModel实例对象身上
                /**
                 * get的调用时机
                 * 1.初次读取计算属性时
                 * 2.所依赖的数据(data中的属性)发生变化时,不改变的话直接读缓存
                 * 3.methods没有缓存,读几次就调用几次无论要用的数据是否发生变化
                 *  @returns {string}
                 */
                get(){
                    //此时get函数中的this指向是vm
                    console.log('get调用了', this);
                    return this.firstName + '-' + this.lastName
                },
                /**
                 * set什么时候调用
                 *   1.当fullName被修改时
                 * @param value
                 */
                set(value){
                    console.log('set调用了', value);
                    //修改计算属性所依赖的普通属性(放在data里面的)
                    //this === vm
                    const [ firstName, lastName ] = value.split('-');
                    console.log('firstName', firstName);
                    console.log('lastName', lastName);
                    this.firstName = firstName;
                    this.lastName = lastName; //依赖属性发生改变之后,计算属性自动改变
                }
            }
        }
    });
 </script>

简写形式

computed: {
    //简写形式
    //前提:计算属性只考虑读取不考虑修改 set丢了
    //简写计算书写为一个函数(这个函数当成getter使用), 注意不要写箭头函数
    //执行完getter之后,vm直接保存返回的数据为fullName属性的属性值,此时vm.fullName不是函数而是一个确切的计算值
    fullName: function (){
    	return this.firstName + '--' + this.lastName;
    }
}

监视属性

  1. 当被监视的属性变化时, 回调函数自动调用, 进行相关操作

  2. 监视的属性必须存在,才能进行监视

  3. 监视的两种写法:

    1. new Vue时传入watch配置
    2. 通过vm.$watch监视
  4. handler函数

    1. 当被监视属性发生改变就会调用该函数
    2. 接收两个参数,一个是这个状态参数改变前的值,另一个是改变后的旧值
  5. 深度监视:

    1. Vue中的watch默认不监测对象内部值的改变(一层)
    2. 配置deep:true可以监测对象内部值改变(多层)
  6. 简写形式,不需要immediate、deep属性

    watch:{
        isHot(newValue, preValue){
            console.log(newValue,preValue);
        }
    }
    

案例:

<div id="root">

    <h1>今天天气很 {{ info }}</h1>
    <button @click="changeWeather">
        切换
    </button>
    <h3>b的值是:{{ numbers.b }}</h3>
    <button @click="numbers.b++">
        点我让b加一
    </button>
</div>
<script type="text/javascript">
    Vue.config.productionTip = false;
    const vm = new Vue({
        el:'#root',
        data:{
            isHot: true,
            numbers:{
                a:1,
                b:1,
                d:{
                    e:2
                }
            }
        },
        //计算属性
        computed: {
            info(){
                return this.isHot ? '炎热' : '凉爽';
            }
        },
        //改变模版数据的方法
        methods:{
            changeWeather(){
                this.isHot = !this.isHot;
            }
        },
        // watch:{
        //     //监视的配置对象
        //     //watch不仅能监视data的普通属性,也可以检测计算属性
        //     isHot:{
        //         immediate: true, //当这个属性为true时,页面刚渲染就运行handler函数
        //         //handler 什么时候调用呢
        //         //当isHot发生改变就会调用该函数
        //         //handler接收两个参数,一个是这个状态参数改变前的值,另一个是改变后的旧值
        //         handler(newValue, preValue){
        //             console.log('ishot 被修改了');
        //             console.log(`newValue: ${newValue}, preValue: ${preValue}`);
        //         }
        //     },
            //深度监视numbers中的所有属性
                numbers:{
                    deep: true, //监视多级结构的属性
                    handler(){
                        console.log('numbers 发生改变')
                    }
                }
        // }
    });
    //watch的第二种写法,直接采用vm对象实例
    vm.$watch('isHot', {
        immediate: true, //当这个属性为true时,页面刚渲染就运行handler函数
        //handler 什么时候调用呢
        //当isHot发生改变就会调用该函数
        //handler接收两个参数,一个是这个状态参数改变前的值,另一个是改变后的旧值
        handler(newValue, preValue){
            console.log('ishot 被修改了');
            console.log(`newValue: ${newValue}, preValue: ${preValue}`);
        }
    });
</script>

绑定样式

  1. class样式
    1. 写法:class=“xxx” xxx可以是字符串、对象、数组
    2. 字符串写法适用于:类名不确定,要动态获取。
    3. 对象写法适用于:要绑定多个样式,个数不确定,名字也不确定
    4. 数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用
  2. style样式
    1. :style="{fontSize: xxx}"其中xxx是动态值。
    2. :style="[a,b]"其中a、b是样式对象。

条件渲染

  1. v-if
    1. 写法:
      (1).v-if=“表达式”
      (2).v-else-if=“表达式”
      (3).v-else=“表达式”
    2. 适用于:切换频率较低的场景。
    3. 特点:不展示的DOM元素直接被移除。
    4. 注意:v-if可以和:v-else-if、v-else一起使用,但要求结构不能被“打断”。
  2. v-show
    1. 写法:v-show=“表达式”
    2. 适用于:切换频率较高的场景
    3. 特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉
  3. 备注:使用v-if的时,元素可能无法获取到,而使用v-show一定可以获取到。

列表渲染

语法:

  • 遍历数组、指定次数

​ v-for=“(item, index) in xxx” :key=“yyy”

  • 遍历对象、字符串

    v-for=“(val, key) of xxx” :key=“yyy”

    v-for=“(c, index) of xxx” :key=“yyy”

  • 在Vue修改数组中的某个元素一定要用如下方法,直接修改的话Vue不监听,模板不改变

    • 使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
    • Vue.set() 或 vm.$set()
    • 原理:
      Vue会监视data中所有层次的数据
      1. 对象中后追加的属性,Vue默认不做响应式处理
      2. 利用vue.set(或者vm. s e t ( ) ) a p i 能够添加的属性变为响应式属性 V u e . s e t ( t a r g e t , p r o p e r t y N a m e / i n d e x , v a l u e ) 或 v m . set())api能够添加的属性变为响应式属性Vue.set(target,propertyName/index,value) 或 vm. set())api能够添加的属性变为响应式属性Vue.set(targetpropertyName/indexvalue)vm.set(target,propertyName/index,value)
      3. 特别注意:Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象 添加属性!!!
methods:{
    updateM(){
        // this.persons[1].name = '马老师';  //奏效
        // this.persons[1].age = 50;      //奏效
        // this.persons[1].sex = '男'; //奏效
        // this.persons[1] = { id: '002', name: '马老师', age: 50, sex:'男' }; //这样修改vue是无法监测数据的
        this.persons.splice(1,1,{ id: '002', name: '马老师', age: 50, sex:'男' });
    },
    addSex(){
    //这里this === vm
    //利用vue.set(或者vm.$set())api能够添加的属性变为响应式属性
    //注意对象不能是 Vue 实例,或者 Vue 实例的根数据对象。
    Vue.set(this.stu, 'sex', '男')
    // this.$set(this.stu, 'sex', '男');
     }
}


“响应式”,是指当数据改变后,Vue 会通知到使用该数据的代码。例如,视图渲染中使用了数据,数据改变后,视图也会自动更新

Vue数据响应式与双向数据绑定原理区分

数据响应式是指通过数据驱动DOM视图的变化,是单向的过程,而双向数据绑定的数据和DOM是一个双向的关系https://blog.csdn.net/forever__fish/article/details/127163227

收集表单数据

  1. 若:,则v-model收集的是value值,用户输入的就是value值。
  2. 若:,则v-model收集的是value值,且要给标签配置value值。
  3. 若:
  4. 没有配置input的value属性,那么收集的就是checked(勾选 or 未勾选,是布尔值)
  5. 配置input的value属性:
    1. v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,是布尔值)
    2. v-model的初始值是数组,那么收集的的就是value组成的数组
  6. 备注:v-model的三个修饰符:
    1. lazy:失去焦点再收集数据
    2. number:输入字符串转为有效的数字
    3. trim:输入首尾空格过滤
<div id="root">
    <form @submit.prevent="demo">
        <!--写了label则点击它也能使指定的input获取焦点 for属性的值为指定元素的id-->
        <label for="demo">账号:</label>
        <!--v-model主要用来双向绑定输入类表单value值-->
        <input type="text" id="demo" v-model.trim="userInfo.account"/>
        <br/>
        密码: <input type="password" v-model="userInfo.password"/>
        <br/>
        性别:
        <!--一组radio单选框的name值一定要相同 设置value值好让v-model去双向绑定-->
        男:<input type="radio" v-model="userInfo.sex" name="sex" value="male"/>
        女:<input type="radio" v-model="userInfo.sex" name="sex" value="female"/>
        <br/>
        年龄: <input type="number" v-model.number="userInfo.age"/>
        <br/>
        爱好:
        <!--如果没有value值则v-model收集checked元素-->
        学习 <input v-model="userInfo.hobby" type="checkbox" value="study"/>
        打游戏 <input v-model="userInfo.hobby" type="checkbox" value="game"/>
        吃饭 <input v-model="userInfo.hobby" type="checkbox" value="eat" />
        <br/>
        所属校区
        <select v-model="userInfo.city">
            <option value="">请选择校区</option>
            <option value="Beijing">北京</option>
            <option value="Shanghai">上海</option>
            <option value="Shenzhen">深圳</option>
            <option value="Wuhan">武汉</option>
        </select>
        <br/>
        其他信息<textarea v-model.lazy="userInfo.other"></textarea>
        <br/>
        <input type="checkbox" v-model="userInfo.ifAgree"/>阅读并接受<a href="https://www.google.com.tw">《用户协议》</a>
        <button>提交数据</button>
    </form>
</div>
<script type="text/javascript">
    Vue.config.productionTip = false;
    const vm = new Vue({
        el: '#root',
        data:{
            userInfo:{
                account: '',
                password: '',
                sex: 'male',
                age:'',
                hobby:[],
                city:'',
                other:'',
                ifAgree:''
            }
        },
        methods:{
            demo(){
                //json转换为string
                console.log(JSON.stringify(this.userInfo));
            }
        }
    })
</script>

生命周期函数

在这里插入图片描述

<script>
export default {
  name: "demo",
  data() {
    return {
      msg: "Welcome to Your Vue.js App",
      msg1: "Welcome to Your Vue.js App1",
    }
  },
  methods: {
    reverseMessage() {
      this.msg = this.msg.split("").reverse().join("")
    }
  },
  computed: {
    fullMessage: function() {
      return this.msg + " " + this.msg
    },
    fullMessage2: {
      get() {
        console.log("get 调用了")
      },
      set(value) {
        console.log("set 调用了");
        this.msg = value.split(" ").slice(0, 1).join("");
      }
    }
  },
  watch: {
    msg(val, oldVal) {
      console.log("watch msg 调用了", val, oldVal)
    },
    msg1:{
      immediate:true,
      deep:true,
      handler(val,oldVal){
        console.log("watch 调用了 msg1", val, oldVal)
      }
    }
  }
}
</script>

非单文件组件

  • Vue.extend() 是vc对象

  • new vue()是vm对象

  • const school = Vue.extend(options) 可简写为:const school = options
    
  • 为组件是可复用的 Vue 实例,所以它们与 new Vue 接收相同的选项,例如 data、computed、watch、methods 以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项。所以vm与vc属性配置并不是一模一样,尽管vc底层复用了很多vm的逻辑

  • 一个重要的内置关系:VueComponent.prototype.proto === Vue.prototype

  • 为什么要有这个关系:让组件实例对象(vc)可以访问到 Vue原型上的属性、方法。

<script type="text/javascript">
    Vue.config.productionTip = false;

    const school = Vue.extend({
        template: `
          <div>
             <h1>学校名称:{{ name }}</h1>
             <h1>学校地址:{{ address }}</h1>
             <button @click="showname">点我提示学校名</button>
          </div>
        `,
        data(){
            return {
                name: '武汉科技大学',  //vuecomponent的实例对象
                address:'武汉'
            }
        },
        methods:{
            showname(){
              console.log(this);
              console.log(this.name);
           }
        }
    });

    // console.log(typeof school, school); //所谓的组件就是构造函数(VueComponent);


    //测试组件
    const test = Vue.extend({
       template:  `<h1>panyue</h1>`
    });

    //hello组件
    const hello = Vue.extend({
        template:`
          <div>
          <h1>{{ msg }}</h1>
          <test></test>
        </div>`,
        data(){
            return {
                msg: '你好'
            }
        },
        components: {
            test
        }
    })


    const vm = new Vue({
        el:"#root",
        components:{
            school,
            hello
        }
    });

    //验证school与hello并不是同一个VueComponent构造函数
    // school.a = 99;
    // console.log('@', school);
    // console.log('#', hello);
    // console.log(school === hello);
    // console.log(school.a, hello.a);
</script>

单文件组件

  • 普通组件School.veu

    • template 写HTML
    • script 创建vc 暴露vc export default {}
    • style 写css
  • App组件 汇总其他组件 components:{School, Student}

  • main.js 创建vm

    //创建vm
    import App from './App';
    //如果文件
    new Vue({
        el: '#root',
        template:`<App></App>`,
        components:{
            App
        }
    });
    
  • index.html 准备root容器

mixin

在这里插入图片描述

Vue脚手架

  • npm install -g @vue/cli
  • vue create xxx
  • 启动项目 npm run serve
  • 打包项目 npm run build

在这里插入图片描述

main.js

入口文件

import {createApp} from 'vue'
import App from './App.vue'
import * as VueRouter from 'vue-router';
import routes from "./config/route";
import Vant from 'vant';
import 'vant/lib/index.css';
import '../global.css'

const app = createApp(App);

const router = VueRouter.createRouter({
    // 内部提供了 history 模式的实现。为了简单起见,我们在这里使用 hash 模式。
    history: VueRouter.createWebHistory(),
    routes, // `routes: routes` 的缩写
})

app.use(Vant);
app.use(router);
app.mount('#app')

App.vue

//vue2
<template>
  <img alt="Vue logo" src="./assets/logo.png">
  <HelloWorld msg="Welcome to Your Vue.js App"/>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'App',
  components: {
    HelloWorld
  }
}
</script>


//vue3
<template>
  <BasicLayout />
</template>

<script setup lang="ts">
import BasicLayout from "./layouts/BasicLayout.vue";
</script>

<template>
  <BasicLayout />
</template>

<style>

</style>

其他组件

<template>
  <van-nav-bar
      :title="title"
      left-arrow
      @click-left="onClickLeft"
      @click-right="onClickRight"
  >
    <template #right>
      <van-icon name="search" size="18"/>
    </template>
  </van-nav-bar>
  <div id="content">
    <router-view/>
  </div>
  <van-tabbar route>
    <van-tabbar-item to="/" icon="home-o" name="index">主页</van-tabbar-item>
    <van-tabbar-item to="/team" icon="search" name="team">队伍</van-tabbar-item>
    <van-tabbar-item to="/user" icon="friends-o" name="user">个人</van-tabbar-item>
  </van-tabbar>
</template>

<script setup lang="ts">
import { useRouter } from "vue-router";
import {ref} from "vue";
import routes from "../config/route";

const router = useRouter();
const DEFAULT_TITLE = '伙伴匹配';
const title = ref(DEFAULT_TITLE);

/**
 * 根据路由切换标题
 */
router.beforeEach((to, from) => {
  const toPath = to.path;
  const route = routes.find((route) => {
    return toPath == route.path;
  })
  title.value = route?.title ?? DEFAULT_TITLE;
})

const onClickLeft = () => {
  router.back();
};

const onClickRight = () => {
  router.push('/search')
};

</script>

<style scoped>
#content {
  padding-bottom: 50px;
}
</style>

ToDoList总结

在这里插入图片描述

vue组件什么是会被销毁

页面关闭、路由跳转、v-if和改变key值

Vuex

在这里插入图片描述

创建store

./src/store/index.js

import {createStore} from "vuex";
import {nanoid} from "nanoid";

const state = {
    todos: JSON.parse(localStorage.getItem('todos')) || []
};

const mutations = {
    saveTodos(state, value) {
        localStorage.setItem('todos', JSON.stringify(value))
    },
    addTodo(state, input) {
        state.todos.unshift({
            id: nanoid(),
            label: input,
            done: false
        })
    },
    allChecked(state, checked){
        for(let i=0;i<state.todos.length;i++){
            state.todos.splice(i,1,{...state.todos[i], done: checked})
        }
    },
    delDone(state){
        console.log("delDone:", state.todos)
        const todoss = state.todos.filter(item => !item.done);

        // 有两个值时,第一个值为删除的位置,第二个值为删除的个数;
        state.todos.splice(0,state.todos.length)
        // 有三个或者多个值时,第一个值为插入元素的位置,第二个值为替换的个数,后面的值都为插入的新元素;
        state.todos.splice(0,todoss.length,...todoss)

    },
    editTodo(state, [id, label]){
        const index = state.todos.findIndex(item => item.id === id);
        state.todos[index].label = label;
    }


};

const getters = {
    done(state) {
        return state.todos.filter(item => item.done).length;
    },
    total(state) {
        return state.todos.length;
    }
};
// 创建一个新的 store 实例
const store = createStore({
    state,
    mutations,
    getters
});

export default store;

使用

main.js

app.use(store);

./src/App.vue

<template>
  <Layout/>
</template>

<script setup>
import { reactive, provide ,watch, getCurrentInstance} from 'vue'
import Layout from "@/components/Layout.vue";
import {nanoid} from 'nanoid';
import { useStore } from 'vuex'

const proxy = getCurrentInstance();
console.log(proxy);

// const readStore = proxy.$store.state.todos;
const store = useStore()
const readStore = store.state.todos;

const todos = reactive(readStore)

watch(todos, (todos, prevTodos) => {
  store.commit('saveTodos', todos)
},{ deep: true })


</script>

<style>

</style>

./src/components/MyFooter.vue

<script setup>
import {ref, inject, getCurrentInstance, watch, computed} from 'vue'
import {useStore, mapGetters} from "vuex";

const store = useStore();
const todos = store.state.todos

// 使用computed保留响应式
const done = computed(()=>{
  return store.getters.done
});
const total = computed(()=>{
  return store.getters.total
})


// const delDone = inject('delDone');

const checked = ref(false)


// const done = ref(todos.filter(item => item.done).length)
// const total = ref(todos.length)
//
// watch(todos,(todos, prevTodos) => {
//     console.log("todos Change", todos);
//     console.log("done", done);
//     console.log("total", total);
//
//     done.value = todos.filter(item => item.done).length;
//     total.value = todos.length;
//
//     },
//     { deep: true }
// )

function allChecked() {

  store.commit("allChecked",checked.value);
  // checked.value =!checked.value;

}
function delDone(){
  store.commit("delDone");
  checked.value = false;
}

</script>

<template>
  <el-row :gutter="5">
    <el-col :span="10" >
      <el-checkbox label="全部完成" @change="allChecked()" v-model="checked"/>
    </el-col>
    <el-col class="mx-0" :span="10" >
      <el-text class="mx-1" size="default">完成情况:{{done}}/{{total}}</el-text>
    </el-col>
    <el-col :span="4">
      <el-button type="danger" size="small" @click="delDone">Del Done</el-button>
    </el-col>
  </el-row>
</template>

<style scoped>

.el-row {
  height: 100%;
  padding: 2px 2px;

}
.el-button{

  font-weight: normal;
  margin: 0 auto;
  width: 100%;
  height: 100%;
  text-align: center;

}
.mx-0 {
  text-align: center;

}

.mx-1 {
  height: 100%;
  width: 100%;
  margin: 0 auto;
}

</style>

使用computed保留getters响应式

// 使用computed保留响应式
const done = computed(()=>{
  return store.getters.done
});
const total = computed(()=>{
  return store.getters.total
})
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 尚硅谷Vue MD笔记是一份非常优秀的学习资料。通过这份笔记,我能够系统地学习和掌握Vue.js框架的核心知识和技能。 首先,Vue MD笔记详细介绍了Vue.js的基本概念和核心特性,包括数据绑定、指令、组件等。通过学习这些基础知识,我能够清楚地理解Vue.js的工作原理和实现机制。 其次,笔记中还提供了大量的实例演示和代码示例,这对我来说非常有帮助。通过这些实例,我能够深入了解Vue.js的使用方法和技巧,同时也可以通过模仿和修改代码来练习和巩固所学的知识。 此外,笔记中还介绍了Vue.js在实际项目中的应用场景和开发经验,这对我在实际开发中的指导非常有帮助。我学会了如何搭建Vue.js项目,如何使用Vue CLI、Vue Router等常用工具和插件,并了解了一些Vue.js的最佳实践和性能优化技巧。 最后,我觉得笔记的编写方式非常清晰和易于理解。它使用了简洁明了的语言,配合大量的图表和示意图,能够很好地帮助我理解和记忆所学的知识点。 总体而言,尚硅谷Vue MD笔记是一份非常宝贵的学习资料。通过学习这份笔记,我能够系统地学习和掌握Vue.js框架的核心知识和技能,并在实际项目中灵活运用。我相信,这份笔记将帮助我成为一名优秀的Vue.js开发者。 ### 回答2: 尚硅谷Vue.md笔记是一份学习Vue框架的笔记资料,它包含了Vue的基本概念、核心特性和使用方法等内容。 这份笔记首先介绍了Vue的起源和背景,简要讲解了Vue是一个响应式的JavaScript框架,能够轻松构建用户界面。接着,笔记详细介绍了Vue中的数据绑定、指令、计算属性、组件化等核心概念和特性。通过学习这些内容,我们可以更好地理解Vue的工作原理和使用方法。 此外,笔记还特别强调了Vue与其他框架的比较和优劣势分析,帮助我们更好地选择适合自己项目的技术栈。同时,笔记中也提供了大量的实例代码和示例,通过实践练习可以更好地掌握Vue的使用。 还有一个关键的特点是笔记的结构清晰、重点突出,对于各个知识点的讲解都较为详细,同时也提供了相关的参考资料和学习资源,方便我们进一步深入学习和扩展。 总之,尚硅谷Vue.md笔记是一份非常有价值的学习资料,对于想要学习Vue框架的开发者来说,它可以帮助我们快速入门和深入学习,并且提供了丰富的实例和相关资源,是一份非常推荐的学习材料。 ### 回答3: 《尚硅谷Vue.md笔记》是一本关于Vue.js技术的学习笔记,内容丰富全面。本书主要包含了Vue.js的基础知识、进阶技巧和实战项目等方面的内容。 首先,本书的前部分介绍了Vue.js的基本概念和核心特性,如数据绑定、指令、组件、路由等。通过对这些知识点的深入讲解,读者可以很好地理解Vue.js的设计原理和运行机制。 其次,本书的中部内容涵盖了Vue.js的进阶技巧和最佳实践。作者通过实例代码和详细的讲解,介绍了Vue.js的高级特性和常用的组件开发方法。此外,还介绍了一些优化和调试技巧,帮助读者提升Vue.js应用的性能和开发效率。 最后,本书的后部分是一些实战项目,作者通过开发一些常见的网页应用,如购物车、音乐播放器等,来帮助读者巩固所学的Vue.js知识。通过实践,读者能够学会如何将Vue.js应用到实际项目中,并了解如何解决实际开发中遇到的问题。 总体来说,本书不仅系统地介绍了Vue.js的核心概念和基本用法,还通过丰富的实例和实战项目,帮助读者更好地理解和应用所学的知识。对于想要学习Vue.js的初学者和有一定经验的开发者来说,这本书是一份优秀的学习资料。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值